Create unique cdm engines per WVDrmPlugin instance

This change creates a unique id in the cdm identifier in order to force
a one-to-one mapping between WVDrmPlugin instances and CDM Engines. This
change simplifies some assumptions. This includes ensuring that the
metrics for a given MediaDrm instance map to a given CdmEngine instance.

Bug: 73724453
Test: Updated unit tests. GTS test pass. Shaka Player, Netflix and Google Play test.
Change-Id: I7e041b6cdf3e272d067da49d25a297b4a4663f1f
This commit is contained in:
Adam Stone
2018-03-29 12:28:57 -07:00
parent 084c370db6
commit 58234a69f2
11 changed files with 339 additions and 199 deletions

View File

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