Fixes widevine metrics proto serialization

Changes to a much more efficient and more reusable protobuf format for
metrics.

Test: Widevine tests, Google Play and MediaDrm CTS test.
Bug: 73724218

Change-Id: I3299051d7a16bcd7758c8f272415ca40e10c1313
This commit is contained in:
Adam Stone
2018-02-20 19:12:02 -08:00
parent efc008c5a1
commit b19f0d106f
25 changed files with 1587 additions and 1867 deletions

View File

@@ -243,11 +243,9 @@ class CryptoSessionForTest : public CryptoSession, public testing::Test {
using CryptoSession::ExtractSystemIdFromOemCert;
CryptoSessionForTest() : CryptoSession(metrics_.GetCryptoMetrics()) {}
void SetUp() {
// crypto_metrics_.crypto_session_security_level_.Record(kSecurityLevelL3);
}
void SetUp() {}
KeySession* key_session() { return key_session_.get(); }
KeySession *key_session() { return key_session_.get(); }
private:
static metrics::SessionMetrics metrics_;
@@ -256,7 +254,7 @@ class CryptoSessionForTest : public CryptoSession, public testing::Test {
metrics::SessionMetrics CryptoSessionForTest::metrics_;
TEST(CryptoSessionTest, CanExtractSystemIdFromOemCertificate) {
std::string oem_cert(reinterpret_cast<const char*>(kOemCert),
std::string oem_cert(reinterpret_cast<const char *>(kOemCert),
sizeof(kOemCert));
uint32_t system_id;
ASSERT_TRUE(
@@ -266,134 +264,67 @@ TEST(CryptoSessionTest, CanExtractSystemIdFromOemCertificate) {
class CryptoSessionMetricsTest : public testing::Test {
protected:
void MakeMetricMap(
const drm_metrics::MetricsGroup& metric_group,
std::map<std::string, drm_metrics::MetricsGroup::Metric>* metric_map) {
std::transform(metric_group.metric().begin(),
metric_group.metric().end(),
std::inserter(*metric_map, metric_map->end()),
CryptoSessionMetricsTest::MakeMetricPair);
}
bool FindMetric(
const std::map<std::string,
drm_metrics::MetricsGroup::Metric>& metric_map,
const std::string& metric_name,
drm_metrics::MetricsGroup::Metric* metric) {
std::map<std::string,
drm_metrics::MetricsGroup::Metric>::const_iterator it =
metric_map.find(metric_name);
if (it == metric_map.end()) {
return false;
}
*metric = it->second;
return true;
}
uint32_t FindKeyboxSystemID() {
OEMCryptoResult sts;
uint8_t key_data[256];
size_t key_data_len = sizeof(key_data);
sts = OEMCrypto_GetKeyData(key_data, &key_data_len, kLevelDefault);
if (sts != OEMCrypto_SUCCESS) return 0;
uint32_t* data = reinterpret_cast<uint32_t*>(key_data);
uint32_t *data = reinterpret_cast<uint32_t *>(key_data);
uint32_t system_id = htonl(data[1]);
return system_id;
}
private:
static std::pair<std::string, drm_metrics::MetricsGroup::Metric>
MakeMetricPair(const drm_metrics::MetricsGroup::Metric& metric) {
LOGV("Metric: %s", metric.name().c_str());
return std::make_pair(metric.name(), metric);
}
};
TEST_F(CryptoSessionMetricsTest, OpenSessionValidMetrics) {
metrics::CryptoMetrics crypto_metrics;
CryptoSession session(&crypto_metrics);
session.Open(wvcdm::kLevelDefault);
drm_metrics::MetricsGroup actual_metrics;
crypto_metrics.Serialize(&actual_metrics);
// TODO(blueeyes): If we an convert to use full proto rather than proto lite,
// convert these tests to use Message-based convenience functions.
std::map<std::string, drm_metrics::MetricsGroup::Metric> metric_map;
MakeMetricMap(actual_metrics, &metric_map);
// Validate common metrics regardless of provisioning type.
drm_metrics::MetricsGroup::Metric metric;
EXPECT_TRUE(FindMetric(
metric_map,
"/drm/widevine/oemcrypto/initialize/time/count{oemcrypto_error:0}",
&metric));
EXPECT_EQ(metric.value().int_value(), 1);
EXPECT_TRUE(FindMetric(
metric_map,
"/drm/widevine/oemcrypto/initialize/time/mean{oemcrypto_error:0}",
&metric));
EXPECT_TRUE(metric.value().has_double_value());
// Exercise a method that will touch a metric.
CdmUsageSupportType usage_type;
ASSERT_EQ(NO_ERROR, session.GetUsageSupportType(&usage_type));
EXPECT_TRUE(FindMetric(
metric_map,
"/drm/widevine/oemcrypto/usage_table_support",
&metric));
EXPECT_EQ(metric.value().int_value(), usage_type);
drm_metrics::WvCdmMetrics::CryptoMetrics metrics_proto;
crypto_metrics.Serialize(&metrics_proto);
// TODO(blueeyes): If we an convert to use full proto rather than proto
// lite, convert these tests to use Message-based convenience functions.
// Validate common metrics regardless of provisioning type.
EXPECT_EQ(1, metrics_proto.oemcrypto_initialize_time_us().size());
EXPECT_TRUE(metrics_proto.oemcrypto_initialize_time_us(0)
.attributes()
.has_oem_crypto_result());
EXPECT_EQ(1u,
metrics_proto.oemcrypto_initialize_time_us(0).operation_count());
EXPECT_TRUE(metrics_proto.oemcrypto_initialize_time_us(0).has_mean());
EXPECT_EQ(usage_type,
metrics_proto.oemcrypto_usage_table_support().int_value());
// Validate metrics that differ based on provisioning type.
CdmClientTokenType token_type = session.GetPreProvisionTokenType();
if (token_type == kClientTokenKeybox) {
uint32_t system_id = FindKeyboxSystemID();
EXPECT_TRUE(FindMetric(
metric_map, "/drm/widevine/crypto_session/system_id", &metric));
EXPECT_EQ(metric.value().int_value(), system_id);
EXPECT_TRUE(FindMetric(
metric_map,
"/drm/widevine/oemcrypto/provisioning_method",
&metric));
EXPECT_EQ(metric.value().int_value(), OEMCrypto_Keybox);
EXPECT_TRUE(FindMetric(
metric_map,
"/drm/widevine/oemcrypto/get_key_data/time/count"
"{oemcrypto_error:0&length:64}",
&metric));
EXPECT_GE(metric.value().int_value(), 1);
EXPECT_TRUE(FindMetric(
metric_map,
"/drm/widevine/oemcrypto/get_key_data/time/mean"
"{oemcrypto_error:0&length:64}",
&metric));
EXPECT_TRUE(metric.value().has_double_value());
EXPECT_EQ(system_id, metrics_proto.crypto_session_system_id().int_value());
EXPECT_EQ(OEMCrypto_Keybox,
metrics_proto.oemcrypto_provisioning_method().int_value());
EXPECT_EQ(1, metrics_proto.oemcrypto_get_key_data_time_us().size());
EXPECT_EQ(
1u, metrics_proto.oemcrypto_get_key_data_time_us(0).operation_count());
} else if (token_type == kClientTokenOemCert) {
EXPECT_TRUE(FindMetric(
metric_map, "/drm/widevine/crypto_session/system_id", &metric));
// Recent devices all have a system id between 1k and 6 or 7k. Errors we
// are trying to catch are 0, byte swapped 32 bit numbers, or garbage. These
// errors will most likely be outside the range of 1000 to 2^16.
EXPECT_LE(1000, metric.value().int_value());
EXPECT_GT(0x10000, metric.value().int_value());
// Recent devices all have a system id between 1k and 6 or 7k. Errors
// we are trying to catch are 0, byte swapped 32 bit numbers, or
// garbage. These errors will most likely be outside the range of 1000
// to 2^16.
EXPECT_LE(1000, metrics_proto.crypto_session_system_id().int_value());
EXPECT_GT(0X10000, metrics_proto.crypto_session_system_id().int_value());
EXPECT_TRUE(FindMetric(
metric_map,
"/drm/widevine/oemcrypto/provisioning_method",
&metric));
EXPECT_EQ(metric.value().int_value(), OEMCrypto_OEMCertificate);
EXPECT_TRUE(FindMetric(
metric_map,
"/drm/widevine/oemcrypto/get_oem_public_certificate/count"
"{oemcrypto_error:0}",
&metric));
EXPECT_EQ(metric.value().int_value(), 1);
EXPECT_EQ(OEMCrypto_OEMCertificate,
metrics_proto.oemcrypto_provisioning_method().int_value());
ASSERT_EQ(1, metrics_proto.oemcrypto_get_oem_public_certificate().size());
EXPECT_EQ(1, metrics_proto.oemcrypto_get_oem_public_certificate(0).count());
} else if (token_type == kClientTokenDrmCert) {
// TODO(blueeyes): Add support for getting the system id from a
// pre-installed DRM certificate..
@@ -418,54 +349,35 @@ TEST_F(CryptoSessionMetricsTest, GetProvisioningTokenValidMetrics) {
ASSERT_TRUE(session.GetProvisioningToken(&token));
}
drm_metrics::MetricsGroup actual_metrics;
crypto_metrics.Serialize(&actual_metrics);
drm_metrics::WvCdmMetrics::CryptoMetrics metrics_proto;
crypto_metrics.Serialize(&metrics_proto);
std::map<std::string, drm_metrics::MetricsGroup::Metric> metric_map;
MakeMetricMap(actual_metrics, &metric_map);
drm_metrics::MetricsGroup::Metric metric;
if (token_type == kClientTokenKeybox) {
// TODO(blueeyes): Add more metrics verifications.
ASSERT_TRUE(FindMetric(
metric_map, "/drm/widevine/crypto_session/get_token/count{success:1}",
&metric));
EXPECT_EQ(metric.value().int_value(), 1);
EXPECT_TRUE(FindMetric(
metric_map, "/drm/widevine/crypto_session/system_id",
&metric));
ASSERT_EQ(1, metrics_proto.crypto_session_get_token().size());
EXPECT_EQ(1, metrics_proto.crypto_session_get_token(0).count());
uint32_t system_id = FindKeyboxSystemID();
EXPECT_EQ(metric.value().int_value(), system_id);
EXPECT_TRUE(FindMetric(
metric_map,
"/drm/widevine/oemcrypto/get_key_data/time/count"
"{oemcrypto_error:0&length:64}",
&metric));
EXPECT_GE(metric.value().int_value(), 1);
EXPECT_EQ(system_id, metrics_proto.crypto_session_system_id().int_value());
EXPECT_EQ(1, metrics_proto.oemcrypto_get_key_data_time_us().size());
EXPECT_EQ(
2u, metrics_proto.oemcrypto_get_key_data_time_us(0).operation_count());
} else if (token_type == kClientTokenOemCert) {
// TODO(blueeyes): Add more metrics verifications.
ASSERT_TRUE(FindMetric(
metric_map, "/drm/widevine/crypto_session/get_token/count{success:1}",
&metric));
EXPECT_EQ(metric.value().int_value(), 1);
EXPECT_TRUE(FindMetric(
metric_map, "/drm/widevine/crypto_session/system_id",
&metric));
// Recent devices all have a system id between 1k and 6 or 7k. Errors we
// are trying to catch are 0, byte swapped 32 bit numbers, or garbage. These
// errors will most likely be outside the range of 1000 to 2^16.
EXPECT_LE(1000, metric.value().int_value());
EXPECT_GT(0x10000, metric.value().int_value());
EXPECT_TRUE(FindMetric(
metric_map,
"/drm/widevine/oemcrypto/get_oem_public_certificate/count"
"{oemcrypto_error:0}",
&metric));
EXPECT_EQ(metric.value().int_value(), 1);
// Recent devices all have a system id between 1k and 6 or 7k. Errors
// we are trying to catch are 0, byte swapped 32 bit numbers, or
// garbage. These errors will most likely be outside the range of 1000
// to 2^16.
EXPECT_LE(1000, metrics_proto.crypto_session_system_id().int_value());
EXPECT_GT(0X10000, metrics_proto.crypto_session_system_id().int_value());
EXPECT_EQ(OEMCrypto_OEMCertificate,
metrics_proto.oemcrypto_provisioning_method().int_value());
EXPECT_EQ(1, metrics_proto.oemcrypto_get_oem_public_certificate().size());
EXPECT_EQ(1, metrics_proto.oemcrypto_get_oem_public_certificate(0).count());
ASSERT_EQ(1, metrics_proto.crypto_session_get_token().size());
EXPECT_EQ(1, metrics_proto.crypto_session_get_token(0).count());
} else {
ASSERT_FALSE(FindMetric(
metric_map, "/drm/widevine/crypto_session/get_token/count{success:1}",
&metric));
ASSERT_EQ(0, metrics_proto.crypto_session_get_token().size());
}
}