Merge "Revert "Create unique cdm engines per WVDrmPlugin instance"" into pi-dev

This commit is contained in:
TreeHugger Robot
2018-04-05 20:03:26 +00:00
committed by Android (Google) Code Review
11 changed files with 198 additions and 338 deletions

View File

@@ -30,28 +30,12 @@ struct CdmIdentifier {
// provide a friendly name of the application package for the purposes of // provide a friendly name of the application package for the purposes of
// logging and metrics. // logging and metrics.
std::string app_package_name; std::string app_package_name;
// The unique identifier guarantees that no two identifiers share the same
// CdmEngine instance. We're moving to a model where a plugin maps 1 to 1
// with a CdmEngine instance. This is a simple way to implement that.
uint32_t unique_id;
// This method is needed to check to see if the identifier is equivalent
// to the default cdm. E.g. no spoid, origin or app package name. Use this
// comparison in lieu of the == operator when checking to see if the
// identifier would cause the default provisioned certificate to be used.
bool IsEquivalentToDefault() {
return spoid == EMPTY_SPOID
&& origin == EMPTY_ORIGIN
&& app_package_name == EMPTY_APP_PACKAGE_NAME;
}
}; };
// Provide comparison operators // Provide comparison operators
inline bool operator==(const CdmIdentifier& lhs, const CdmIdentifier& rhs) { inline bool operator==(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
return lhs.spoid == rhs.spoid && lhs.origin == rhs.origin return lhs.spoid == rhs.spoid && lhs.origin == rhs.origin
&& lhs.app_package_name == rhs.app_package_name && lhs.app_package_name == rhs.app_package_name;
&& lhs.unique_id == rhs.unique_id;
} }
inline bool operator!=(const CdmIdentifier& lhs, const CdmIdentifier& rhs) { inline bool operator!=(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
@@ -63,9 +47,7 @@ inline bool operator<(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
|| ((lhs.spoid == rhs.spoid) || ((lhs.spoid == rhs.spoid)
&& (lhs.origin < rhs.origin && (lhs.origin < rhs.origin
|| (lhs.origin == rhs.origin || (lhs.origin == rhs.origin
&& (lhs.app_package_name < rhs.app_package_name && lhs.app_package_name < rhs.app_package_name)));
|| (lhs.app_package_name == rhs.app_package_name
&& lhs.unique_id < rhs.unique_id)))));
} }
inline bool operator>(const CdmIdentifier& lhs, const CdmIdentifier& rhs) { inline bool operator>(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
@@ -84,8 +66,7 @@ inline bool operator>=(const CdmIdentifier& lhs, const CdmIdentifier& rhs) {
static const CdmIdentifier kDefaultCdmIdentifier = { static const CdmIdentifier kDefaultCdmIdentifier = {
EMPTY_SPOID, EMPTY_SPOID,
EMPTY_ORIGIN, EMPTY_ORIGIN,
EMPTY_APP_PACKAGE_NAME, EMPTY_APP_PACKAGE_NAME
0
}; };
} // namespace wvcdm } // namespace wvcdm

View File

@@ -127,14 +127,9 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
// Validate a passed-in service certificate // Validate a passed-in service certificate
virtual bool IsValidServiceCertificate(const std::string& certificate); virtual bool IsValidServiceCertificate(const std::string& certificate);
// Fill the metrics parameter with the metrics data for the CdmEngine // Retrieve the serialized metrics from CdmEngine and CdmSession instances
// associated with the given CdmIdentifier. If the CdmEngine instance does // that have been closed.
// not exist, this will return an error. virtual void GetSerializedMetrics(std::string* serialized_metrics);
virtual CdmResponseType GetMetrics(const CdmIdentifier& identifier,
drm_metrics::WvCdmMetrics* metrics);
// Closes the CdmEngine and sessions associated with the given CdmIdentifier.
virtual CdmResponseType CloseCdm(const CdmIdentifier& identifier);
private: private:
struct CdmInfo { struct CdmInfo {
@@ -150,10 +145,10 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
// Finds the CdmEngine instance for the given session id, returning NULL if // Finds the CdmEngine instance for the given session id, returning NULL if
// not found. // not found.
CdmEngine* GetCdmForSessionId(const std::string& session_id); CdmEngine* GetCdmForSessionId(const std::string& session_id);
// Closes CdmEngine instances that don't have any open sessions. Also stores
// Close all of the open CdmEngine instances. This is used when ready to close // metrics data for closed CdmEngine instances.
// the WvContentDecryptionModule instance. // Callers must acquire the cdms_lock_ before calling this method.
void CloseAllCdms(); void CloseCdmsWithoutSessions();
uint32_t GenerateSessionSharingId(); uint32_t GenerateSessionSharingId();
@@ -175,6 +170,9 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
// 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_;
// The metrics for cdm engines and sessions that have been closed.
drm_metrics::WvCdmMetricsGroup metrics_group_;
CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule); CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule);
}; };

View File

@@ -24,7 +24,6 @@ Lock WvContentDecryptionModule::session_sharing_id_generation_lock_;
WvContentDecryptionModule::WvContentDecryptionModule() {} WvContentDecryptionModule::WvContentDecryptionModule() {}
WvContentDecryptionModule::~WvContentDecryptionModule() { WvContentDecryptionModule::~WvContentDecryptionModule() {
CloseAllCdms();
ForceDisablePolicyTimer(); ForceDisablePolicyTimer();
} }
@@ -76,6 +75,8 @@ CdmResponseType WvContentDecryptionModule::CloseSession(
cdm_by_session_id_.erase(session_id); cdm_by_session_id_.erase(session_id);
} }
DisablePolicyTimer();
return sts; return sts;
} }
@@ -329,21 +330,12 @@ bool WvContentDecryptionModule::IsValidServiceCertificate(
return cert.has_certificate(); return cert.has_certificate();
} }
void WvContentDecryptionModule::GetSerializedMetrics(
CdmResponseType WvContentDecryptionModule::GetMetrics( std::string* serialized_metrics) {
const CdmIdentifier& identifier, drm_metrics::WvCdmMetrics* metrics) {
if (!metrics) {
return PARAMETER_NULL;
}
AutoLock auto_lock(cdms_lock_); AutoLock auto_lock(cdms_lock_);
auto it = cdms_.find(identifier); CloseCdmsWithoutSessions();
if (it == cdms_.end()) { metrics_group_.SerializeToString(serialized_metrics);
LOGE("WVContentDecryptionModule::Close. cdm_identifier not found"); metrics_group_.Clear();
// TODO(blueeyes): Add a better error.
return UNKNOWN_ERROR;
}
it->second.cdm_engine->GetMetrics()->Serialize(metrics);
return NO_ERROR;
} }
WvContentDecryptionModule::CdmInfo::CdmInfo() WvContentDecryptionModule::CdmInfo::CdmInfo()
@@ -379,26 +371,30 @@ CdmEngine* WvContentDecryptionModule::GetCdmForSessionId(
return it->second; return it->second;
} }
void WvContentDecryptionModule::CloseAllCdms() { // This method requires that the caller first acquire cdms_lock_.
AutoLock auto_lock(cdms_lock_); void WvContentDecryptionModule::CloseCdmsWithoutSessions() {
for (auto it = cdms_.begin(); it != cdms_.end();) { for (auto it = cdms_.begin(); it != cdms_.end();) {
it = cdms_.erase(it); if (it->second.cdm_engine->SessionSize() != 0) {
} ++it;
} } else {
// Retrieve the metrics from the engine and any completed
// sessions. Clear the metrics from any completed sessions.
metrics::EngineMetrics* engine_metrics =
it->second.cdm_engine->GetMetrics();
// engine_metrics should never be null.
if (engine_metrics != NULL) {
engine_metrics->Serialize(metrics_group_.add_metrics());
} else {
// Engine metrics should never be null.
LOGI(
"WvContentDecryptionModule::CloseCdmsWithoutSessions."
"engine_metrics was unexpectedly NULL.");
}
CdmResponseType WvContentDecryptionModule::CloseCdm( // The CDM is no longer used for this identifier, delete it.
const CdmIdentifier& cdm_identifier) { it = cdms_.erase(it);
AutoLock auto_lock(cdms_lock_); }
auto it = cdms_.find(cdm_identifier);
if (it == cdms_.end()) {
LOGE("WVContentDecryptionModule::Close. cdm_identifier not found");
// TODO(blueeyes): Create a better error.
return UNKNOWN_ERROR;
} }
cdms_.erase(it);
DisablePolicyTimer();
return NO_ERROR;
} }
void WvContentDecryptionModule::EnablePolicyTimer() { void WvContentDecryptionModule::EnablePolicyTimer() {
@@ -407,16 +403,28 @@ void WvContentDecryptionModule::EnablePolicyTimer() {
policy_timer_.Start(this, kCdmPolicyTimerDurationSeconds); policy_timer_.Start(this, kCdmPolicyTimerDurationSeconds);
} }
// This implementation assumes that the caller has already acquired the
// cdms_lock_.
void WvContentDecryptionModule::DisablePolicyTimer() { void WvContentDecryptionModule::DisablePolicyTimer() {
bool cdms_is_empty = false;
{
AutoLock auto_lock(cdms_lock_);
CloseCdmsWithoutSessions();
cdms_is_empty = cdms_.empty();
}
AutoLock auto_lock(policy_timer_lock_); AutoLock auto_lock(policy_timer_lock_);
if (cdms_.empty() && policy_timer_.IsRunning()) { if (cdms_is_empty) {
policy_timer_.Stop(); if (policy_timer_.IsRunning()) {
policy_timer_.Stop();
}
} }
} }
void WvContentDecryptionModule::ForceDisablePolicyTimer() { void WvContentDecryptionModule::ForceDisablePolicyTimer() {
{
AutoLock auto_lock(cdms_lock_);
CloseCdmsWithoutSessions();
}
AutoLock auto_lock(policy_timer_lock_); AutoLock auto_lock(policy_timer_lock_);
if (policy_timer_.IsRunning()) { if (policy_timer_.IsRunning()) {
policy_timer_.Stop(); policy_timer_.Stop();

View File

@@ -605,21 +605,24 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
EXPECT_TRUE(license_renewal.has_key_control_nonce()); EXPECT_TRUE(license_renewal.has_key_control_nonce());
} }
void ValidateHasUpdateUsageEntry(const drm_metrics::WvCdmMetrics& metrics) void ValidateHasUpdateUsageEntry(const std::string& serialized_metrics)
const { const {
drm_metrics::WvCdmMetricsGroup group;
ASSERT_TRUE(group.ParseFromString(serialized_metrics));
bool has_update_usage_entry_metrics = false; bool has_update_usage_entry_metrics = false;
for (const auto& session : metrics.session_metrics()) { for (const auto& metrics : group.metrics()) {
has_update_usage_entry_metrics |= for (const auto& session : metrics.session_metrics()) {
session.crypto_metrics() has_update_usage_entry_metrics |=
.crypto_session_update_usage_entry_time_us().size() > 0; session.crypto_metrics()
has_update_usage_entry_metrics |= .crypto_session_update_usage_entry_time_us().size() > 0;
session.crypto_metrics().oemcrypto_update_usage_entry().size() > 0; has_update_usage_entry_metrics |=
session.crypto_metrics().oemcrypto_update_usage_entry().size() > 0;
}
} }
std::string serialized_metrics;
ASSERT_TRUE(metrics.SerializeToString(&serialized_metrics));
EXPECT_TRUE(has_update_usage_entry_metrics) EXPECT_TRUE(has_update_usage_entry_metrics)
<< "metrics: " << wvcdm::b2a_hex(serialized_metrics); << "metrics: " << wvcdm::b2a_hex(serialized_metrics);
} }
void QueryKeyStatus(bool streaming, bool expect_renewal, void QueryKeyStatus(bool streaming, bool expect_renewal,
@@ -1449,9 +1452,9 @@ TEST_P(WvCdmStreamingUsageReportTest, UsageTest) {
} }
// Validate that update usage table entry is exercised. // Validate that update usage table entry is exercised.
drm_metrics::WvCdmMetrics metrics; std::string serialized_metrics;
ASSERT_EQ(NO_ERROR, decryptor_.GetMetrics(kDefaultCdmIdentifier, &metrics)); decryptor_.GetSerializedMetrics(&serialized_metrics);
ValidateHasUpdateUsageEntry(metrics); ValidateHasUpdateUsageEntry(serialized_metrics);
} }
INSTANTIATE_TEST_CASE_P(Cdm, WvCdmStreamingUsageReportTest, INSTANTIATE_TEST_CASE_P(Cdm, WvCdmStreamingUsageReportTest,

View File

@@ -51,8 +51,7 @@ const int kHttpInternalServerError = 500;
const wvcdm::CdmIdentifier kExampleIdentifier = { const wvcdm::CdmIdentifier kExampleIdentifier = {
wvcdm::EMPTY_SPOID, wvcdm::EMPTY_SPOID,
"com.example", "com.example",
"com.example", "com.example"
7
}; };
// Protobuf generated classes // Protobuf generated classes
@@ -393,19 +392,15 @@ const uint32_t kSingleEncryptedSubSampleIcpLicenseExpirationWindow = 2;
struct SessionSharingSubSampleInfo { struct SessionSharingSubSampleInfo {
SubSampleInfo* sub_sample; SubSampleInfo* sub_sample;
bool session_sharing_enabled; bool session_sharing_enabled;
wvcdm::CdmIdentifier cdm_identifier;
}; };
SessionSharingSubSampleInfo session_sharing_sub_samples[] = { SessionSharingSubSampleInfo session_sharing_sub_samples[] = {
{&clear_sub_sample, false, wvcdm::kDefaultCdmIdentifier}, {&clear_sub_sample, false},
{&clear_sub_sample, true, wvcdm::kDefaultCdmIdentifier}, {&clear_sub_sample, true},
{&clear_sub_sample_no_key, false, wvcdm::kDefaultCdmIdentifier}, {&clear_sub_sample_no_key, false},
{&clear_sub_sample_no_key, true, wvcdm::kDefaultCdmIdentifier}, {&clear_sub_sample_no_key, true},
{&single_encrypted_sub_sample, false, wvcdm::kDefaultCdmIdentifier}, {&single_encrypted_sub_sample, false},
{&single_encrypted_sub_sample, true, wvcdm::kDefaultCdmIdentifier}, {&single_encrypted_sub_sample, true}};
// The last entry simulates session sharing using the non default
// identifier.
{&single_encrypted_sub_sample, true, kExampleIdentifier}};
struct UsageInfoSubSampleInfo { struct UsageInfoSubSampleInfo {
SubSampleInfo* sub_sample; SubSampleInfo* sub_sample;
@@ -1306,14 +1301,6 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
GenerateKeyRequest(init_data, license_type, NULL); GenerateKeyRequest(init_data, license_type, NULL);
} }
void GenerateKeyRequest(const std::string& init_data,
CdmLicenseType license_type,
const CdmIdentifier& identifier) {
CdmAppParameterMap app_parameters;
GenerateKeyRequest(wvcdm::KEY_MESSAGE, "video/mp4", init_data,
app_parameters, license_type, identifier, NULL);
}
void GenerateKeyRequest(const std::string& init_data, void GenerateKeyRequest(const std::string& init_data,
CdmLicenseType license_type, CdmLicenseType license_type,
CdmClientPropertySet* property_set) { CdmClientPropertySet* property_set) {
@@ -1355,13 +1342,7 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
decryptor_.GenerateKeyRequest( decryptor_.GenerateKeyRequest(
session_id_, key_set_id, init_data_type, init_data, session_id_, key_set_id, init_data_type, init_data,
license_type, app_parameters, property_set, license_type, app_parameters, property_set,
cdm_identifier, &key_request)) cdm_identifier, &key_request));
<< "session_id_ " << session_id_ << std::endl
<< "init_data (hex) " << wvcdm::b2a_hex(init_data) << std::endl
<< "key_set_id " << key_set_id << std::endl
<< "cdm_identifier.origin " << cdm_identifier.origin << std::endl
<< "cdm_identifier.app_package_name " << cdm_identifier.app_package_name << std::endl
<< "cdm_identifier.unique_id " << cdm_identifier.unique_id << std::endl;
key_msg_ = key_request.message; key_msg_ = key_request.message;
EXPECT_EQ(0u, key_request.url.size()); EXPECT_EQ(0u, key_request.url.size());
} }
@@ -4147,20 +4128,14 @@ class WvCdmSessionSharingTest
TEST_P(WvCdmSessionSharingTest, SessionSharingTest) { TEST_P(WvCdmSessionSharingTest, SessionSharingTest) {
SessionSharingSubSampleInfo* session_sharing_info = GetParam(); SessionSharingSubSampleInfo* session_sharing_info = GetParam();
CdmIdentifier cdm_identifier = session_sharing_info->cdm_identifier;
if (!cdm_identifier.IsEquivalentToDefault()) {
Provision(session_sharing_info->cdm_identifier, kLevelDefault);
}
TestWvCdmClientPropertySet property_set; TestWvCdmClientPropertySet property_set;
property_set.set_session_sharing_mode( property_set.set_session_sharing_mode(
session_sharing_info->session_sharing_enabled); session_sharing_info->session_sharing_enabled);
ASSERT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set, decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier,
cdm_identifier, NULL, NULL, &session_id_);
&session_id_));
CdmSessionId gp_session_id_1 = session_id_; CdmSessionId gp_session_id_1 = session_id_;
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming, cdm_identifier); GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth); VerifyKeyRequestResponse(g_license_server, g_client_auth);
// TODO(rfrias): Move content information to ConfigTestEnv // TODO(rfrias): Move content information to ConfigTestEnv
@@ -4171,11 +4146,10 @@ TEST_P(WvCdmSessionSharingTest, SessionSharingTest) {
"edef8ba979d64acea3c827dcd51d21ed00000014" // Widevine system id "edef8ba979d64acea3c827dcd51d21ed00000014" // Widevine system id
"08011210bdf1cb4fffc6506b8b7945b0bd2917fb"); // pssh data "08011210bdf1cb4fffc6506b8b7945b0bd2917fb"); // pssh data
ASSERT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set, decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier,
cdm_identifier, NULL, NULL, &session_id_);
&session_id_));
CdmSessionId gp_session_id_2 = session_id_; CdmSessionId gp_session_id_2 = session_id_;
GenerateKeyRequest(gp_key_id2, kLicenseTypeStreaming, cdm_identifier); GenerateKeyRequest(gp_key_id2, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, gp_client_auth2); VerifyKeyRequestResponse(g_license_server, gp_client_auth2);
SubSampleInfo* data = session_sharing_info->sub_sample; SubSampleInfo* data = session_sharing_info->sub_sample;
@@ -4190,10 +4164,7 @@ TEST_P(WvCdmSessionSharingTest, SessionSharingTest) {
if (session_sharing_info->session_sharing_enabled || !data->is_encrypted) { if (session_sharing_info->session_sharing_enabled || !data->is_encrypted) {
EXPECT_EQ(NO_ERROR, EXPECT_EQ(NO_ERROR,
decryptor_.Decrypt(gp_session_id_2, data->validate_key_id, decryptor_.Decrypt(gp_session_id_2, data->validate_key_id,
decryption_parameters)) decryption_parameters));
<< "session_sharing_info->session_sharing_enabled "
<< session_sharing_info->session_sharing_enabled << std::endl
<< "data->is_encrypted " << data->is_encrypted << std::endl;
EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(), EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(),
decrypt_buffer.begin())); decrypt_buffer.begin()));
} else { } else {
@@ -4202,19 +4173,13 @@ TEST_P(WvCdmSessionSharingTest, SessionSharingTest) {
decryption_parameters)); decryption_parameters));
} }
if (!cdm_identifier.IsEquivalentToDefault()) {
// Unprovision both security level certs.
decryptor_.Unprovision(kSecurityLevelL1, cdm_identifier);
decryptor_.Unprovision(kSecurityLevelL3, cdm_identifier);
}
decryptor_.CloseSession(gp_session_id_1); decryptor_.CloseSession(gp_session_id_1);
decryptor_.CloseSession(gp_session_id_2); decryptor_.CloseSession(gp_session_id_2);
} }
INSTANTIATE_TEST_CASE_P(Cdm, WvCdmSessionSharingTest, INSTANTIATE_TEST_CASE_P(Cdm, WvCdmSessionSharingTest,
::testing::Range(&session_sharing_sub_samples[0], ::testing::Range(&session_sharing_sub_samples[0],
&session_sharing_sub_samples[7])); &session_sharing_sub_samples[6]));
TEST_F(WvCdmRequestLicenseTest, SessionSharingTest) { TEST_F(WvCdmRequestLicenseTest, SessionSharingTest) {
TestWvCdmClientPropertySet property_set; TestWvCdmClientPropertySet property_set;

View File

@@ -30,10 +30,11 @@ class WvContentDecryptionModuleMetricsTest : public ::testing::Test {
wvcdm::WvContentDecryptionModule decryptor_; wvcdm::WvContentDecryptionModule decryptor_;
}; };
TEST_F(WvContentDecryptionModuleMetricsTest, IdentifierNotFound) { TEST_F(WvContentDecryptionModuleMetricsTest, NoMetrics) {
drm_metrics::WvCdmMetrics metrics; // Get metrics before any operations are performed.
ASSERT_EQ(wvcdm::UNKNOWN_ERROR, std::string serialized_metrics;
decryptor_.GetMetrics(kDefaultCdmIdentifier, &metrics)); decryptor_.GetSerializedMetrics(&serialized_metrics);
EXPECT_TRUE(serialized_metrics.empty());
} }
TEST_F(WvContentDecryptionModuleMetricsTest, EngineOnlyMetrics) { TEST_F(WvContentDecryptionModuleMetricsTest, EngineOnlyMetrics) {
@@ -47,21 +48,27 @@ TEST_F(WvContentDecryptionModuleMetricsTest, EngineOnlyMetrics) {
decryptor_.GetProvisioningRequest(cert_type, cert_authority, decryptor_.GetProvisioningRequest(cert_type, cert_authority,
kDefaultCdmIdentifier, &request, kDefaultCdmIdentifier, &request,
&provisioning_server_url)); &provisioning_server_url));
std::string serialized_metrics;
decryptor_.GetSerializedMetrics(&serialized_metrics);
drm_metrics::WvCdmMetrics metrics; drm_metrics::WvCdmMetricsGroup metrics_group;
ASSERT_EQ(wvcdm::NO_ERROR, ASSERT_TRUE(metrics_group.ParseFromString(serialized_metrics))
decryptor_.GetMetrics(kDefaultCdmIdentifier, &metrics)); << "Unexpected failure deserializing metrics: "
<< wvcdm::b2a_hex(serialized_metrics);
ASSERT_THAT(metrics_group.metrics().size(), Eq(1));
// 100 is an arbitrary high value that shouldn't ever occur. // 100 is an arbitrary high value that shouldn't ever occur.
EXPECT_THAT( EXPECT_THAT(
metrics.engine_metrics().oemcrypto_initialization_mode().int_value(), metrics_group.metrics(0).engine_metrics()
.oemcrypto_initialization_mode().int_value(),
Lt(100)); Lt(100));
EXPECT_THAT( EXPECT_THAT(
metrics.engine_metrics().oemcrypto_initialization_mode().int_value(), metrics_group.metrics(0).engine_metrics()
.oemcrypto_initialization_mode().int_value(),
Ge(0)); Ge(0));
ASSERT_THAT(metrics.engine_metrics() ASSERT_THAT(metrics_group.metrics(0).engine_metrics()
.cdm_engine_get_provisioning_request_time_us().size(), Eq(1)); .cdm_engine_get_provisioning_request_time_us().size(), Eq(1));
EXPECT_THAT(metrics.engine_metrics() EXPECT_THAT(metrics_group.metrics(0).engine_metrics()
.cdm_engine_get_provisioning_request_time_us(0) .cdm_engine_get_provisioning_request_time_us(0)
.operation_count(), .operation_count(),
Eq(1u)); Eq(1u));
@@ -78,80 +85,81 @@ TEST_F(WvContentDecryptionModuleMetricsTest, EngineAndSessionMetrics) {
decryptor_.OpenSession(key_system, NULL, decryptor_.OpenSession(key_system, NULL,
kDefaultCdmIdentifier, NULL, &session_id)); kDefaultCdmIdentifier, NULL, &session_id));
drm_metrics::WvCdmMetrics metrics; // The metrics will have a single engine and single session stats.
ASSERT_EQ(wvcdm::NO_ERROR,
decryptor_.GetMetrics(kDefaultCdmIdentifier, &metrics));
std::string serialized_metrics; std::string serialized_metrics;
ASSERT_TRUE(metrics.SerializeToString(&serialized_metrics)); decryptor_.GetSerializedMetrics(&serialized_metrics);
// Spot check some metric values. // Spot check some metric values.
drm_metrics::WvCdmMetricsGroup metrics_group;
ASSERT_TRUE(metrics_group.ParseFromString(serialized_metrics))
<< "Unexpected failure deserializing metrics: "
<< wvcdm::b2a_hex(serialized_metrics);
ASSERT_THAT(metrics_group.metrics().size(), Eq(1));
// Validate engine-level metrics. // Validate engine-level metrics.
EXPECT_TRUE(metrics.engine_metrics().has_oemcrypto_initialization_mode()); EXPECT_TRUE(metrics_group.metrics(0).engine_metrics()
ASSERT_THAT(metrics.engine_metrics().cdm_engine_open_session().size(), Eq(1)); .has_oemcrypto_initialization_mode());
EXPECT_THAT(metrics.engine_metrics().cdm_engine_open_session(0).count(), ASSERT_THAT(
Eq(1)); metrics_group.metrics(0).engine_metrics().cdm_engine_open_session().size(),
EXPECT_THAT(metrics.engine_metrics() Eq(1));
EXPECT_THAT(metrics_group.metrics(0).engine_metrics()
.cdm_engine_open_session(0).count(), Eq(1));
EXPECT_THAT(metrics_group.metrics(0).engine_metrics()
.cdm_engine_open_session(0).attributes().error_code(), .cdm_engine_open_session(0).attributes().error_code(),
Eq(CdmResponseType::NEED_PROVISIONING)); Eq(CdmResponseType::NEED_PROVISIONING));
// Validate a session-level metric. // Validate a session-level metric.
ASSERT_THAT(metrics.session_metrics().size(), Eq(1)); ASSERT_THAT(metrics_group.metrics(0).session_metrics().size(), Eq(1));
EXPECT_THAT( EXPECT_THAT(
metrics.session_metrics(0).cdm_session_life_span_ms().double_value(), metrics_group.metrics(0).session_metrics(0)
.cdm_session_life_span_ms().double_value(),
Gt(0.0)) Gt(0.0))
<< "Unexpected failure with session_metrics: " << "Unexpected failure with session_metrics: "
<< wvcdm::b2a_hex(serialized_metrics); << wvcdm::b2a_hex(serialized_metrics);
} }
TEST_F(WvContentDecryptionModuleMetricsTest, TEST_F(WvContentDecryptionModuleMetricsTest, MultipleEngineMetric) {
DifferentCdmIdentifiersHaveDifferentMetrics) {
CdmSessionId session_id; CdmSessionId session_id;
wvcdm::CdmKeySystem key_system("com.widevine"); wvcdm::CdmKeySystem key_system("com.widevine");
CdmIdentifier identifiers[] = { kDefaultCdmIdentifier, CdmIdentifier identifier = { "foo", "bar", "baz" };
{ "foo", "bar", "baz", 7 },
// Note that this has all the same parameters
// as the one above except for the unique_id.
{ "foo", "bar", "baz", 8 }};
const int cdm_engine_count = 3;
for (int i = 0; i < cdm_engine_count; i++) {
// To make sure we can detect different engine metrics,
// make the open session call a different number of times for
// each identifier.
for (int j = 0; j <= i; j ++) {
EXPECT_EQ(CdmResponseType::NEED_PROVISIONING,
decryptor_.OpenSession(key_system, NULL,
identifiers[i], NULL, &session_id));
}
}
for (int i = 0; i < cdm_engine_count; i++) { // Openning the session will fail with NEEDS_PROVISIONING error. But it will
drm_metrics::WvCdmMetrics metrics; // still create some session-level stats.
metrics.Clear(); EXPECT_EQ(CdmResponseType::NEED_PROVISIONING,
ASSERT_EQ(wvcdm::NO_ERROR, decryptor_.OpenSession(key_system, NULL,
decryptor_.GetMetrics(identifiers[i], &metrics)); kDefaultCdmIdentifier, NULL, &session_id));
std::string serialized_metrics; // Open a second engine with a custom identifier.
ASSERT_TRUE(metrics.SerializeToString(&serialized_metrics)); EXPECT_EQ(CdmResponseType::NEED_PROVISIONING,
decryptor_.OpenSession(key_system, NULL,
identifier, NULL, &session_id));
ASSERT_THAT(metrics.engine_metrics().cdm_engine_open_session().size(), // The metrics will now have two engines with single session stats each.
Eq(1)); std::string serialized_metrics;
// The number of times open session was called should match the index decryptor_.GetSerializedMetrics(&serialized_metrics);
// of the identifier
EXPECT_THAT(metrics.engine_metrics().cdm_engine_open_session(0).count(), // Spot check some metric values.
Eq(i + 1)); drm_metrics::WvCdmMetricsGroup metrics_group;
ASSERT_TRUE(metrics_group.ParseFromString(serialized_metrics));
// Two engine-level metrics are expected.
ASSERT_THAT(metrics_group.metrics().size(), Eq(2));
for (int i = 0; i < metrics_group.metrics().size(); i++) {
drm_metrics::WvCdmMetrics::EngineMetrics engine_metrics =
metrics_group.metrics(i).engine_metrics();
// Validate an engine-level metric.
EXPECT_TRUE(engine_metrics.has_oemcrypto_initialization_mode());
ASSERT_THAT(engine_metrics.cdm_engine_open_session().size(), Eq(1));
EXPECT_THAT(engine_metrics.cdm_engine_open_session(0).count(), Eq(1));
EXPECT_THAT( EXPECT_THAT(
metrics.engine_metrics() engine_metrics.cdm_engine_open_session(0).attributes().error_code(),
.cdm_engine_open_session(0).attributes().error_code(),
Eq(CdmResponseType::NEED_PROVISIONING)); Eq(CdmResponseType::NEED_PROVISIONING));
// Spot check a session-level metric. // Validate a session-level metric.
ASSERT_THAT(metrics.session_metrics().size(), Eq(i + 1)) ASSERT_THAT(metrics_group.metrics(i).session_metrics().size(), Eq(1));
<< "Unexpected failure with session_metrics: " EXPECT_THAT(metrics_group.metrics(i).session_metrics(0)
<< wvcdm::b2a_hex(serialized_metrics); .cdm_session_life_span_ms().double_value(), Gt(0.0));
EXPECT_THAT(metrics.session_metrics(0)
.cdm_session_life_span_ms().double_value(), Gt(0.0))
<< "Unexpected failure with session_metrics: "
<< wvcdm::b2a_hex(serialized_metrics);
} }
} }
} // wvcdm namespace }

View File

@@ -365,10 +365,6 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener,
const std::string& origin() const { return mCdmIdentifier.origin; } const std::string& origin() const { return mCdmIdentifier.origin; }
bool set_origin(const std::string& id); bool set_origin(const std::string& id);
// Indicates whether the builder can still be modified. This returns false
// until a call to getCdmIdentifier.
bool is_sealed() { return mIsIdentifierSealed; }
private: private:
WVDRM_DISALLOW_COPY_AND_ASSIGN(CdmIdentifierBuilder); WVDRM_DISALLOW_COPY_AND_ASSIGN(CdmIdentifierBuilder);
@@ -386,13 +382,6 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener,
// outside this class should use getDeviceUniqueId() to get the // outside this class should use getDeviceUniqueId() to get the
// application-safe device-unique ID. // application-safe device-unique ID.
Status getOemcryptoDeviceId(std::string* id); Status getOemcryptoDeviceId(std::string* id);
// The unique identifier is meant to ensure that two clients with the
// same spoid, origin and app package name still get different cdm engine
// instances. This is a stepping stone to simplifying the implementation.
// Note that we do not have a lock or mutex around this object. We assume
// that locking is handled external to this object.
uint32_t getNextUniqueId();
} mCdmIdentifierBuilder; } mCdmIdentifierBuilder;
sp<wvcdm::WvContentDecryptionModule> const mCDM; sp<wvcdm::WvContentDecryptionModule> const mCDM;

View File

@@ -392,7 +392,7 @@ status_t WVDrmPlugin::provideProvisionResponse(
} }
CdmProvisioningResponse cdmResponse(response.begin(), response.end()); CdmProvisioningResponse cdmResponse(response.begin(), response.end());
if (cdmResponse == kSpecialUnprovisionResponse) { if (cdmResponse == kSpecialUnprovisionResponse) {
if (mCdmIdentifier.IsEquivalentToDefault()) { if (mCdmIdentifier == kDefaultCdmIdentifier) {
return kErrorNoOriginSpecified; return kErrorNoOriginSpecified;
} }
return unprovision(mCdmIdentifier); return unprovision(mCdmIdentifier);
@@ -540,14 +540,9 @@ status_t WVDrmPlugin::getPropertyByteArray(const String8& name,
} else if (name == "serviceCertificate") { } else if (name == "serviceCertificate") {
value = ToVector(mPropertySet.service_certificate()); value = ToVector(mPropertySet.service_certificate());
} else if (name == "metrics") { } else if (name == "metrics") {
std::string serialized_metrics; std::string metrics_value;
drm_metrics::WvCdmMetrics metrics; mCDM->GetSerializedMetrics(&metrics_value);
mCDM->GetMetrics(mCdmIdentifier, &metrics); value = ToVector(metrics_value);
if (!metrics.SerializeToString(&serialized_metrics)) {
return android::ERROR_DRM_UNKNOWN;
} else {
value = ToVector(serialized_metrics);
}
} else { } else {
ALOGE("App requested unknown byte array property %s", name.string()); ALOGE("App requested unknown byte array property %s", name.string());
return android::ERROR_DRM_CANNOT_HANDLE; return android::ERROR_DRM_CANNOT_HANDLE;

View File

@@ -14,7 +14,6 @@
#include "mapErrors-inl.h" #include "mapErrors-inl.h"
#include "media/stagefright/MediaErrors.h" #include "media/stagefright/MediaErrors.h"
#include "metrics.pb.h"
#include "openssl/sha.h" #include "openssl/sha.h"
#include "wv_cdm_constants.h" #include "wv_cdm_constants.h"
@@ -140,16 +139,6 @@ WVDrmPlugin::~WVDrmPlugin() {
} }
} }
mCryptoSessions.clear(); mCryptoSessions.clear();
CdmIdentifier identifier;
Status status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
if (status != Status::OK) {
ALOGE("Failed to get cdm identifier %d", status);
} else {
status = mapCdmResponseType(mCDM->CloseCdm(identifier));
if (status != Status::OK) {
ALOGE("Failed to get close cdm %d", status);
}
}
} }
Status WVDrmPlugin::openSessionCommon(std::vector<uint8_t>& sessionId) { Status WVDrmPlugin::openSessionCommon(std::vector<uint8_t>& sessionId) {
@@ -627,7 +616,7 @@ Return<void> WVDrmPlugin::provideProvisionResponse(
CdmProvisioningResponse cdmResponse(resp.begin(), resp.end()); CdmProvisioningResponse cdmResponse(resp.begin(), resp.end());
if (cdmResponse == kSpecialUnprovisionResponse) { if (cdmResponse == kSpecialUnprovisionResponse) {
if (identifier.IsEquivalentToDefault()) { if (identifier == kDefaultCdmIdentifier) {
ALOGW("Returns UNKNOWN error for legacy status kErrorNoOriginSpecified"); ALOGW("Returns UNKNOWN error for legacy status kErrorNoOriginSpecified");
_hidl_cb(Status::ERROR_DRM_UNKNOWN, toHidlVec(certificate), _hidl_cb(Status::ERROR_DRM_UNKNOWN, toHidlVec(certificate),
toHidlVec(wrappedKey)); toHidlVec(wrappedKey));
@@ -995,27 +984,9 @@ Return<void> WVDrmPlugin::getPropertyByteArray(
} else if (name == "serviceCertificate") { } else if (name == "serviceCertificate") {
value = StrToVector(mPropertySet.service_certificate()); value = StrToVector(mPropertySet.service_certificate());
} else if (name == "metrics") { } else if (name == "metrics") {
drm_metrics::WvCdmMetrics metrics; std::string metrics_value;
// If the cdm identifier is not yet sealed, then there are no metrics mCDM->GetSerializedMetrics(&metrics_value);
// for that cdm engine. Avoid calling getCdmIdentifier and sealing value = StrToVector(metrics_value);
// the identifier builder.
if (mCdmIdentifierBuilder.is_sealed()) {
CdmIdentifier identifier;
status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
if (status != Status::OK) {
ALOGE("Unexpected error retrieving cdm identifier: %d", status);
} else {
status = mapCdmResponseType(mCDM->GetMetrics(identifier, &metrics));
}
}
if (status == Status::OK) {
std::string serialized_metrics;
if (!metrics.SerializeToString(&serialized_metrics)) {
status = Status::ERROR_DRM_UNKNOWN;
} else {
value = StrToVector(serialized_metrics);
}
}
} else { } else {
ALOGE("App requested unknown byte array property %s", name.c_str()); ALOGE("App requested unknown byte array property %s", name.c_str());
status = Status::ERROR_DRM_CANNOT_HANDLE; status = Status::ERROR_DRM_CANNOT_HANDLE;
@@ -1670,7 +1641,6 @@ WVDrmPlugin::CdmIdentifierBuilder::CdmIdentifierBuilder(
mAppPackageName(appPackageName), mAppPackageName(appPackageName),
mParent(parent) { mParent(parent) {
mCdmIdentifier.app_package_name = mAppPackageName; mCdmIdentifier.app_package_name = mAppPackageName;
mCdmIdentifier.unique_id = getNextUniqueId();
} }
Status WVDrmPlugin::CdmIdentifierBuilder::getCdmIdentifier( Status WVDrmPlugin::CdmIdentifierBuilder::getCdmIdentifier(
@@ -1678,6 +1648,7 @@ Status WVDrmPlugin::CdmIdentifierBuilder::getCdmIdentifier(
if (!mIsIdentifierSealed) { if (!mIsIdentifierSealed) {
Status res = calculateSpoid(); Status res = calculateSpoid();
if (res != Status::OK) return res; if (res != Status::OK) return res;
mIsIdentifierSealed = true; mIsIdentifierSealed = true;
} }
*identifier = mCdmIdentifier; *identifier = mCdmIdentifier;
@@ -1746,12 +1717,6 @@ Status WVDrmPlugin::CdmIdentifierBuilder::getOemcryptoDeviceId(
return mParent.queryProperty(wvcdm::QUERY_KEY_DEVICE_ID, *id); return mParent.queryProperty(wvcdm::QUERY_KEY_DEVICE_ID, *id);
} }
uint32_t WVDrmPlugin::CdmIdentifierBuilder::getNextUniqueId() {
// Start with 1. 0 is reserved for the default cdm identifier.
static uint32_t unique_id = 1;
return ++unique_id;
}
} // namespace widevine } // namespace widevine
} // namespace V1_1 } // namespace V1_1
} // namespace drm } // namespace drm

View File

@@ -20,7 +20,6 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "media/stagefright/foundation/ABase.h" #include "media/stagefright/foundation/ABase.h"
#include "media/stagefright/MediaErrors.h" #include "media/stagefright/MediaErrors.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h" #include "wv_cdm_constants.h"
#include "wv_cdm_types.h" #include "wv_cdm_types.h"
#include "wv_content_decryption_module.h" #include "wv_content_decryption_module.h"
@@ -121,17 +120,15 @@ const uint8_t* const kUnprovisionResponse =
const size_t kUnprovisionResponseSize = 11; const size_t kUnprovisionResponseSize = 11;
const std::string kDeviceId("0123456789\0ABCDEF", 17); const std::string kDeviceId("0123456789\0ABCDEF", 17);
// This is a serialized WvCdmMetrics message containing a small amount of // This is a serialized MetricsGroup message containing a small amount of
// sample data. This ensures we're able to extract it via a property. // sample data. This ensures we're able to extract it via a property.
const char kSerializedMetricsHex[] = const char kSerializedMetrics[] = {
"0a580a001a0210072202100d2a02100832182216636f6d2e676f6f676c652e616e64726f69" 0x0a, 0x0a, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x02, 0x08, 0x00,
"642e676d734208220631342e302e304a06080112020800520610d5f3fad5056a0b1d00fd4c" 0x0a, 0x12, 0x0a, 0x05, 0x74, 0x65, 0x73, 0x74, 0x32, 0x12, 0x09, 0x11,
"47280132020804a2010608011202080012cb010a0622047369643412b5010a021001520919" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x15, 0x0a, 0x05,
"1d5a643bdfff50405a0b1d00d01945280132021001620d1d00f8e84528013204080020006a" 0x74, 0x65, 0x73, 0x74, 0x33, 0x12, 0x0c, 0x1a, 0x0a, 0x74, 0x65, 0x73,
"0310b739820102100d8a01060801120248009a010310ff01da0106080112024800e2010e1d" 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65
"005243472801320528800248009a020d1d00b016452801320428404800a202060801120248" };
"19aa0206080212024800b2020b1d8098f047280132024800ba02021001ca020b1d00101945"
"280132024800e202021004fa02021002a203021000b2030210021a09196891ed7c3f355040";
#define N_ELEM(a) (sizeof(a)/sizeof(a[0])) #define N_ELEM(a) (sizeof(a)/sizeof(a[0]))
} // anonymous namespace } // anonymous namespace
@@ -201,8 +198,7 @@ class MockCDM : public WvContentDecryptionModule {
MOCK_METHOD1(IsValidServiceCertificate, bool(const std::string&)); MOCK_METHOD1(IsValidServiceCertificate, bool(const std::string&));
MOCK_METHOD2(GetMetrics, CdmResponseType(const CdmIdentifier&, MOCK_METHOD1(GetSerializedMetrics, void(std::string*));
drm_metrics::WvCdmMetrics*));
}; };
class MockCrypto : public WVGenericCryptoInterface { class MockCrypto : public WVGenericCryptoInterface {
@@ -1130,9 +1126,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
static const std::string oemCryptoApiVersion = "13"; static const std::string oemCryptoApiVersion = "13";
static const std::string currentSRMVersion = "1"; static const std::string currentSRMVersion = "1";
static const std::string cdmVersion = "Infinity Minus 1"; static const std::string cdmVersion = "Infinity Minus 1";
drm_metrics::WvCdmMetrics expected_metrics; std::string serializedMetrics(
std::string serialized_metrics = wvcdm::a2bs_hex(kSerializedMetricsHex); kSerializedMetrics, kSerializedMetrics + sizeof(kSerializedMetrics));
ASSERT_TRUE(expected_metrics.ParseFromString(serialized_metrics));
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _)) EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _))
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1), .WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1),
@@ -1176,9 +1171,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
.WillOnce(DoAll(SetArgPointee<2>(cdmVersion), .WillOnce(DoAll(SetArgPointee<2>(cdmVersion),
testing::Return(wvcdm::NO_ERROR))); testing::Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm, GetMetrics(_, _)) EXPECT_CALL(*cdm, GetSerializedMetrics(_))
.WillOnce(DoAll(SetArgPointee<1>(expected_metrics), .WillOnce(SetArgPointee<0>(serializedMetrics));
testing::Return(wvcdm::NO_ERROR)));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto, false); WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto, false);
std::string stringResult; std::string stringResult;
@@ -1281,51 +1275,14 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
EXPECT_STREQ(currentSRMVersion.c_str(), stringResult.c_str()); EXPECT_STREQ(currentSRMVersion.c_str(), stringResult.c_str());
}); });
// This call occurs before any open session or other call. This means
// that the cdm identifer is not yet sealed, and metrics return empty
// metrics data.
plugin.getPropertyByteArray( plugin.getPropertyByteArray(
hidl_string("metrics"), hidl_string("metrics"),
[&](Status status, hidl_vec<uint8_t> vectorResult) { [&](Status status, hidl_vec<uint8_t> vectorResult) {
ASSERT_EQ(Status::OK, status); ASSERT_EQ(Status::OK, status);
std::vector<uint8_t> id(vectorResult); std::vector<uint8_t> id(vectorResult);
const char empty[] = {}; EXPECT_THAT(id, ElementsAreArray(serializedMetrics.data(),
EXPECT_THAT(id, ElementsAreArray(empty, sizeof(empty))); serializedMetrics.size()));
}); });
// Set expectations for the OpenSession call and a CloseSession call.
EXPECT_CALL(*cdm,
OpenSession(StrEq("com.widevine"), _, HasOrigin(EMPTY_ORIGIN), _, _))
.WillOnce(DoAll(SetArgPointee<4>(cdmSessionId),
testing::Return(wvcdm::NO_ERROR)));
// Provide expected behavior when plugin requests session control info
EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _))
.Times(AtLeast(1))
.WillRepeatedly(Invoke(setSessionIdOnMap<4>));
EXPECT_CALL(*cdm, CloseSession(_))
.Times(AtLeast(0));
// This call causes the cdm identifier to become sealed.
std::vector<uint8_t> sessionId;
plugin.openSession([&](Status status, hidl_vec<uint8_t> hSessionId) {
ASSERT_EQ(Status::OK, status);
sessionId.clear();
sessionId.assign(hSessionId.data(),
hSessionId.data() + hSessionId.size());
});
// This call occurs after open session. The CDM identifer should be sealed.
// And the call should populate the mock metrics data.
plugin.getPropertyByteArray(
hidl_string("metrics"),
[&](Status status, hidl_vec<uint8_t> vectorResult) {
ASSERT_EQ(Status::OK, status);
std::vector<uint8_t> id(vectorResult);
EXPECT_THAT(id, ElementsAreArray(serialized_metrics.data(),
serialized_metrics.size()));
});
ASSERT_EQ(Status::OK, plugin.closeSession(toHidlVec(sessionId)));
} }
TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) { TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) {

View File

@@ -13,7 +13,6 @@
#include "media/stagefright/foundation/ABase.h" #include "media/stagefright/foundation/ABase.h"
#include "media/stagefright/foundation/AString.h" #include "media/stagefright/foundation/AString.h"
#include "media/stagefright/MediaErrors.h" #include "media/stagefright/MediaErrors.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h" #include "wv_cdm_constants.h"
#include "wv_cdm_types.h" #include "wv_cdm_types.h"
#include "wv_content_decryption_module.h" #include "wv_content_decryption_module.h"
@@ -34,18 +33,14 @@ const uint8_t* const kUnprovisionResponse =
reinterpret_cast<const uint8_t*>("unprovision"); reinterpret_cast<const uint8_t*>("unprovision");
const size_t kUnprovisionResponseSize = 11; const size_t kUnprovisionResponseSize = 11;
// This is a serialized WvCdmMetrics message containing a small amount of // This is a serialized MetricsGroup message containing a small amount of
// sample data. This ensures we're able to extract it via a property. // sample data. This ensures we're able to extract it via a property.
const char kSerializedMetricsHex[] = const char kSerializedMetrics[] = {
"0a580a001a0210072202100d2a02100832182216636f6d2e676f6f676c652e616e64726f69" 0x0a, 0x0a, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x02, 0x08, 0x00,
"642e676d734208220631342e302e304a06080112020800520610d5f3fad5056a0b1d00fd4c" 0x0a, 0x12, 0x0a, 0x05, 0x74, 0x65, 0x73, 0x74, 0x32, 0x12, 0x09, 0x11,
"47280132020804a2010608011202080012cb010a0622047369643412b5010a021001520919" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x15, 0x0a, 0x05,
"1d5a643bdfff50405a0b1d00d01945280132021001620d1d00f8e84528013204080020006a" 0x74, 0x65, 0x73, 0x74, 0x33, 0x12, 0x0c, 0x1a, 0x0a, 0x74, 0x65, 0x73,
"0310b739820102100d8a01060801120248009a010310ff01da0106080112024800e2010e1d" 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65};
"005243472801320528800248009a020d1d00b016452801320428404800a202060801120248"
"19aa0206080212024800b2020b1d8098f047280132024800ba02021001ca020b1d00101945"
"280132024800e202021004fa02021002a203021000b2030210021a09196891ed7c3f355040";
} // anonymous namespace } // anonymous namespace
class MockCDM : public WvContentDecryptionModule { class MockCDM : public WvContentDecryptionModule {
@@ -113,8 +108,7 @@ class MockCDM : public WvContentDecryptionModule {
MOCK_METHOD1(IsValidServiceCertificate, bool(const std::string&)); MOCK_METHOD1(IsValidServiceCertificate, bool(const std::string&));
MOCK_METHOD2(GetMetrics, CdmResponseType(const CdmIdentifier&, MOCK_METHOD1(GetSerializedMetrics, void(std::string*));
drm_metrics::WvCdmMetrics*));
}; };
class MockCrypto : public WVGenericCryptoInterface { class MockCrypto : public WVGenericCryptoInterface {
@@ -856,10 +850,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
static const string oemCryptoApiVersion = "10"; static const string oemCryptoApiVersion = "10";
static const string currentSRMVersion = "1"; static const string currentSRMVersion = "1";
static const string cdmVersion = "Infinity Minus 1"; static const string cdmVersion = "Infinity Minus 1";
string serializedMetrics(kSerializedMetrics,
drm_metrics::WvCdmMetrics expected_metrics; kSerializedMetrics + sizeof(kSerializedMetrics));
std::string serialized_metrics = wvcdm::a2bs_hex(kSerializedMetricsHex);
ASSERT_TRUE(expected_metrics.ParseFromString(serialized_metrics));
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _)) EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _))
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1), .WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1),
@@ -903,9 +895,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
.WillOnce(DoAll(SetArgPointee<2>(cdmVersion), .WillOnce(DoAll(SetArgPointee<2>(cdmVersion),
Return(wvcdm::NO_ERROR))); Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm, GetMetrics(_, _)) EXPECT_CALL(*cdm, GetSerializedMetrics(_))
.WillOnce(DoAll(SetArgPointee<1>(expected_metrics), .WillOnce(SetArgPointee<0>(serializedMetrics));
testing::Return(wvcdm::NO_ERROR)));
String8 stringResult; String8 stringResult;
Vector<uint8_t> vectorResult; Vector<uint8_t> vectorResult;
@@ -971,8 +962,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
vectorResult.clear(); vectorResult.clear();
res = plugin.getPropertyByteArray(String8("metrics"), vectorResult); res = plugin.getPropertyByteArray(String8("metrics"), vectorResult);
ASSERT_EQ(OK, res); ASSERT_EQ(OK, res);
EXPECT_THAT(vectorResult, ElementsAreArray(serialized_metrics.data(), EXPECT_THAT(vectorResult, ElementsAreArray(serializedMetrics.data(),
serialized_metrics.size())); serializedMetrics.size()));
} }
TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) { TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) {