Snap for 7519874 from b6cdd12394 to sc-release
Change-Id: Ib05998ed7e4d75d856bd331d9497bd4270066fbe
This commit is contained in:
@@ -96,7 +96,8 @@ const char kUsageInfoFileNameExt[] = ".bin";
|
|||||||
const char kUsageInfoFileNamePrefix[] = "usage";
|
const char kUsageInfoFileNamePrefix[] = "usage";
|
||||||
const char kUsageTableFileName[] = "usgtable.bin";
|
const char kUsageTableFileName[] = "usgtable.bin";
|
||||||
const char kWildcard[] = "*";
|
const char kWildcard[] = "*";
|
||||||
constexpr int64_t kFourMonthsInSeconds = (2 * 30 + 2 * 31) * 24 * 60 * 60;
|
// TODO(b/192430982): Renable expiration of legacy DRM certificates
|
||||||
|
// constexpr int64_t kFourMonthsInSeconds = (2 * 30 + 2 * 31) * 24 * 60 * 60;
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
bool SetDeviceCertificate(const std::string& certificate,
|
bool SetDeviceCertificate(const std::string& certificate,
|
||||||
@@ -427,7 +428,9 @@ bool DeviceFiles::StoreCertificate(const std::string& certificate,
|
|||||||
if (default_certificate) {
|
if (default_certificate) {
|
||||||
Clock clock;
|
Clock clock;
|
||||||
device_certificate->set_acquisition_time_seconds(clock.GetCurrentTime());
|
device_certificate->set_acquisition_time_seconds(clock.GetCurrentTime());
|
||||||
} else {
|
}
|
||||||
|
/* TODO(b/192430982): Renable expiration of legacy DRM certificates
|
||||||
|
else {
|
||||||
// Since certificates of type kCertificateAtsc are not allowed to be
|
// Since certificates of type kCertificateAtsc are not allowed to be
|
||||||
// stored, this is a certificate of type kCertificateLegacy.
|
// stored, this is a certificate of type kCertificateLegacy.
|
||||||
// The only time when a legacy certificate is stored is when it does not
|
// The only time when a legacy certificate is stored is when it does not
|
||||||
@@ -440,6 +443,7 @@ bool DeviceFiles::StoreCertificate(const std::string& certificate,
|
|||||||
current_time + kFourMonthsInSeconds +
|
current_time + kFourMonthsInSeconds +
|
||||||
rng.RandomInRange(kFourMonthsInSeconds));
|
rng.RandomInRange(kFourMonthsInSeconds));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
std::string serialized_file;
|
std::string serialized_file;
|
||||||
file.SerializeToString(&serialized_file);
|
file.SerializeToString(&serialized_file);
|
||||||
@@ -595,6 +599,7 @@ DeviceFiles::CertificateState DeviceFiles::RetrieveCertificate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
case kCertificateLegacy: {
|
case kCertificateLegacy: {
|
||||||
|
/* TODO(b/192430982): Renable expiration of legacy DRM certificates
|
||||||
// Validation check for DRM certificate without an expiration
|
// Validation check for DRM certificate without an expiration
|
||||||
// time set by the provisioning service. Add an expiry time
|
// time set by the provisioning service. Add an expiry time
|
||||||
// within the next 6 months +/- 2 months, if one has not been set.
|
// within the next 6 months +/- 2 months, if one has not been set.
|
||||||
@@ -611,6 +616,7 @@ DeviceFiles::CertificateState DeviceFiles::RetrieveCertificate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (current_time > expiration_time_seconds) return kCertificateExpired;
|
if (current_time > expiration_time_seconds) return kCertificateExpired;
|
||||||
|
*/
|
||||||
|
|
||||||
return kCertificateValid;
|
return kCertificateValid;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1568,8 +1568,10 @@ const CertificateErrorData kRetrieveLegacyCertificateErrorData[] = {
|
|||||||
kTestLegacyCertificateFileDataInvalidClientExpiration},
|
kTestLegacyCertificateFileDataInvalidClientExpiration},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* TODO(b/192430982): Renable expiration of legacy DRM certificates
|
||||||
constexpr size_t kNumberOfLegacyCertificates =
|
constexpr size_t kNumberOfLegacyCertificates =
|
||||||
ArraySize(kRetrieveLegacyCertificateErrorData);
|
ArraySize(kRetrieveLegacyCertificateErrorData);
|
||||||
|
*/
|
||||||
|
|
||||||
const CertificateErrorData kRetrieveDefaultCertificateErrorData[] = {
|
const CertificateErrorData kRetrieveDefaultCertificateErrorData[] = {
|
||||||
// Certificate expired
|
// Certificate expired
|
||||||
@@ -4020,6 +4022,7 @@ TEST_F(DeviceFilesTest, RetrieveAtscCertificateNotFound) {
|
|||||||
&serial_number, &system_id));
|
&serial_number, &system_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO(b/192430982): Renable expiration of legacy DRM certificates
|
||||||
TEST_F(DeviceFilesTest, RetrieveLegacyCertificateWithoutExpirationTime) {
|
TEST_F(DeviceFilesTest, RetrieveLegacyCertificateWithoutExpirationTime) {
|
||||||
MockFileSystem file_system;
|
MockFileSystem file_system;
|
||||||
std::string certificate_file_name;
|
std::string certificate_file_name;
|
||||||
@@ -4221,6 +4224,7 @@ TEST_F(DeviceFilesTest, RetrieveDefaultCertificate) {
|
|||||||
EXPECT_EQ(kTestWrappedKey, private_key);
|
EXPECT_EQ(kTestWrappedKey, private_key);
|
||||||
EXPECT_EQ("7CB49F987A635E1E0A52184694582D6E", b2a_hex(serial_number));
|
EXPECT_EQ("7CB49F987A635E1E0A52184694582D6E", b2a_hex(serial_number));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
TEST_F(DeviceFilesTest, RetrieveDefaultCertificateNeverExpires) {
|
TEST_F(DeviceFilesTest, RetrieveDefaultCertificateNeverExpires) {
|
||||||
MockFileSystem file_system;
|
MockFileSystem file_system;
|
||||||
@@ -4331,7 +4335,9 @@ TEST_F(DeviceFilesTest, RetrieveCertificateWithoutKeyType) {
|
|||||||
// Call to Open will return a unique_ptr, freeing this object.
|
// Call to Open will return a unique_ptr, freeing this object.
|
||||||
// The file will be re-written with a new client expiration time
|
// The file will be re-written with a new client expiration time
|
||||||
MockFile* read_file = new MockFile();
|
MockFile* read_file = new MockFile();
|
||||||
|
/* TODO(b/192430982): Renable expiration of legacy DRM certificates
|
||||||
MockFile* write_file = new MockFile();
|
MockFile* write_file = new MockFile();
|
||||||
|
*/
|
||||||
EXPECT_CALL(file_system, Exists(StrEq(device_legacy_certificate_path)))
|
EXPECT_CALL(file_system, Exists(StrEq(device_legacy_certificate_path)))
|
||||||
.Times(AtLeast(1))
|
.Times(AtLeast(1))
|
||||||
.WillRepeatedly(Return(true));
|
.WillRepeatedly(Return(true));
|
||||||
@@ -4341,17 +4347,21 @@ TEST_F(DeviceFilesTest, RetrieveCertificateWithoutKeyType) {
|
|||||||
EXPECT_CALL(file_system, FileSize(StrEq(device_legacy_certificate_path)))
|
EXPECT_CALL(file_system, FileSize(StrEq(device_legacy_certificate_path)))
|
||||||
.WillOnce(Return(data.size()));
|
.WillOnce(Return(data.size()));
|
||||||
EXPECT_CALL(file_system, DoOpen(StrEq(device_legacy_certificate_path), _))
|
EXPECT_CALL(file_system, DoOpen(StrEq(device_legacy_certificate_path), _))
|
||||||
.WillOnce(Return(read_file))
|
.WillOnce(Return(read_file));
|
||||||
.WillOnce(Return(write_file));
|
/* TODO(b/192430982): Renable expiration of legacy DRM certificates
|
||||||
|
.WillOnce(Return(write_file));
|
||||||
|
*/
|
||||||
EXPECT_CALL(*read_file, Read(NotNull(), Eq(data.size())))
|
EXPECT_CALL(*read_file, Read(NotNull(), Eq(data.size())))
|
||||||
.WillOnce(DoAll(SetArrayArgument<0>(data.begin(), data.end()),
|
.WillOnce(DoAll(SetArrayArgument<0>(data.begin(), data.end()),
|
||||||
Return(data.size())));
|
Return(data.size())));
|
||||||
EXPECT_CALL(*read_file, Write(_, _)).Times(0);
|
EXPECT_CALL(*read_file, Write(_, _)).Times(0);
|
||||||
|
/* TODO(b/192430982): Renable expiration of legacy DRM certificates
|
||||||
EXPECT_CALL(*write_file, Read(_, _)).Times(0);
|
EXPECT_CALL(*write_file, Read(_, _)).Times(0);
|
||||||
EXPECT_CALL(*write_file, Write(_, _))
|
EXPECT_CALL(*write_file, Write(_, _))
|
||||||
.With(AllArgs(StrAndLenContains(std::vector<std::string>{
|
.With(AllArgs(StrAndLenContains(std::vector<std::string>{
|
||||||
kTestCertificateWithoutExpiration, kTestWrappedKey.key()})))
|
kTestCertificateWithoutExpiration, kTestWrappedKey.key()})))
|
||||||
.WillOnce(ReturnArg<1>());
|
.WillOnce(ReturnArg<1>());
|
||||||
|
*/
|
||||||
|
|
||||||
DeviceFiles device_files(&file_system);
|
DeviceFiles device_files(&file_system);
|
||||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||||
|
|||||||
@@ -215,6 +215,14 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
|||||||
void DisableTimerAndWaitForExit();
|
void DisableTimerAndWaitForExit();
|
||||||
void OnTimerEvent();
|
void OnTimerEvent();
|
||||||
|
|
||||||
|
// Fill the |metrics| parameter with the metrics data for the CdmEngine
|
||||||
|
// associated with the given |identifier|. If the CdmEngine instance does
|
||||||
|
// not exist, this will return an error.
|
||||||
|
// This methods assumes that |metrics| is not null and that the |cdms_lock_|
|
||||||
|
// has already been acquired.
|
||||||
|
CdmResponseType GetMetricsInternal(const CdmIdentifier& identifier,
|
||||||
|
drm_metrics::WvCdmMetrics* metrics);
|
||||||
|
|
||||||
static std::mutex session_sharing_id_generation_lock_;
|
static std::mutex session_sharing_id_generation_lock_;
|
||||||
std::mutex timer_lock_;
|
std::mutex timer_lock_;
|
||||||
Timer timer_;
|
Timer timer_;
|
||||||
@@ -222,14 +230,27 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
|||||||
// instance variables
|
// instance variables
|
||||||
// This manages the lifetime of the CDM instances.
|
// This manages the lifetime of the CDM instances.
|
||||||
std::map<CdmIdentifier, CdmInfo> cdms_;
|
std::map<CdmIdentifier, CdmInfo> cdms_;
|
||||||
std::mutex cdms_lock_;
|
|
||||||
|
|
||||||
// This contains weak pointers to the CDM instances contained in |cdms_|.
|
// This contains weak pointers to the CDM instances contained in |cdms_|.
|
||||||
std::map<std::string, CdmEngine*> cdm_by_session_id_;
|
std::map<std::string, CdmEngine*> cdm_by_session_id_;
|
||||||
|
// Lock for accessing either |cdms_| or |cdm_by_session_id_|.
|
||||||
|
// This lock should be acquired for any of the following:
|
||||||
|
// 1) Getting a CDM instance from |cdms_| or |cdm_by_session_id_|
|
||||||
|
// - Hold lock while searching, release lock once pointer is acquired
|
||||||
|
// 2) Iterating over |cdms_| or |cdm_by_session_id_|
|
||||||
|
// - Hold lock for the entire duration of iterating over CDMs
|
||||||
|
// - DO NOT release the lock until all operations are complete
|
||||||
|
// - This MUST be done regardless of whether |cdms_| or
|
||||||
|
// |cdm_by_session_id_| is being modified
|
||||||
|
// 3) Creating a new CDM instance with |cdms_|
|
||||||
|
// - Hold lock when creating AND initializing the CDM
|
||||||
|
// - Release once CDM is fully initialized
|
||||||
|
// 4) Linking a session to a CDM with |cdm_by_session_id_|
|
||||||
|
// - Hold lock when mapping a session ID to a CDM, release once set
|
||||||
|
// 5) Unlinking a session from a CDM with |cdm_by_session_id_|
|
||||||
|
// - Hold lock when erasing, release once erased.
|
||||||
|
std::mutex cdms_lock_;
|
||||||
|
|
||||||
CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule);
|
CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_WV_CONTENT_DECRYPTION_MODULE_H_
|
#endif // CDM_BASE_WV_CONTENT_DECRYPTION_MODULE_H_
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ CdmResponseType WvContentDecryptionModule::OpenSession(
|
|||||||
CdmResponseType sts = cdm_engine->OpenSession(key_system, property_set,
|
CdmResponseType sts = cdm_engine->OpenSession(key_system, property_set,
|
||||||
event_listener, session_id);
|
event_listener, session_id);
|
||||||
if (sts == NO_ERROR) {
|
if (sts == NO_ERROR) {
|
||||||
|
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||||
cdm_by_session_id_[*session_id] = cdm_engine;
|
cdm_by_session_id_[*session_id] = cdm_engine;
|
||||||
}
|
}
|
||||||
return sts;
|
return sts;
|
||||||
@@ -82,12 +83,11 @@ CdmResponseType WvContentDecryptionModule::CloseSession(
|
|||||||
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
|
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
|
||||||
// TODO(rfrias): Avoid reusing the error codes from CdmEngine.
|
// TODO(rfrias): Avoid reusing the error codes from CdmEngine.
|
||||||
if (!cdm_engine) return SESSION_NOT_FOUND_1;
|
if (!cdm_engine) return SESSION_NOT_FOUND_1;
|
||||||
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
const CdmResponseType sts = cdm_engine->CloseSession(session_id);
|
||||||
CdmResponseType sts = cdm_engine->CloseSession(session_id);
|
|
||||||
if (sts == NO_ERROR) {
|
if (sts == NO_ERROR) {
|
||||||
|
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||||
cdm_by_session_id_.erase(session_id);
|
cdm_by_session_id_.erase(session_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sts;
|
return sts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +107,7 @@ CdmResponseType WvContentDecryptionModule::GenerateKeyRequest(
|
|||||||
if (license_type == kLicenseTypeRelease) {
|
if (license_type == kLicenseTypeRelease) {
|
||||||
sts = cdm_engine->OpenKeySetSession(key_set_id, property_set, nullptr);
|
sts = cdm_engine->OpenKeySetSession(key_set_id, property_set, nullptr);
|
||||||
if (sts != NO_ERROR) return sts;
|
if (sts != NO_ERROR) return sts;
|
||||||
|
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||||
cdm_by_session_id_[key_set_id] = cdm_engine;
|
cdm_by_session_id_[key_set_id] = cdm_engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +131,7 @@ CdmResponseType WvContentDecryptionModule::GenerateKeyRequest(
|
|||||||
app_parameters, key_request);
|
app_parameters, key_request);
|
||||||
if (license_type == kLicenseTypeRelease && sts != KEY_MESSAGE) {
|
if (license_type == kLicenseTypeRelease && sts != KEY_MESSAGE) {
|
||||||
cdm_engine->CloseKeySetSession(key_set_id);
|
cdm_engine->CloseKeySetSession(key_set_id);
|
||||||
|
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||||
cdm_by_session_id_.erase(key_set_id);
|
cdm_by_session_id_.erase(key_set_id);
|
||||||
}
|
}
|
||||||
return sts;
|
return sts;
|
||||||
@@ -152,6 +154,7 @@ CdmResponseType WvContentDecryptionModule::AddKey(
|
|||||||
// Empty session id indicates license type release.
|
// Empty session id indicates license type release.
|
||||||
if (sts == KEY_ADDED && session_id.empty()) {
|
if (sts == KEY_ADDED && session_id.empty()) {
|
||||||
cdm_engine->CloseKeySetSession(release_key_set_id);
|
cdm_engine->CloseKeySetSession(release_key_set_id);
|
||||||
|
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||||
cdm_by_session_id_.erase(release_key_set_id);
|
cdm_by_session_id_.erase(release_key_set_id);
|
||||||
}
|
}
|
||||||
return sts;
|
return sts;
|
||||||
@@ -297,11 +300,11 @@ CdmResponseType WvContentDecryptionModule::GetSecureStopIds(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
||||||
CdmResponseType sts =
|
const CdmResponseType sts =
|
||||||
cdm_engine->ListUsageIds(app_id, kSecurityLevelL1, nullptr, ssids);
|
cdm_engine->ListUsageIds(app_id, kSecurityLevelL1, nullptr, ssids);
|
||||||
std::vector<CdmSecureStopId> secure_stop_ids;
|
std::vector<CdmSecureStopId> secure_stop_ids;
|
||||||
CdmResponseType sts_l3 = cdm_engine->ListUsageIds(app_id, kSecurityLevelL3,
|
const CdmResponseType sts_l3 = cdm_engine->ListUsageIds(
|
||||||
nullptr, &secure_stop_ids);
|
app_id, kSecurityLevelL3, nullptr, &secure_stop_ids);
|
||||||
ssids->insert(ssids->end(), secure_stop_ids.begin(), secure_stop_ids.end());
|
ssids->insert(ssids->end(), secure_stop_ids.begin(), secure_stop_ids.end());
|
||||||
return sts_l3 != NO_ERROR ? sts_l3 : sts;
|
return sts_l3 != NO_ERROR ? sts_l3 : sts;
|
||||||
}
|
}
|
||||||
@@ -383,17 +386,19 @@ CdmResponseType WvContentDecryptionModule::GetMetrics(
|
|||||||
if (!metrics || !full_list_returned) {
|
if (!metrics || !full_list_returned) {
|
||||||
return PARAMETER_NULL;
|
return PARAMETER_NULL;
|
||||||
}
|
}
|
||||||
|
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||||
for (auto& key_value_pair : cdms_) {
|
for (auto& key_value_pair : cdms_) {
|
||||||
|
const CdmIdentifier& identifier = key_value_pair.first;
|
||||||
drm_metrics::WvCdmMetrics metric;
|
drm_metrics::WvCdmMetrics metric;
|
||||||
CdmResponseType status = GetMetrics(key_value_pair.first, &metric);
|
const CdmResponseType status = GetMetricsInternal(identifier, &metric);
|
||||||
if (status == NO_ERROR) {
|
if (status == NO_ERROR) {
|
||||||
metrics->push_back(metric);
|
metrics->push_back(metric);
|
||||||
} else {
|
} else {
|
||||||
LOGD("GetMetrics call failed: cdm identifier=%u, error=%d",
|
LOGD("GetMetrics call failed: cdm identifier=%u, error=%d",
|
||||||
key_value_pair.first.unique_id, status);
|
identifier.unique_id, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// With no streaming activities, cdms_ size would be zero,
|
// With no streaming activities, |cdms_| size would be zero,
|
||||||
// treat it as a non full list in that case.
|
// treat it as a non full list in that case.
|
||||||
*full_list_returned = !cdms_.empty() && metrics->size() == cdms_.size();
|
*full_list_returned = !cdms_.empty() && metrics->size() == cdms_.size();
|
||||||
|
|
||||||
@@ -410,6 +415,12 @@ CdmResponseType WvContentDecryptionModule::GetMetrics(
|
|||||||
return PARAMETER_NULL;
|
return PARAMETER_NULL;
|
||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||||
|
return GetMetricsInternal(identifier, metrics);
|
||||||
|
}
|
||||||
|
|
||||||
|
CdmResponseType WvContentDecryptionModule::GetMetricsInternal(
|
||||||
|
const CdmIdentifier& identifier, drm_metrics::WvCdmMetrics* metrics) {
|
||||||
|
// Note: Caller should lock before calling.
|
||||||
auto it = cdms_.find(identifier);
|
auto it = cdms_.find(identifier);
|
||||||
if (it == cdms_.end()) {
|
if (it == cdms_.end()) {
|
||||||
LOGE("Cdm Identifier not found");
|
LOGE("Cdm Identifier not found");
|
||||||
@@ -454,6 +465,7 @@ CdmEngine* WvContentDecryptionModule::EnsureCdmForIdentifier(
|
|||||||
|
|
||||||
CdmEngine* WvContentDecryptionModule::GetCdmForSessionId(
|
CdmEngine* WvContentDecryptionModule::GetCdmForSessionId(
|
||||||
const std::string& session_id) {
|
const std::string& session_id) {
|
||||||
|
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||||
// Use find to avoid creating empty entries when not found.
|
// Use find to avoid creating empty entries when not found.
|
||||||
auto it = cdm_by_session_id_.find(session_id);
|
auto it = cdm_by_session_id_.find(session_id);
|
||||||
if (it == cdm_by_session_id_.end()) return nullptr;
|
if (it == cdm_by_session_id_.end()) return nullptr;
|
||||||
@@ -462,10 +474,8 @@ CdmEngine* WvContentDecryptionModule::GetCdmForSessionId(
|
|||||||
|
|
||||||
void WvContentDecryptionModule::CloseAllCdms() {
|
void WvContentDecryptionModule::CloseAllCdms() {
|
||||||
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||||
|
cdm_by_session_id_.clear();
|
||||||
for (auto it = cdms_.begin(); it != cdms_.end();) {
|
cdms_.clear();
|
||||||
it = cdms_.erase(it);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType WvContentDecryptionModule::CloseCdm(
|
CdmResponseType WvContentDecryptionModule::CloseCdm(
|
||||||
|
|||||||
Reference in New Issue
Block a user