From b19f0d106f7aa19cc9da97830827933bbdbb2abf Mon Sep 17 00:00:00 2001 From: Adam Stone Date: Tue, 20 Feb 2018 19:12:02 -0800 Subject: [PATCH] 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 --- libwvdrmengine/cdm/Android.mk | 1 + .../cdm/core/test/crypto_session_unittest.cpp | 214 ++---- .../include/wv_content_decryption_module.h | 35 +- .../cdm/metrics/include/attribute_handler.h | 53 ++ .../cdm/metrics/include/counter_metric.h | 192 ++--- .../cdm/metrics/include/distribution.h | 18 +- .../cdm/metrics/include/event_metric.h | 247 +++---- .../cdm/metrics/include/field_tuples.h | 103 +-- .../metrics/include/metric_serialization.h | 46 -- .../cdm/metrics/include/metrics_collections.h | 326 ++++++--- .../cdm/metrics/include/pow2bucket.h | 50 ++ .../cdm/metrics/include/value_metric.h | 89 ++- .../cdm/metrics/src/attribute_handler.cpp | 89 +++ .../cdm/metrics/src/counter_metric.cpp | 20 +- .../cdm/metrics/src/distribution.cpp | 20 +- .../cdm/metrics/src/event_metric.cpp | 44 +- libwvdrmengine/cdm/metrics/src/metrics.proto | 217 +++++- .../cdm/metrics/src/metrics_collections.cpp | 683 +++++++----------- .../cdm/metrics/src/value_metric.cpp | 140 ++-- .../metrics/test/counter_metric_unittest.cpp | 218 +++--- .../metrics/test/distribution_unittest.cpp | 10 +- .../metrics/test/event_metric_unittest.cpp | 276 +++---- .../metrics/test/value_metric_unittest.cpp | 83 +-- .../cdm/src/wv_content_decryption_module.cpp | 170 ++--- .../cdm/test/wv_cdm_metrics_test.cpp | 110 +-- 25 files changed, 1587 insertions(+), 1867 deletions(-) create mode 100644 libwvdrmengine/cdm/metrics/include/attribute_handler.h delete mode 100644 libwvdrmengine/cdm/metrics/include/metric_serialization.h create mode 100644 libwvdrmengine/cdm/metrics/include/pow2bucket.h create mode 100644 libwvdrmengine/cdm/metrics/src/attribute_handler.cpp diff --git a/libwvdrmengine/cdm/Android.mk b/libwvdrmengine/cdm/Android.mk index 9ebd5972..31923902 100644 --- a/libwvdrmengine/cdm/Android.mk +++ b/libwvdrmengine/cdm/Android.mk @@ -46,6 +46,7 @@ LOCAL_SRC_FILES := \ $(CORE_SRC_DIR)/sublicense_key_session.cpp \ $(CORE_SRC_DIR)/usage_table_header.cpp \ $(SRC_DIR)/wv_content_decryption_module.cpp \ + $(METRICS_SRC_DIR)/attribute_handler.cpp \ $(METRICS_SRC_DIR)/counter_metric.cpp \ $(METRICS_SRC_DIR)/distribution.cpp \ $(METRICS_SRC_DIR)/event_metric.cpp \ diff --git a/libwvdrmengine/cdm/core/test/crypto_session_unittest.cpp b/libwvdrmengine/cdm/core/test/crypto_session_unittest.cpp index 536c91bd..bead949a 100644 --- a/libwvdrmengine/cdm/core/test/crypto_session_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/crypto_session_unittest.cpp @@ -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(kOemCert), + std::string oem_cert(reinterpret_cast(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* 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& metric_map, - const std::string& metric_name, - drm_metrics::MetricsGroup::Metric* metric) { - std::map::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(key_data); + uint32_t *data = reinterpret_cast(key_data); uint32_t system_id = htonl(data[1]); return system_id; } - - private: - static std::pair - 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 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 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()); } } diff --git a/libwvdrmengine/cdm/include/wv_content_decryption_module.h b/libwvdrmengine/cdm/include/wv_content_decryption_module.h index 52957731..85198525 100644 --- a/libwvdrmengine/cdm/include/wv_content_decryption_module.h +++ b/libwvdrmengine/cdm/include/wv_content_decryption_module.h @@ -42,15 +42,12 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler { virtual bool IsOpenSession(const CdmSessionId& session_id); // Construct a valid license request. - virtual CdmResponseType GenerateKeyRequest(const CdmSessionId& session_id, - const CdmKeySetId& key_set_id, - const std::string& init_data_type, - const CdmInitData& init_data, - const CdmLicenseType license_type, - CdmAppParameterMap& app_parameters, - CdmClientPropertySet* property_set, - const CdmIdentifier& identifier, - CdmKeyRequest* key_request); + virtual CdmResponseType GenerateKeyRequest( + const CdmSessionId& session_id, const CdmKeySetId& key_set_id, + const std::string& init_data_type, const CdmInitData& init_data, + const CdmLicenseType license_type, CdmAppParameterMap& app_parameters, + CdmClientPropertySet* property_set, const CdmIdentifier& identifier, + CdmKeyRequest* key_request); // Accept license response and extract key info. virtual CdmResponseType AddKey(const CdmSessionId& session_id, @@ -77,22 +74,18 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler { CdmQueryMap* key_info); // Query OEMCrypto session ID - virtual CdmResponseType QueryOemCryptoSessionId(const CdmSessionId& session_id, - CdmQueryMap* response); + virtual CdmResponseType QueryOemCryptoSessionId( + const CdmSessionId& session_id, CdmQueryMap* response); // Provisioning related methods virtual CdmResponseType GetProvisioningRequest( - CdmCertificateType cert_type, - const std::string& cert_authority, - const CdmIdentifier& identifier, - CdmProvisioningRequest* request, + CdmCertificateType cert_type, const std::string& cert_authority, + const CdmIdentifier& identifier, CdmProvisioningRequest* request, std::string* default_url); virtual CdmResponseType HandleProvisioningResponse( - const CdmIdentifier& identifier, - CdmProvisioningResponse& response, - std::string* cert, - std::string* wrapped_key); + const CdmIdentifier& identifier, CdmProvisioningResponse& response, + std::string* cert, std::string* wrapped_key); virtual CdmResponseType Unprovision(CdmSecurityLevel level, const CdmIdentifier& identifier); @@ -161,7 +154,7 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler { // timer related methods to drive policy decisions void EnablePolicyTimer(); - void DisablePolicyTimer(); // Disable if all cdm engines are closed. + void DisablePolicyTimer(); // Disable if all cdm engines are closed. void ForceDisablePolicyTimer(); // Force disable the policy timer. void OnTimerEvent(); @@ -178,7 +171,7 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler { std::map cdm_by_session_id_; // The metrics for cdm engines and sessions that have been closed. - drm_metrics::MetricsGroup metrics_; + drm_metrics::WvCdmMetricsGroup metrics_group_; CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule); }; diff --git a/libwvdrmengine/cdm/metrics/include/attribute_handler.h b/libwvdrmengine/cdm/metrics/include/attribute_handler.h new file mode 100644 index 00000000..f11bb1d9 --- /dev/null +++ b/libwvdrmengine/cdm/metrics/include/attribute_handler.h @@ -0,0 +1,53 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// This file contains the declarations for the EventMetric class and related +// types. +#ifndef WVCDM_METRICS_ATTRIBUTE_HANDLER_H_ +#define WVCDM_METRICS_ATTRIBUTE_HANDLER_H_ + +#include "OEMCryptoCENC.h" +#include "field_tuples.h" +#include "log.h" +#include "metrics.pb.h" +#include "pow2bucket.h" +#include "value_metric.h" +#include "wv_cdm_types.h" + +namespace wvcdm { +namespace metrics { + +// This method is used to set the value of a single proto field. +// Specializations handle setting each value. +template +void SetAttributeField(const F& value, drm_metrics::Attributes* attributes); + +// This class handles serializing the attributes for metric types that breakdown +// into multiple buckets. The template parameters should be specified in pairs. +// E.g. I1 and F1 should match. I1 should specify the field number in the proto +// and F1 should specify the type of the field to be set. +template +class AttributeHandler { + public: + // This method returns the serialized attribute proto for the given field + // values. The order of the field values must match the order in the + // template. + std::string GetSerializedAttributes(F1 field1, F2 field2, F3 field3, + F4 field4) const { + drm_metrics::Attributes attributes; + SetAttributeField(field1, &attributes); + SetAttributeField(field2, &attributes); + SetAttributeField(field3, &attributes); + SetAttributeField(field4, &attributes); + std::string serialized_attributes; + if (!attributes.SerializeToString(&serialized_attributes)) { + LOGE("Failed to serialize attribute proto."); + return ""; + } + return serialized_attributes; + } +}; + +} // namespace metrics +} // namespace wvcdm +#endif // WVCDM_METRICS_ATTRIBUTE_HANDLER_H_ diff --git a/libwvdrmengine/cdm/metrics/include/counter_metric.h b/libwvdrmengine/cdm/metrics/include/counter_metric.h index c66e9996..0b21acb3 100644 --- a/libwvdrmengine/cdm/metrics/include/counter_metric.h +++ b/libwvdrmengine/cdm/metrics/include/counter_metric.h @@ -11,9 +11,9 @@ #include #include +#include "attribute_handler.h" #include "field_tuples.h" #include "lock.h" -#include "metric_serialization.h" namespace wvcdm { namespace metrics { @@ -22,23 +22,22 @@ class CounterMetricTest; // This base class provides the common defintion used by all templated // instances of CounterMetric. -class BaseCounterMetric : public MetricSerializable { +class BaseCounterMetric { public: - // Send metric values to the MetricSerializer. |serializer| must - // not be null and is owned by the caller. - virtual void Serialize(MetricSerializer* serializer); + const std::map* GetValues() const { + return &value_map_; + }; protected: // Instantiates a BaseCounterMetric. - BaseCounterMetric(const std::string& metric_name) - : metric_name_(metric_name) {} + BaseCounterMetric() {} virtual ~BaseCounterMetric() {} // Increment will look for an existing instance of the field names and // add the new value to the existing value. If the instance does not exist, // this method will create it. - void Increment(const std::string& field_names_values, int64_t value); + void Increment(const std::string &counter_key, int64_t value); private: friend class CounterMetricTest; @@ -48,8 +47,9 @@ class BaseCounterMetric : public MetricSerializable { std::map value_map_; /* - * This locks the internal state of the counter metric to ensure safety across - * multiple threads preventing the caller from worrying about locking. + * This locks the internal state of the counter metric to ensure safety + * across multiple threads preventing the caller from worrying about + * locking. */ Lock internal_lock_; }; @@ -67,136 +67,84 @@ class BaseCounterMetric : public MetricSerializable { // // Example usage: // -// CounterMetric my_metric("multiple/fields/metric", -// "request_type", // Field name. -// "error_code"); // Field name. +// CounterMetric< +// ::drm_metrics::Attributes::kErrorCodeFieldNumber, +// CdmResponseType, +// ::drm_metrics::Attributes::kCdmSecurityLevelFieldNumber, +// CdmSecurityLevel> my_metric; // -// my_metric.Increment(1, 7, 23); // (counter value, request type, error code). +// // (counter value, error code, security level) +// my_metric.Increment(1, CdmResponseType::NO_ERROR, SecurityLevel::kLevel3); // -// The CounterMetric supports serialization. A call to Serialize will serialize -// all values to the provided MetricsSerializer instance. -// -// example: -// -// class MyMetricSerializer : public MetricSerializer { -// // Add implementation here. -// } -// -// MyMetricSerializer serializer; -// my_metric.Serialize(&serializer); -template +// The CounterMetric class serializes its values to a repeated field of +// drm_metrics::CounterMetric instances. The field numbers used for +// recording the drm_metrics::Attributes are specified in the template +// parameters above (e.g. kErrorCodeFieldNumber). +template class CounterMetric : public BaseCounterMetric { public: - // Create a CounterMetric instance with the name |metric_name|. - CounterMetric(const std::string& metric_name); - - // Overloaded constructors with variable field name arguments. The number - // of |field_name| arguments must match the number of used Field type - // arguments. - CounterMetric(const std::string& metric_name, - const char* field_name); - CounterMetric(const std::string& metric_name, - const char* field_name1, - const char* field_name2); - CounterMetric(const std::string& metric_name, - const char* field_name1, - const char* field_name2, - const char* field_name3); - CounterMetric(const std::string& metric_name, - const char* field_name1, - const char* field_name2, - const char* field_name3, - const char* field_name4); + explicit CounterMetric() : BaseCounterMetric() {} // Increment will update the counter value associated with the provided // field values. void Increment(F1 field1 = util::Unused(), F2 field2 = util::Unused(), - F3 field3 = util::Unused(), F4 field4 = util::Unused()); + F3 field3 = util::Unused(), F4 field4 = util::Unused()) { + Increment(1, field1, field2, field3, field4); + } // Increment will add the value to the counter associated with the provided // field values. - void Increment(int64_t value, - F1 field1 = util::Unused(), F2 field2 = util::Unused(), - F3 field3 = util::Unused(), F4 field4 = util::Unused()); + void Increment(int64_t value, F1 field1 = util::Unused(), + F2 field2 = util::Unused(), F3 field3 = util::Unused(), + F4 field4 = util::Unused()) { + std::string key = + attribute_handler_.GetSerializedAttributes(field1, field2, + field3, field4); + BaseCounterMetric::Increment(key, value); + } + + void ToProto(::google::protobuf::RepeatedPtrField + *counters); private: friend class CounterMetricTest; - std::vector field_names_; + AttributeHandler attribute_handler_; }; -// Overloaded template constructor implementations for CounterMetric. -template -CounterMetric::CounterMetric( - const std::string& metric_name) - : BaseCounterMetric(metric_name) { - ASSERT_METRIC_UNUSED_START_FROM(1); +// Partial specializations for CounterMetric template. + +// Specialization for the CounterMetric with no attributes. +// For this, we don't deserialize and populate the attributes message. +template <> +inline void CounterMetric<0, util::Unused, 0, util::Unused, 0, util::Unused, 0, + util::Unused>:: + ToProto(::google::protobuf::RepeatedPtrField + *counters) { + + const std::map* values = GetValues(); + for (std::map::const_iterator it = values->begin(); + it != values->end(); it++) { + drm_metrics::CounterMetric *new_counter = counters->Add(); + new_counter->set_count(it->second); + } } -template -CounterMetric::CounterMetric( - const std::string& metric_name, - const char* field_name) - : BaseCounterMetric(metric_name) { - ASSERT_METRIC_UNUSED_START_FROM(2); - util::AppendFieldNames(&field_names_, - util::FirstUnusedType::value - 1, - field_name); -} -template -CounterMetric::CounterMetric( - const std::string& metric_name, - const char* field_name1, - const char* field_name2) - : BaseCounterMetric(metric_name) { - ASSERT_METRIC_UNUSED_START_FROM(3); - util::AppendFieldNames(&field_names_, - util::FirstUnusedType::value - 1, - field_name1, field_name2); -} -template -CounterMetric::CounterMetric( - const std::string& metric_name, - const char* field_name1, - const char* field_name2, - const char* field_name3) - : BaseCounterMetric(metric_name) { - ASSERT_METRIC_UNUSED_START_FROM(4); - util::AppendFieldNames(&field_names_, - util::FirstUnusedType::value - 1, - field_name1, field_name2, field_name3); -} -template -CounterMetric::CounterMetric( - const std::string& metric_name, - const char* field_name1, - const char* field_name2, - const char* field_name3, - const char* field_name4) - : BaseCounterMetric(metric_name) { - ASSERT_METRIC_UNUSED_START_FROM(5); - util::AppendFieldNames(&field_names_, - util::FirstUnusedType::value - 1, - field_name1, field_name2, - field_name3, field_name4); -} - -template -void CounterMetric::Increment( - F1 field1, F2 field2, F3 field3, F4 field4) { - std::string field_name_values = - util::MakeFieldNameString(field_names_, field1, field2, field3, field4); - BaseCounterMetric::Increment(field_name_values, 1); -} - -template -void CounterMetric::Increment( - int64_t value, F1 field1, F2 field2, F3 field3, F4 field4) { - std::string field_name_values = - util::MakeFieldNameString(field_names_, field1, field2, field3, field4); - BaseCounterMetric::Increment(field_name_values, value); +template +inline void CounterMetric::ToProto( + ::google::protobuf::RepeatedPtrField + *counters) { + const std::map* values = GetValues(); + for (std::map::const_iterator it = values->begin(); + it != values->end(); it++) { + drm_metrics::CounterMetric *new_counter = counters->Add(); + if (!new_counter->mutable_attributes()->ParseFromString(it->first)) { + LOGE("Failed to parse the attributes from a string."); + } + new_counter->set_count(it->second); + } } } // namespace metrics diff --git a/libwvdrmengine/cdm/metrics/include/distribution.h b/libwvdrmengine/cdm/metrics/include/distribution.h index 9b42d395..50ac97d4 100644 --- a/libwvdrmengine/cdm/metrics/include/distribution.h +++ b/libwvdrmengine/cdm/metrics/include/distribution.h @@ -27,23 +27,23 @@ class Distribution { Distribution(); // Uses the provided sample value to update the computed statistics. - void Record(double value); + void Record(float value); // Return the value for each of the stats computed about the series of // values (min, max, count, etc.). - double Min() const { return min_; } - double Max() const { return max_; } - double Mean() const { return mean_; } - int64_t Count() const { return count_; } + float Min() const { return min_; } + float Max() const { return max_; } + float Mean() const { return mean_; } + uint64_t Count() const { return count_; } double Variance() const { return count_ == 0 ? 0.0 : sum_squared_deviation_ / count_; } private: - int64_t count_; - double min_; - double max_; - double mean_; + uint64_t count_; + float min_; + float max_; + float mean_; double sum_squared_deviation_; }; diff --git a/libwvdrmengine/cdm/metrics/include/event_metric.h b/libwvdrmengine/cdm/metrics/include/event_metric.h index dcfd5223..a1142055 100644 --- a/libwvdrmengine/cdm/metrics/include/event_metric.h +++ b/libwvdrmengine/cdm/metrics/include/event_metric.h @@ -10,10 +10,14 @@ #include #include +#include "OEMCryptoCENC.h" +#include "attribute_handler.h" #include "distribution.h" -#include "field_tuples.h" #include "lock.h" -#include "metric_serialization.h" +#include "log.h" +#include "metrics.pb.h" +#include "pow2bucket.h" +#include "shared_ptr.h" namespace wvcdm { namespace metrics { @@ -22,31 +26,26 @@ class EventMetricTest; // This base class provides the common defintion used by all templated // instances of EventMetric. -class BaseEventMetric : public MetricSerializable { +class BaseEventMetric { public: - // Send metric values to the MetricSerializer. |serializer| must - // not be null and is owned by the caller. - virtual void Serialize(MetricSerializer* serializer); - protected: // Instantiates a BaseEventMetric. - BaseEventMetric(const std::string& metric_name) - : metric_name_(metric_name) {} + BaseEventMetric() {} virtual ~BaseEventMetric(); // Record will look for an existing instance of the Distribution identified - // by the field_names_values string and update it. If the instance does + // by the distribution_key string and update it. If the instance does // not exist, this will create it. - void Record(const std::string& field_names_values, double value); + void Record(const std::string &distribution_key, double value); + + // value_map_ contains a mapping from the string key (attribute name/values) + // to the distribution instance which holds the metric information + // (min, max, sum, etc.). + std::map value_map_; private: friend class EventMetricTest; - const std::string metric_name_; - // value_map_ contains a mapping from the field name/value pairs to the - // distribution instance which holds the metric information (min, max, sum, - // etc.). - std::map value_map_; /* * This locks the internal state of the event metric to ensure safety across @@ -55,39 +54,6 @@ class BaseEventMetric : public MetricSerializable { Lock internal_lock_; }; -// This class converts the size_t value into the highest power of two -// below the value. E.g. for 7, the value is 4. For 11, the value is 8. -// This class is intended to simplify the use of EventMetric Fields that may -// have many possible values, but we want to bucket them into a small set of -// numbers (32 or 64). -class Pow2Bucket { - public: - explicit Pow2Bucket(size_t value) : value_(GetLowerBucket(value)) {} - - Pow2Bucket(const Pow2Bucket& value) : value_(value.value_) {} - - // Support for converting to string. - friend std::ostream& operator<<(std::ostream& os, const Pow2Bucket& log) - { return os << log.value_; } - - private: - inline size_t GetLowerBucket(size_t value) { - if (!value) { - return 0; - } - - size_t log = 0; - while (value) { - log++; - value >>= 1; - } - - return 1u << (log - 1); - } - - size_t value_; -}; - // The EventMetric class is used to capture statistics about an event such as // a method call. EventMetric keeps track of the count, mean, min, max and // variance for the value being measured. For example, we may want to track the @@ -105,125 +71,100 @@ class Pow2Bucket { // // Example usage: // -// EventMetric my_metric("multiple/fields/metric", -// "request_type", "error_code", // Field names); // -// my_metric.Record(1, 7, 23); // (latency value, request type, error code). +// EventMetric< +// ::drm_metrics::Attributes::kErrorCodeFieldNumber, +// CdmResponseType, +// ::drm_metrics::Attributes::kCdmSecurityLevelFieldNumber, +// CdmSecurityLevel> my_metric; // -// The EventMetric supports serialization. A call to Serialize will -// serialize all values to the provided MetricsSerializer instance. +// // (latency value, error code, security level) +// my_metric.Increment(1, CdmResponseType::NO_ERROR, SecurityLevel::kLevel3); // -// example: -// -// class MyMetricSerializer : public MetricSerializer { -// // Add implementation here. -// } -// -// MyMetricSerializer serializer; -// my_metric.Serialize(&serializer); -// -template +// The EventMetric class serializes its values to a repeated field of +// drm_metrics::DistributionMetric instances. The field numbers used for +// recording the drm_metrics::Attributes are specified in the template +// parameters above (e.g. kErrorCodeFieldNumber). +template class EventMetric : public BaseEventMetric { public: - // Create an EventMetric instance with the name |metric_name|. - EventMetric(const std::string& metric_name); - - // Overloaded constructors with variable field name arguments. The number - // of |field_name| arguments must match the number of used Field type - // arguments. - EventMetric(const std::string& metric_name, - const char* field_name); - EventMetric(const std::string& metric_name, - const char* field_name1, - const char* field_name2); - EventMetric(const std::string& metric_name, - const char* field_name1, - const char* field_name2, - const char* field_name3); - EventMetric(const std::string& metric_name, - const char* field_name1, - const char* field_name2, - const char* field_name3, - const char* field_name4); + // Create an EventMetric instance with no attribute breakdowns. + explicit EventMetric() : BaseEventMetric(){} // Record will update the statistics of the EventMetric broken down by the // given field values. - void Record(double value, - F1 field1 = util::Unused(), - F2 field2 = util::Unused(), - F3 field3 = util::Unused(), - F4 field4 = util::Unused()); + void Record(double value, F1 field1 = util::Unused(), + F2 field2 = util::Unused(), F3 field3 = util::Unused(), + F4 field4 = util::Unused()) { + std::string key = + attribute_handler_.GetSerializedAttributes(field1, field2, + field3, field4); + BaseEventMetric::Record(key, value); + } + + const std::map* GetDistributions() const { + return &value_map_; + }; + + void ToProto( + ::google::protobuf::RepeatedPtrField + *distributions_proto); private: friend class EventMetricTest; - std::vector field_names_; + AttributeHandler attribute_handler_; + + inline void SetDistributionValues( + const Distribution &distribution, + drm_metrics::DistributionMetric *metric_proto) { + metric_proto->set_mean(distribution.Mean()); + metric_proto->set_operation_count(distribution.Count()); + if (distribution.Count() > 1) { + metric_proto->set_min(distribution.Min()); + metric_proto->set_max(distribution.Max()); + metric_proto->set_mean(distribution.Mean()); + metric_proto->set_variance(distribution.Variance()); + metric_proto->set_operation_count(distribution.Count()); + } + } }; -// Overloaded template constructor implementations for EventMetric. -template -EventMetric::EventMetric( - const std::string& metric_name) - : BaseEventMetric(metric_name) { - ASSERT_METRIC_UNUSED_START_FROM(1); +// Partial Specializations of Event Metrics. + +// Specialization for the event metric with no attributes. +// For this, we don't deserialize and populate the attributes message. +template <> +inline void EventMetric<0, util::Unused, 0, util::Unused, 0, util::Unused, 0, + util::Unused>:: + ToProto( + ::google::protobuf::RepeatedPtrField + *distributions_proto) { + const std::map* distributions + = GetDistributions(); + for (std::map::const_iterator it = + distributions->begin(); it != distributions->end(); it++) { + drm_metrics::DistributionMetric *new_metric = distributions_proto->Add(); + SetDistributionValues(*it->second, new_metric); + } } -template -EventMetric::EventMetric( - const std::string& metric_name, - const char* field_name) - : BaseEventMetric(metric_name) { - ASSERT_METRIC_UNUSED_START_FROM(2); - util::AppendFieldNames(&field_names_, - util::FirstUnusedType::value - 1, - field_name); -} -template -EventMetric::EventMetric( - const std::string& metric_name, - const char* field_name1, - const char* field_name2) - : BaseEventMetric(metric_name) { - ASSERT_METRIC_UNUSED_START_FROM(3); - util::AppendFieldNames(&field_names_, - util::FirstUnusedType::value - 1, - field_name1, field_name2); -} -template -EventMetric::EventMetric( - const std::string& metric_name, - const char* field_name1, - const char* field_name2, - const char* field_name3) - : BaseEventMetric(metric_name) { - ASSERT_METRIC_UNUSED_START_FROM(4); - util::AppendFieldNames(&field_names_, - util::FirstUnusedType::value - 1, - field_name1, field_name2, field_name3); -} -template -EventMetric::EventMetric( - const std::string& metric_name, - const char* field_name1, - const char* field_name2, - const char* field_name3, - const char* field_name4) - : BaseEventMetric(metric_name) { - ASSERT_METRIC_UNUSED_START_FROM(5); - util::AppendFieldNames(&field_names_, - util::FirstUnusedType::value - 1, - field_name1, field_name2, - field_name3, field_name4); -} - -template -void EventMetric::Record( - double value, F1 field1, F2 field2, F3 field3, F4 field4) { - std::string field_name_values = - util::MakeFieldNameString(field_names_, field1, field2, field3, field4); - BaseEventMetric::Record(field_name_values, value); +template +inline void EventMetric::ToProto( + ::google::protobuf::RepeatedPtrField + *distributions_proto) { + const std::map* distributions + = GetDistributions(); + for (std::map::const_iterator it = + distributions->begin(); it != distributions->end(); it++) { + drm_metrics::DistributionMetric *new_metric = distributions_proto->Add(); + if (!new_metric->mutable_attributes()->ParseFromString(it->first)) { + LOGE("Failed to parse the attributes from a string."); + } + SetDistributionValues(*it->second, new_metric); + } } } // namespace metrics diff --git a/libwvdrmengine/cdm/metrics/include/field_tuples.h b/libwvdrmengine/cdm/metrics/include/field_tuples.h index 307d7def..1031806b 100644 --- a/libwvdrmengine/cdm/metrics/include/field_tuples.h +++ b/libwvdrmengine/cdm/metrics/include/field_tuples.h @@ -5,13 +5,8 @@ #ifndef WVCDM_METRICS_FIELD_TUPLES_H_ #define WVCDM_METRICS_FIELD_TUPLES_H_ -#include -#include #include #include -#include -#include -#include namespace wvcdm { namespace metrics { @@ -24,103 +19,11 @@ namespace util { // templated classes with "variable" type arguments. struct Unused { // Required for compilation. Should never be used. - inline friend std::ostream& operator<< (std::ostream& out, const Unused&) - { return out; } + inline friend std::ostream& operator<<(std::ostream& out, const Unused&) { + return out; + } }; -// This utility method formats the collection of field name/value pairs. -// The format of the string is: -// -// [{field:value[&field:value]*}] -// -// If there are no pairs, returns a blank string. -template -std::string MakeFieldNameString(const std::vector& field_names, - const F1 field1, const F2 field2, - const F3 field3, const F4 field4) { - std::stringstream field_name_and_values; - std::vector::const_iterator field_name_iterator = - field_names.begin(); - if (field_name_iterator == field_names.end()) { - return field_name_and_values.str(); - } - // There is at least one name/value pair. Prepend open brace. - field_name_and_values << "{"; - field_name_and_values << *field_name_iterator << ':' << field1; - if (++field_name_iterator == field_names.end()) { - field_name_and_values << "}"; - return field_name_and_values.str(); - } - field_name_and_values << '&' << *field_name_iterator << ':' << field2; - if (++field_name_iterator == field_names.end()) { - field_name_and_values << "}"; - return field_name_and_values.str(); - } - field_name_and_values << '&' << *field_name_iterator << ':' << field3; - if (++field_name_iterator == field_names.end()) { - field_name_and_values << "}"; - return field_name_and_values.str(); - } - field_name_and_values << '&' << *field_name_iterator << ':' << field4; - field_name_and_values << "}"; - return field_name_and_values.str(); -} - -// This specialization of the helper method is a shortcut for class -// instances with no fields. -template<> -inline std::string MakeFieldNameString( - const std::vector& /* field_names */, - const Unused /* unused1 */, const Unused /* unused2 */, - const Unused /* unused3 */, const Unused /* unused4 */) { - return ""; -} - -// This helper function appends the field names to a vector of strings. -inline void AppendFieldNames(std::vector* field_name_vector, - int field_count, ...) { - va_list field_names; - - va_start(field_names, field_count); - for (int x = 0; x < field_count; x++) { - field_name_vector->push_back(va_arg(field_names, const char*)); - } - va_end(field_names); -} - -// These helper methods and FirstUnusedType assure that there is no mismatch -// between the specified types for metrics type parameters and the constructors -// and methods used for the specializations. -template -struct CompileAssert {}; -#define COMPILE_ASSERT(expr, msg) \ - typedef util::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] \ - __attribute__((unused)) - -template struct is_unused { static const bool value = false; }; -template <> struct is_unused { static const bool value = true; }; - -template -class FirstUnusedType { - static const bool a = is_unused::value; - static const bool b = is_unused::value; - static const bool c = is_unused::value; - static const bool d = is_unused::value; - // Check that all types after the first Unused are also Unused. - COMPILE_ASSERT(a <= b, Invalid_Unused_At_Position_2); - COMPILE_ASSERT(b <= c, Invalid_Unused_At_Position_3); - COMPILE_ASSERT(c <= d, Invalid_Unused_At_Position_4); - - public: - static const int value = 5 - (a + b + c + d); -}; - -// Asserts that no Unused types exist before N; after N, are all Unused types. -#define ASSERT_METRIC_UNUSED_START_FROM(N) \ - COMPILE_ASSERT((\ - util::FirstUnusedType::value) == N, \ - Unused_Start_From_##N) - } // namespace util } // namespace metrics } // namespace wvcdm diff --git a/libwvdrmengine/cdm/metrics/include/metric_serialization.h b/libwvdrmengine/cdm/metrics/include/metric_serialization.h deleted file mode 100644 index b2aa3a2b..00000000 --- a/libwvdrmengine/cdm/metrics/include/metric_serialization.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2017 Google Inc. All Rights Reserved. -// -// This file contains the declarations for the Metric class and related -// types. -#ifndef WVCDM_METRICS_METRIC_SERIALIZATION_H_ -#define WVCDM_METRICS_METRIC_SERIALIZATION_H_ - -namespace wvcdm { -namespace metrics { - -// The MetricSerializer is implemented by the code that instantiates -// MetricSerializable instances. The caller provides this MetricSerializer -// instance to MetricSerializable::Serialize. In turn, Serialize will make a -// call to Set* for each value to be Serialized. The MetricSerialiable -// implementation may set zero or more values on the MetricSerializer. -class MetricSerializer { - public: - virtual ~MetricSerializer() {}; - - // The metric_id is the metric name, plus the metric part name, and the - // metric field name/value string. E.g. - // name: "drm/cdm/decrypt/duration" - // part: "mean" - // field name/value string: "{error_code:0&buffer_size:1024}" - // becomes: "drm/cdm/decrypt/duration/mean/{error_code:0&buffer_size:1024}". - virtual void SetString(const std::string& metric_id, - const std::string& value) = 0; - virtual void SetInt32(const std::string& metric_id, int32_t value) = 0; - virtual void SetInt64(const std::string& metric_id, int64_t value) = 0; - virtual void SetDouble(const std::string& metric_id, double value) = 0; -}; - -// This abstract class merely provides the definition for serializing the value -// of the metric. -class MetricSerializable { - public: - virtual ~MetricSerializable() { } - // Serialize metric values to the MetricSerializer. |serializer| must - // not be null and is owned by the caller. - virtual void Serialize(MetricSerializer* serializer) = 0; -}; - -} // namespace metrics -} // namespace wvcdm - -#endif // WVCDM_METRICS_METRIC_SERIALIZATION_H_ diff --git a/libwvdrmengine/cdm/metrics/include/metrics_collections.h b/libwvdrmengine/cdm/metrics/include/metrics_collections.h index 4193024d..20ac573f 100644 --- a/libwvdrmengine/cdm/metrics/include/metrics_collections.h +++ b/libwvdrmengine/cdm/metrics/include/metrics_collections.h @@ -6,14 +6,14 @@ #ifndef WVCDM_METRICS_METRICS_GROUP_H_ #define WVCDM_METRICS_METRICS_GROUP_H_ -#include #include #include +#include +#include "OEMCryptoCENC.h" #include "counter_metric.h" #include "event_metric.h" #include "metrics.pb.h" -#include "OEMCryptoCENC.h" #include "value_metric.h" #include "wv_cdm_types.h" @@ -29,9 +29,9 @@ // long total_time = 0; // long error_code = TimeSomeOperation(&total_time); // M_RECORD(my_metrics, my_metric_name, total_time, error_code); -#define M_RECORD(GROUP, METRIC, TIME, ...) \ - if ( GROUP ) { \ - ( GROUP ) -> METRIC . Record( TIME, ##__VA_ARGS__ ); \ +#define M_RECORD(GROUP, METRIC, TIME, ...) \ + if (GROUP) { \ + (GROUP)->METRIC.Record(TIME, ##__VA_ARGS__); \ } // This definition automatically times an operation and records the time and @@ -44,107 +44,187 @@ // my_metrics_collection, // oemcrypto_initialize_, // sts); -#define M_TIME(CALL, GROUP, METRIC, ...) \ - if ( GROUP ) { \ - wvcdm::metrics::TimerMetric timer; \ - timer.Start(); \ - CALL; \ - ( GROUP ) -> METRIC . Record(timer.AsUs(), ##__VA_ARGS__ ); \ - } else { \ - CALL; \ +#define M_TIME(CALL, GROUP, METRIC, ...) \ + if (GROUP) { \ + wvcdm::metrics::TimerMetric timer; \ + timer.Start(); \ + CALL; \ + (GROUP)->METRIC.Record(timer.AsUs(), ##__VA_ARGS__); \ + } else { \ + CALL; \ } namespace wvcdm { namespace metrics { +namespace { + +// Short name definitions to ease AttributeHandler definitions. +// Internal namespace to help simplify declarations. +const int kErrorCodeFieldNumber = + ::drm_metrics::Attributes::kErrorCodeFieldNumber; +const int kErrorCodeBoolFieldNumber = + ::drm_metrics::Attributes::kErrorCodeBoolFieldNumber; +const int kCdmSecurityLevelFieldNumber = + ::drm_metrics::Attributes::kCdmSecurityLevelFieldNumber; +const int kSecurityLevelFieldNumber = + ::drm_metrics::Attributes::kSecurityLevelFieldNumber; +const int kLengthFieldNumber = + ::drm_metrics::Attributes::kLengthFieldNumber; +const int kEncryptAlgorithmFieldNumber = + ::drm_metrics::Attributes::kEncryptionAlgorithmFieldNumber; +const int kSigningAlgorithmFieldNumber = + ::drm_metrics::Attributes::kSigningAlgorithmFieldNumber; +const int kOemCryptoResultFieldNumber = + ::drm_metrics::Attributes::kOemCryptoResultFieldNumber; +const int kKeyStatusTypeFieldNumber = + ::drm_metrics::Attributes::kKeyStatusTypeFieldNumber; +const int kEventTypeFieldNumber = + ::drm_metrics::Attributes::kEventTypeFieldNumber; + +} // anonymous namespace + // This enum defines the conditions encountered during OEMCrypto Initialization // in oemcrypto_adapter_dynamic. typedef enum OEMCryptoInitializationMode { - OEMCrypto_INITIALIZED_USING_IN_APP = 0, - OEMCrypto_INITIALIZED_FORCING_L3 = 1, - OEMCrypto_INITIALIZED_USING_L3_NO_L1_LIBRARY_PATH = 2, - OEMCrypto_INITIALIZED_USING_L3_L1_OPEN_FAILED = 3, - OEMCrypto_INITIALIZED_USING_L3_L1_LOAD_FAILED = 4, - OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INITIALIZE_L1 = 5, - OEMCrypto_INITIALIZED_USING_L3_WRONG_L1_VERSION = 6, - OEMCrypto_INITIALIZED_USING_L1_WITH_KEYBOX = 7, - OEMCrypto_INITIALIZED_USING_L1_WITH_CERTIFICATE = 8, - OEMCrypto_INITIALIZED_USING_L1_CERTIFICATE_MIX = 9, - OEMCrypto_INITIALIZED_USING_L3_BAD_KEYBOX = 10, + OEMCrypto_INITIALIZED_USING_IN_APP = 0, + OEMCrypto_INITIALIZED_FORCING_L3 = 1, + OEMCrypto_INITIALIZED_USING_L3_NO_L1_LIBRARY_PATH = 2, + OEMCrypto_INITIALIZED_USING_L3_L1_OPEN_FAILED = 3, + OEMCrypto_INITIALIZED_USING_L3_L1_LOAD_FAILED = 4, + OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INITIALIZE_L1 = 5, + OEMCrypto_INITIALIZED_USING_L3_WRONG_L1_VERSION = 6, + OEMCrypto_INITIALIZED_USING_L1_WITH_KEYBOX = 7, + OEMCrypto_INITIALIZED_USING_L1_WITH_CERTIFICATE = 8, + OEMCrypto_INITIALIZED_USING_L1_CERTIFICATE_MIX = 9, + OEMCrypto_INITIALIZED_USING_L3_BAD_KEYBOX = 10, OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX = 11, - OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INSTALL_KEYBOX = 12, - OEMCrypto_INITIALIZED_USING_L1_INSTALLED_KEYBOX = 13, - OEMCrypto_INITIALIZED_USING_L3_INVALID_L1 = 14, - OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0 = 15, - OEMCrypto_INITIALIZED_L3_INITIALIZATION_FAILED = 16 + OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INSTALL_KEYBOX = 12, + OEMCrypto_INITIALIZED_USING_L1_INSTALLED_KEYBOX = 13, + OEMCrypto_INITIALIZED_USING_L3_INVALID_L1 = 14, + OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0 = 15, + OEMCrypto_INITIALIZED_L3_INITIALIZATION_FAILED = 16 } OEMCryptoInitializationMode; // This class contains metrics for Crypto Session and OEM Crypto. class CryptoMetrics { public: - CryptoMetrics(); - - void Serialize(drm_metrics::MetricsGroup* metrics); + void Serialize(drm_metrics::WvCdmMetrics::CryptoMetrics *crypto_metrics); /* CRYPTO SESSION */ // TODO(blueeyes): Convert this to crypto_session_default_security_level_. ValueMetric crypto_session_security_level_; - CounterMetric crypto_session_delete_all_usage_reports_; - CounterMetric crypto_session_delete_multiple_usage_information_; - EventMetric crypto_session_generic_decrypt_; - EventMetric crypto_session_generic_encrypt_; - EventMetric crypto_session_generic_sign_; - EventMetric crypto_session_generic_verify_; - CounterMetric crypto_session_get_device_unique_id_; - CounterMetric crypto_session_get_token_; + CounterMetric + crypto_session_delete_all_usage_reports_; + CounterMetric + crypto_session_delete_multiple_usage_information_; + EventMetric + crypto_session_generic_decrypt_; + EventMetric + crypto_session_generic_encrypt_; + EventMetric + crypto_session_generic_sign_; + EventMetric + crypto_session_generic_verify_; + CounterMetric + crypto_session_get_device_unique_id_; + CounterMetric crypto_session_get_token_; ValueMetric crypto_session_life_span_; - EventMetric crypto_session_load_certificate_private_key_; - EventMetric crypto_session_open_; // This is the requested security level. + EventMetric + crypto_session_load_certificate_private_key_; + // This uses the requested security level. + EventMetric + crypto_session_open_; ValueMetric crypto_session_system_id_; - EventMetric crypto_session_update_usage_information_; + EventMetric + crypto_session_update_usage_information_; ValueMetric crypto_session_usage_information_support_; /* OEMCRYPTO */ ValueMetric oemcrypto_api_version_; - CounterMetric oemcrypto_close_session_; - EventMetric oemcrypto_copy_buffer_; + CounterMetric + oemcrypto_close_session_; + EventMetric + oemcrypto_copy_buffer_; ValueMetric oemcrypto_current_hdcp_capability_; - CounterMetric oemcrypto_deactivate_usage_entry_; - EventMetric oemcrypto_decrypt_cenc_; - CounterMetric oemcrypto_delete_usage_entry_; - CounterMetric oemcrypto_delete_usage_table_; - EventMetric oemcrypto_derive_keys_from_session_key_; - CounterMetric oemcrypto_force_delete_usage_entry_; - EventMetric oemcrypto_generate_derived_keys_; - CounterMetric oemcrypto_generate_nonce_; - EventMetric oemcrypto_generate_rsa_signature_; - EventMetric oemcrypto_generate_signature_; - EventMetric oemcrypto_generic_decrypt_; - EventMetric oemcrypto_generic_encrypt_; - EventMetric oemcrypto_generic_sign_; - EventMetric oemcrypto_generic_verify_; - CounterMetric oemcrypto_get_device_id_; - EventMetric oemcrypto_get_key_data_; - CounterMetric oemcrypto_get_oem_public_certificate_; - CounterMetric oemcrypto_get_random_; - EventMetric oemcrypto_initialize_; + CounterMetric + oemcrypto_deactivate_usage_entry_; + EventMetric + oemcrypto_decrypt_cenc_; + CounterMetric + oemcrypto_delete_usage_entry_; + CounterMetric + oemcrypto_delete_usage_table_; + EventMetric + oemcrypto_derive_keys_from_session_key_; + CounterMetric + oemcrypto_force_delete_usage_entry_; + EventMetric + oemcrypto_generate_derived_keys_; + CounterMetric + oemcrypto_generate_nonce_; + EventMetric + oemcrypto_generate_rsa_signature_; + EventMetric + oemcrypto_generate_signature_; + EventMetric + oemcrypto_generic_decrypt_; + EventMetric + oemcrypto_generic_encrypt_; + EventMetric + oemcrypto_generic_sign_; + EventMetric + oemcrypto_generic_verify_; + CounterMetric + oemcrypto_get_device_id_; + EventMetric + oemcrypto_get_key_data_; + CounterMetric + oemcrypto_get_oem_public_certificate_; + CounterMetric + oemcrypto_get_random_; + EventMetric + oemcrypto_initialize_; ValueMetric oemcrypto_is_anti_rollback_hw_present_; ValueMetric oemcrypto_is_keybox_valid_; - EventMetric oemcrypto_load_device_rsa_key_; - EventMetric oemcrypto_load_entitled_keys_; - EventMetric oemcrypto_load_keys_; + EventMetric + oemcrypto_load_device_rsa_key_; + EventMetric + oemcrypto_load_entitled_keys_; + EventMetric + oemcrypto_load_keys_; ValueMetric oemcrypto_max_hdcp_capability_; ValueMetric oemcrypto_max_number_of_sessions_; ValueMetric oemcrypto_number_of_open_sessions_; ValueMetric oemcrypto_provisioning_method_; - EventMetric oemcrypto_refresh_keys_; - CounterMetric oemcrypto_report_usage_; - EventMetric oemcrypto_rewrap_device_rsa_key_; - EventMetric oemcrypto_rewrap_device_rsa_key_30_; + EventMetric + oemcrypto_refresh_keys_; + CounterMetric + oemcrypto_report_usage_; + EventMetric + oemcrypto_rewrap_device_rsa_key_; + EventMetric + oemcrypto_rewrap_device_rsa_key_30_; ValueMetric oemcrypto_security_patch_level_; - EventMetric oemcrypto_select_key_; + EventMetric + oemcrypto_select_key_; ValueMetric oemcrypto_usage_table_support_; - CounterMetric oemcrypto_update_usage_table_; + CounterMetric + oemcrypto_update_usage_table_; }; // This class contains session-scoped metrics. All properties and @@ -156,11 +236,12 @@ class SessionMetrics { // Sets the session id of the metrics group. This allows the session // id to be captured and reported as part of the collection of metrics. - void SetSessionId(const CdmSessionId& session_id) { - session_id_ = session_id; } + void SetSessionId(const CdmSessionId &session_id) { + session_id_ = session_id; + } // Returns the session id or an empty session id if it has not been set. - const CdmSessionId& GetSessionId() const { return session_id_; } + const CdmSessionId &GetSessionId() const { return session_id_; } // Marks the metrics object as completed and ready for serialization. void SetCompleted() { completed_ = true; } @@ -171,20 +252,23 @@ class SessionMetrics { // Returns a pointer to the crypto metrics belonging to the engine instance. // This instance retains ownership of the object. - CryptoMetrics* GetCryptoMetrics() { return &crypto_metrics_; } + CryptoMetrics *GetCryptoMetrics() { return &crypto_metrics_; } // Metrics collected at the session level. ValueMetric cdm_session_life_span_; // Milliseconds. - EventMetric cdm_session_renew_key_; - CounterMetric cdm_session_restore_offline_session_; - CounterMetric cdm_session_restore_usage_session_; + EventMetric cdm_session_renew_key_; + CounterMetric + cdm_session_restore_offline_session_; + CounterMetric + cdm_session_restore_usage_session_; // Serialize the session metrics to the provided |metric_group|. // |metric_group| is owned by the caller and must not be null. - void Serialize(drm_metrics::MetricsGroup* metric_group); + void Serialize(drm_metrics::WvCdmMetrics::SessionMetrics *session_metrics); private: - void SerializeSessionMetrics(drm_metrics::MetricsGroup* metric_group); + void SerializeSessionMetrics( + drm_metrics::WvCdmMetrics::SessionMetrics *session_metrics); CdmSessionId session_id_; bool completed_; CryptoMetrics crypto_metrics_; @@ -210,7 +294,7 @@ class OemCryptoDynamicAdapterMetrics { // Serialize the session metrics to the provided |metric_group|. // |metric_group| is owned by the caller and must not be null. - void Serialize(drm_metrics::MetricsGroup* metric_group); + void Serialize(drm_metrics::WvCdmMetrics::EngineMetrics *engine_metrics); // Clears the existing metric values. void Clear(); @@ -227,7 +311,7 @@ class OemCryptoDynamicAdapterMetrics { // initialization is guaranteed to be threadsafe. We return the reference to // avoid non-guaranteed destructor order problems. Effectively, the destructor // is never run for the created instance. -OemCryptoDynamicAdapterMetrics& GetDynamicAdapterMetricsInstance(); +OemCryptoDynamicAdapterMetrics &GetDynamicAdapterMetricsInstance(); // This class contains engine-scoped metrics. All properties and // statistics related to operations within the engine, but outside @@ -240,7 +324,7 @@ class EngineMetrics { // Add a new SessionMetrics instance and return a pointer to the caller. // The new SessionMetrics instance is owned by this EngineMetrics instance // and will exist until RemoveSession is called or this object is deleted. - SessionMetrics* AddSession(); + SessionMetrics *AddSession(); // Removes the metrics object for the given session id. This should only // be called when the SessionMetrics instance is no longer in use. @@ -249,7 +333,7 @@ class EngineMetrics { // Returns a pointer to the crypto metrics belonging to the engine instance. // The CryptoMetrics instance is still owned by this object and will exist // until this object is deleted. - CryptoMetrics* GetCryptoMetrics() { return &crypto_metrics_; } + CryptoMetrics *GetCryptoMetrics() { return &crypto_metrics_; } // Serialize engine and session metrics into a serialized MetricsGroup // instance and output that instance to the provided |metric_group|. @@ -259,44 +343,66 @@ class EngineMetrics { // |clear_sessions| indicates that this call should clear sessions metrics // for those sessions that were serialized. This allows atomic // serialization and closing of session-level metrics. - void Serialize(drm_metrics::MetricsGroup* metric_group, bool completed_only, - bool clear_serialized_sessions); + // void Serialize(drm_metrics::MetricsGroup* metric_group, bool + // completed_only, + // bool clear_serialized_sessions); + void Serialize(drm_metrics::WvCdmMetrics *engine_metrics); - void SetAppPackageName(const std::string& app_package_name); + void SetAppPackageName(const std::string &app_package_name); // Metrics recorded at the engine level. - EventMetric cdm_engine_add_key_; + EventMetric cdm_engine_add_key_; ValueMetric cdm_engine_cdm_version_; - CounterMetric cdm_engine_close_session_; + CounterMetric + cdm_engine_close_session_; ValueMetric cdm_engine_creation_time_millis_; - EventMetric cdm_engine_decrypt_; - CounterMetric cdm_engine_find_session_for_key_; - EventMetric cdm_engine_generate_key_request_; - EventMetric cdm_engine_get_provisioning_request_; - EventMetric cdm_engine_get_usage_info_; - EventMetric cdm_engine_handle_provisioning_response_; + EventMetric + cdm_engine_decrypt_; + CounterMetric + cdm_engine_find_session_for_key_; + EventMetric + cdm_engine_generate_key_request_; + EventMetric + cdm_engine_get_provisioning_request_; + CounterMetric + cdm_engine_get_secure_stop_ids_; + EventMetric + cdm_engine_get_usage_info_; + EventMetric + cdm_engine_handle_provisioning_response_; ValueMetric cdm_engine_life_span_; // Milliseconds - CounterMetric cdm_engine_open_key_set_session_; - CounterMetric cdm_engine_open_session_; - EventMetric cdm_engine_query_key_status_; - CounterMetric cdm_engine_remove_all_usage_info_; - CounterMetric cdm_engine_remove_usage_info_; - CounterMetric cdm_engine_release_usage_info_; - CounterMetric cdm_engine_get_secure_stop_ids_; - CounterMetric cdm_engine_remove_keys_; - EventMetric cdm_engine_restore_key_; - CounterMetric cdm_engine_unprovision_; + CounterMetric + cdm_engine_open_key_set_session_; + CounterMetric + cdm_engine_open_session_; + EventMetric + cdm_engine_query_key_status_; + CounterMetric + cdm_engine_release_all_usage_info_; + CounterMetric + cdm_engine_release_usage_info_; + CounterMetric + cdm_engine_remove_all_usage_info_; + CounterMetric cdm_engine_remove_keys_; + CounterMetric + cdm_engine_remove_usage_info_; + EventMetric cdm_engine_restore_key_; + CounterMetric + cdm_engine_unprovision_; private: Lock session_metrics_lock_; - std::vector session_metrics_list_; + std::vector session_metrics_list_; CryptoMetrics crypto_metrics_; std::string app_package_name_; - void SerializeEngineMetrics(drm_metrics::MetricsGroup* out); + void SerializeEngineMetrics( + drm_metrics::WvCdmMetrics::EngineMetrics *engine_metrics); }; } // namespace metrics } // namespace wvcdm -#endif // WVCDM_METRICS_METRICS_GROUP_H_ +#endif // WVCDM_METRICS_METRICS_GROUP_H_ diff --git a/libwvdrmengine/cdm/metrics/include/pow2bucket.h b/libwvdrmengine/cdm/metrics/include/pow2bucket.h new file mode 100644 index 00000000..7ab06c00 --- /dev/null +++ b/libwvdrmengine/cdm/metrics/include/pow2bucket.h @@ -0,0 +1,50 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// This file contains the declaration of the Pow2Bucket class which +// is a convenient way to bucketize sampled values into powers of 2. +#ifndef WVCDM_METRICS_POW2BUCKET_H_ +#define WVCDM_METRICS_POW2BUCKET_H_ + +namespace wvcdm { +namespace metrics { + +// This class converts the size_t value into the highest power of two +// below the value. E.g. for 7, the value is 4. For 11, the value is 8. +// This class is intended to simplify the use of EventMetric Fields that may +// have many possible values, but we want to bucket them into a small set of +// numbers (32 or 64). +class Pow2Bucket { + public: + explicit Pow2Bucket(size_t value) : value_(GetLowerBucket(value)) {} + + Pow2Bucket(const Pow2Bucket &value) : value_(value.value_) {} + + size_t value() const { return value_; } + + // Support for converting to string. + friend std::ostream &operator<<(std::ostream &os, const Pow2Bucket &log) { + return os << log.value_; + } + + private: + inline size_t GetLowerBucket(size_t value) { + if (!value) { + return 0; + } + + size_t log = 0; + while (value) { + log++; + value >>= 1; + } + + return 1u << (log - 1); + } + + size_t value_; +}; + +} // namespace metrics +} // namespace wvcdm + +#endif // WVCDM_METRICS_POW2BUCKET_H_ diff --git a/libwvdrmengine/cdm/metrics/include/value_metric.h b/libwvdrmengine/cdm/metrics/include/value_metric.h index 5c0704ef..5982439a 100644 --- a/libwvdrmengine/cdm/metrics/include/value_metric.h +++ b/libwvdrmengine/cdm/metrics/include/value_metric.h @@ -8,69 +8,44 @@ #include #include -#include "metric_serialization.h" +#include "metrics.pb.h" namespace wvcdm { namespace metrics { -// Private namespace for some helper implementation functions. +// Internal namespace for helper methods. namespace impl { -// These helper functions map the templated ValueMetric class -// Serialize call to the MetricSerializer explicit calls. -template -void Serialize(MetricSerializer* serializer, - const std::string& metric_name, const T& t); +// Helper function for setting a value in the proto. +template +void SetValue(drm_metrics::ValueMetric *value_proto, const T &value); -inline void SerializeError(MetricSerializer* serializer, - const std::string& metric_name, - const int& error_code) { - serializer->SetInt32(metric_name + "/error", error_code); -} +} // namespace impl -} // namespace impl - -// The Metric class supports storing a single value which can be overwritten. -// the Metric class also supports the MetricSerializer interface through -// which the value can be serialized. If the value was never given a value -// or an error code, then the metric will not serialize anything. +// The ValueMetric class supports storing a single, overwritable value or an +// error code. This class can be serialized to a drm_metrics::ValueMetric proto. +// If an error or value was not provided, this metric will serialize to nullptr. // // Example Usage: -// Metric cdm_version("drm/cdm/version") -// .Record("a.b.c.d"); -// -// MyMetricSerializerImpl serialzer; -// cdm_version.Serialize(&serializer); +// Metric cdm_version().Record("a.b.c.d"); +// std::unique_ptr mymetric( +// cdm_version.ToProto()); // // Example Error Usage: // -// Metric cdm_version("drm/cdm/version") -// .SetError(error_code); +// Metric cdm_version().SetError(error_code); +// std::unique_ptr mymetric( +// cdm_version.ToProto()); // -// Note that serialization is the same. But the ValueMetric will serialize -// the error code to /error instead of just . -template -class ValueMetric : public MetricSerializable { +template +class ValueMetric { public: // Constructs a metric with the given metric name. - explicit ValueMetric(const std::string& metric_name) - : metric_name_(metric_name), error_code_(0), - has_error_(false), has_value_(false) {} - - // Serialize the metric name and value using the given serializer. - // Caller owns |serializer| which cannot be null. - virtual void Serialize(MetricSerializer* serializer) { - if (has_value_) { - impl::Serialize(serializer, metric_name_, value_); - } else if (has_error_) { - impl::SerializeError(serializer, metric_name_, error_code_); - } else { - // Do nothing if there is no value and no error. - } - } + explicit ValueMetric() + : error_code_(0), has_error_(false), has_value_(false) {} // Record the value of the metric. - void Record(const T& value) { + void Record(const T &value) { value_ = value; has_value_ = true; has_error_ = false; @@ -83,8 +58,11 @@ class ValueMetric : public MetricSerializable { has_error_ = true; } - // Get the current value of the metric. - const T& GetValue() { return value_; } + bool HasValue() const { return has_value_; } + const T &GetValue() const { return value_; } + + bool HasError() const { return has_error_; } + int GetError() const { return error_code_; } // Clears the indicators that the metric or error was set. void Clear() { @@ -92,8 +70,23 @@ class ValueMetric : public MetricSerializable { has_error_ = false; } + // Returns a new ValueMetric proto containing the metric value or the + // error code. If neither the error or value are set, it returns nullptr. + drm_metrics::ValueMetric *ToProto() { + if (has_error_) { + drm_metrics::ValueMetric *value_proto = new drm_metrics::ValueMetric; + value_proto->set_error_code(error_code_); + return value_proto; + } else if (has_value_) { + drm_metrics::ValueMetric *value_proto = new drm_metrics::ValueMetric; + impl::SetValue(value_proto, value_); + return value_proto; + } + + return NULL; + } + private: - std::string metric_name_; T value_; int error_code_; bool has_error_; diff --git a/libwvdrmengine/cdm/metrics/src/attribute_handler.cpp b/libwvdrmengine/cdm/metrics/src/attribute_handler.cpp new file mode 100644 index 00000000..6f295881 --- /dev/null +++ b/libwvdrmengine/cdm/metrics/src/attribute_handler.cpp @@ -0,0 +1,89 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// This file contains implementations for the AttributeHandler. + +#include "attribute_handler.h" +#include "OEMCryptoCENC.h" +#include "pow2bucket.h" +#include "wv_cdm_types.h" + +namespace wvcdm { +namespace metrics { + +// +// Specializations for setting attribute fields. +// +template <> +void SetAttributeField(const CdmResponseType &cdm_error, + drm_metrics::Attributes *attributes) { + attributes->set_error_code(cdm_error); +} + +template <> +void SetAttributeField( + const CdmSecurityLevel &cdm_security_level, + drm_metrics::Attributes *attributes) { + attributes->set_cdm_security_level(cdm_security_level); +} + +template <> +void SetAttributeField(const SecurityLevel &security_level, + drm_metrics::Attributes *attributes) { + attributes->set_security_level(security_level); +} + +template <> +void SetAttributeField(const bool &cdm_error, + drm_metrics::Attributes *attributes) { + attributes->set_error_code_bool(cdm_error); +} + +template <> +void SetAttributeField( + const OEMCryptoResult &oem_crypto_result, + drm_metrics::Attributes *attributes) { + attributes->set_oem_crypto_result(oem_crypto_result); +} + +template <> +void SetAttributeField( + const Pow2Bucket &pow2, drm_metrics::Attributes *attributes) { + attributes->set_length(pow2.value()); +} + +template <> +void SetAttributeField( + const CdmEncryptionAlgorithm &encryption_algorithm, + drm_metrics::Attributes *attributes) { + attributes->set_encryption_algorithm(encryption_algorithm); +} + +template <> +void SetAttributeField( + const CdmSigningAlgorithm &signing_algorithm, + drm_metrics::Attributes *attributes) { + attributes->set_signing_algorithm(signing_algorithm); +} + +template <> +void SetAttributeField<0, util::Unused>(const util::Unused &, + drm_metrics::Attributes *) { + // Intentionally empty. +} + +// Specializations only used by tests. +template <> +void SetAttributeField( + const int &cdm_error, drm_metrics::Attributes *attributes) { + attributes->set_error_code(cdm_error); +} + +} // namespace metrics +} // namespace wvcdm diff --git a/libwvdrmengine/cdm/metrics/src/counter_metric.cpp b/libwvdrmengine/cdm/metrics/src/counter_metric.cpp index 5f561a74..6bf9f807 100644 --- a/libwvdrmengine/cdm/metrics/src/counter_metric.cpp +++ b/libwvdrmengine/cdm/metrics/src/counter_metric.cpp @@ -5,29 +5,21 @@ #include "counter_metric.h" +#include "metrics.pb.h" + namespace wvcdm { namespace metrics { -void BaseCounterMetric::Increment(const std::string& field_names_values, +void BaseCounterMetric::Increment(const std::string &counter_key, int64_t value) { AutoLock lock(internal_lock_); - if (value_map_.find(field_names_values) == value_map_.end()) { - value_map_[field_names_values] = value; + if (value_map_.find(counter_key) == value_map_.end()) { + value_map_[counter_key] = value; } else { - value_map_[field_names_values] = value_map_[field_names_values] + value; - } -} - -void BaseCounterMetric::Serialize(MetricSerializer* serializer) { - AutoLock lock(internal_lock_); - - for (std::map::iterator it - = value_map_.begin(); it != value_map_.end(); it++) { - serializer->SetInt64(metric_name_ + "/count" + it->first, it->second); + value_map_[counter_key] = value_map_[counter_key] + value; } } } // namespace metrics } // namespace wvcdm - diff --git a/libwvdrmengine/cdm/metrics/src/distribution.cpp b/libwvdrmengine/cdm/metrics/src/distribution.cpp index 378e75ff..0a4cb882 100644 --- a/libwvdrmengine/cdm/metrics/src/distribution.cpp +++ b/libwvdrmengine/cdm/metrics/src/distribution.cpp @@ -9,20 +9,19 @@ namespace wvcdm { namespace metrics { -Distribution::Distribution() : - count_(0LL), - min_(DBL_MAX), - max_(-DBL_MAX), - mean_(0.0), - sum_squared_deviation_(0.0) { -} +Distribution::Distribution() + : count_(0ULL), + min_(FLT_MAX), + max_(-FLT_MAX), + mean_(0.0), + sum_squared_deviation_(0.0) {} -void Distribution::Record(double value) { +void Distribution::Record(float value) { // Using method of provisional means. - double deviation = value - mean_; + float deviation = value - mean_; mean_ = mean_ + (deviation / ++count_); sum_squared_deviation_ = - sum_squared_deviation_ + (deviation * (value - mean_)); + sum_squared_deviation_ + (deviation * (value - mean_)); min_ = min_ < value ? min_ : value; max_ = max_ > value ? max_ : value; @@ -30,4 +29,3 @@ void Distribution::Record(double value) { } // namespace metrics } // namespace wvcdm - diff --git a/libwvdrmengine/cdm/metrics/src/event_metric.cpp b/libwvdrmengine/cdm/metrics/src/event_metric.cpp index 06e2ac51..309a19bf 100644 --- a/libwvdrmengine/cdm/metrics/src/event_metric.cpp +++ b/libwvdrmengine/cdm/metrics/src/event_metric.cpp @@ -4,60 +4,34 @@ #include "event_metric.h" +using ::google::protobuf::RepeatedPtrField; + namespace wvcdm { namespace metrics { BaseEventMetric::~BaseEventMetric() { AutoLock lock(internal_lock_); - for (std::map::iterator it - = value_map_.begin(); it != value_map_.end(); it++) { + for (std::map::iterator it = value_map_.begin(); + it != value_map_.end(); it++) { delete it->second; } } -void BaseEventMetric::Record(const std::string& field_names_values, - double value) { +void BaseEventMetric::Record(const std::string &key, double value) { AutoLock lock(internal_lock_); - Distribution* distribution; + Distribution *distribution; - if (value_map_.find(field_names_values) == value_map_.end()) { + if (value_map_.find(key) == value_map_.end()) { distribution = new Distribution(); - value_map_[field_names_values] = distribution; + value_map_[key] = distribution; } else { - distribution = value_map_[field_names_values]; + distribution = value_map_[key]; } distribution->Record(value); } -void BaseEventMetric::Serialize(MetricSerializer* serializer) { - AutoLock lock(internal_lock_); - - for (std::map::iterator it - = value_map_.begin(); it != value_map_.end(); it++) { - serializer->SetInt64( - metric_name_ + "/count" + it->first, - it->second->Count()); - serializer->SetDouble( - metric_name_ + "/mean" + it->first, - it->second->Mean()); - // Only publish additional information if there was more than one sample. - if (it->second->Count() > 1) { - serializer->SetDouble( - metric_name_ + "/variance" + it->first, - it->second->Variance()); - serializer->SetDouble( - metric_name_ + "/min" + it->first, - it->second->Min()); - serializer->SetDouble( - metric_name_ + "/max" + it->first, - it->second->Max()); - } - } -} - } // namespace metrics } // namespace wvcdm - diff --git a/libwvdrmengine/cdm/metrics/src/metrics.proto b/libwvdrmengine/cdm/metrics/src/metrics.proto index 02c5af24..60c65d1d 100644 --- a/libwvdrmengine/cdm/metrics/src/metrics.proto +++ b/libwvdrmengine/cdm/metrics/src/metrics.proto @@ -9,31 +9,206 @@ package drm_metrics; // need this if we are using libprotobuf-cpp-2.3.0-lite option optimize_for = LITE_RUNTIME; -// The MetricsGroup is a collection of metric name/value pair instances -// that can be serialized and provided to a caller. -message MetricsGroup { - message Metric { - message MetricValue { - // Only one of the following values must be set. Note that the oneof - // keyword is not supported in the protobuf version checked into the CDM. - optional int64 int_value = 1; - optional double double_value = 2; - optional string string_value = 3; - } +// The Attributes message is used to contain values associated with the +// metric that was captured. E.g. if we're capturing a counter value, the +// Attributes will contain the values assocated with that counter. E.g. we may +// want to count all of the operations with a give error code. +message Attributes { + // Reserved for compatibility with logging proto. + // TODO(blueeyes): The reserved keyword is not supported in the older version + // of protoc in the CE CDM third_party directory. Uncomment the reserved + // line when we upgrade. b/67016366. + // reserved 8, 10 to 13; - // The name of the metric. Must be valid UTF-8. Required. - optional string name = 1; + // The error code. See CdmResponseType in wv_cdm_types.h + optional int32 error_code = 1; + // The status of the processed data. Some methods has a bool error code + // rather than a CdmResponseType error code. True if it succeeds, and + // false if it fails. + optional bool error_code_bool = 2; + // The CdmSecurityLevel. Defined in wv_cdm_types.h + optional uint32 cdm_security_level = 3; + // The SecurityLevel. Defined in wv_cdm_types.h. + optional uint32 security_level = 4; + // The length in bytes. + optional uint64 length = 5; + // The CDM encryption algorithm. It can be "AES-CBC-128" or unknown. See + // CdmEncryptionAlgorithm in wv_cdm_types.h + optional uint32 encryption_algorithm = 6; + // The CDM signing algorithm. It can be "HMACSHA256" or unknown. See + // CdmSigningAlgorithm in wv_cdm_types.h + optional uint32 signing_algorithm = 7; + // The OEM crypto result. See OEMCryptoResult in OEMCryptoCENC.h + optional int32 oem_crypto_result = 9; + // Defined at ::android::hardware::drm::V1_0::KeyStatusType; + optional uint32 key_status_type = 14; + // Defined at ::android::hardware::drm::V1_0::EventType; + optional uint32 event_type = 15; +} - // The value of the metric. Required. - optional MetricValue value = 2; +// The Counter message is used to store a count value with an associated +// Attribute. +message CounterMetric { + optional int64 count = 1; + // Represents the attributes associated with this counter instance. + optional Attributes attributes = 2; +} + +// The DistributionMetric is meant to capture the moments of a normally +// distributed (or approximately normal) value. +message DistributionMetric { + optional float min = 1; + optional float max = 2; + optional float mean = 3; + optional double variance = 4; + optional uint64 operation_count = 5; + + // Represents the attributes assocated with this distribution metric + // instance. + optional Attributes attributes = 6; +} + +// ValueMetric represents either a single value or an error. +message ValueMetric { + // Only one of the following values should be set for the given metric. + optional int32 error_code = 1; + optional int64 int_value = 2; + optional double double_value = 3; + optional string string_value = 4; +} + + +// This message contains the specific metrics captured by DrmMetrics. It is +// used for serializing and logging metrics. +// next id: 3. +message WvCdmMetrics { + // Attributes are associated with a recorded value. E.g. A counter may + // represent a count of an operation returning a specific error code. The + // error code will be an attribute. + + // This contains metrics that were captured at the CryptoSession level. These + // include CryptoSession metrics and most OEMCrypto metrics. + // next id: 56 + message CryptoMetrics { + // Crypto Session Metrics. + optional ValueMetric crypto_session_security_level = 1; + repeated CounterMetric crypto_session_delete_all_usage_reports = 2; + repeated CounterMetric crypto_session_delete_multiple_usage_information = 3; + repeated DistributionMetric crypto_session_generic_decrypt_time_us = 4; + repeated DistributionMetric crypto_session_generic_encrypt_time_us = 5; + repeated DistributionMetric crypto_session_generic_sign_time_us = 6; + repeated DistributionMetric crypto_session_generic_verify_time_us = 7; + repeated CounterMetric crypto_session_get_device_unique_id = 8; + repeated CounterMetric crypto_session_get_token = 9; + optional ValueMetric crypto_session_life_span = 10; + repeated DistributionMetric crypto_session_load_certificate_private_key_time_us = 11; + repeated DistributionMetric crypto_session_open_time_us = 12; + optional ValueMetric crypto_session_system_id = 13; + repeated DistributionMetric crypto_session_update_usage_information_time_us = 14; + optional ValueMetric crypto_session_usage_information_support = 15; + // OemCrypto metrics. + optional ValueMetric oemcrypto_api_version = 16; + repeated CounterMetric oemcrypto_close_session = 17; + repeated DistributionMetric oemcrypto_copy_buffer_time_us = 18; + optional ValueMetric oemcrypto_current_hdcp_capability = 19; + repeated CounterMetric oemcrypto_deactivate_usage_entry = 20; + repeated DistributionMetric oemcrypto_decrypt_cenc_time_us = 21; + repeated CounterMetric oemcrypto_delete_usage_entry = 22; + repeated CounterMetric oemcrypto_delete_usage_table = 23; + repeated DistributionMetric oemcrypto_derive_keys_from_session_key_time_us = 24; + repeated CounterMetric oemcrypto_force_delete_usage_entry = 25; + repeated DistributionMetric oemcrypto_generate_derived_keys_time_us = 26; + repeated CounterMetric oemcrypto_generate_nonce = 27; + repeated DistributionMetric oemcrypto_generate_rsa_signature_time_us = 28; + repeated DistributionMetric oemcrypto_generate_signature_time_us = 29; + repeated DistributionMetric oemcrypto_generic_decrypt_time_us = 30; + repeated DistributionMetric oemcrypto_generic_encrypt_time_us = 31; + repeated DistributionMetric oemcrypto_generic_sign_time_us = 32; + repeated DistributionMetric oemcrypto_generic_verify_time_us = 33; + repeated CounterMetric oemcrypto_get_device_id = 34; + repeated DistributionMetric oemcrypto_get_key_data_time_us = 35; + repeated CounterMetric oemcrypto_get_oem_public_certificate = 36; + repeated CounterMetric oemcrypto_get_random = 37; + repeated DistributionMetric oemcrypto_initialize_time_us = 38; + optional ValueMetric oemcrypto_is_anti_rollback_hw_present = 39; + optional ValueMetric oemcrypto_is_keybox_valid = 40; + repeated DistributionMetric oemcrypto_load_device_rsa_key_time_us = 41; + repeated DistributionMetric oemcrypto_load_entitled_keys_time_us = 42; + repeated DistributionMetric oemcrypto_load_keys_time_us = 43; + optional ValueMetric oemcrypto_max_hdcp_capability = 44; + optional ValueMetric oemcrypto_max_number_of_sessions = 45; + optional ValueMetric oemcrypto_number_of_open_sessions = 46; + optional ValueMetric oemcrypto_provisioning_method = 47; + repeated DistributionMetric oemcrypto_refresh_keys_time_us = 48; + repeated CounterMetric oemcrypto_report_usage = 49; + repeated DistributionMetric oemcrypto_rewrap_device_rsa_key_time_us = 50; + repeated DistributionMetric oemcrypto_rewrap_device_rsa_key_30_time_us = 51; + optional ValueMetric oemcrypto_security_patch_level = 52; + repeated DistributionMetric oemcrypto_select_key_time_us = 53; + optional ValueMetric oemcrypto_usage_table_support = 54; + repeated CounterMetric oemcrypto_update_usage_table = 55; } - // The list of name/value pairs of metrics. - repeated Metric metric = 1; + // This contains metrics that were captured within a CdmSession. This contains + // nested CryptoMetrics that were captured in the context of the session. + // next id: 7 + message SessionMetrics { + optional ValueMetric session_id = 1; + optional CryptoMetrics crypto_metrics = 2; + optional ValueMetric cdm_session_life_span_ms = 3; + repeated DistributionMetric cdm_session_renew_key_time_us = 4; + repeated CounterMetric cdm_session_restore_offline_session = 5; + repeated CounterMetric cdm_session_restore_usage_session = 6; + } - // Allow multiple sub groups of metrics. - repeated MetricsGroup metric_sub_group = 2; + // These are metrics recorded at the Engine level. This includes CryptoSession + // metrics that were captured in the context of the engine. + // next id: 29 + message EngineMetrics { + optional CryptoMetrics crypto_metrics = 1; - // Name of the application package associated with the metrics. - optional string app_package_name = 3; + // OEMCrypto Initialize Metrics. + optional ValueMetric oemcrypto_initialization_mode = 3; + optional ValueMetric oemcrypto_l1_api_version = 4; + optional ValueMetric oemcrypto_l1_min_api_version = 5; + // CdmEngine Metrics. + optional ValueMetric app_package_name = 6; + repeated DistributionMetric cdm_engine_add_key_time_us = 7; + optional ValueMetric cdm_engine_cdm_version = 8; + repeated CounterMetric cdm_engine_close_session = 9; + optional ValueMetric cdm_engine_creation_time_millis = 10; + repeated DistributionMetric cdm_engine_decrypt_time_us = 11; + repeated CounterMetric cdm_engine_find_session_for_key = 12; + repeated DistributionMetric cdm_engine_generate_key_request_time_us = 13; + repeated DistributionMetric cdm_engine_get_provisioning_request_time_us = 14; + repeated CounterMetric cdm_engine_get_secure_stop_ids = 15; + repeated DistributionMetric cdm_engine_get_usage_info_time_us = 16; + repeated DistributionMetric cdm_engine_handle_provisioning_response_time_us = 17; + optional ValueMetric cdm_engine_life_span = 18; + repeated CounterMetric cdm_engine_open_key_set_session = 19; + repeated CounterMetric cdm_engine_open_session = 20; + repeated DistributionMetric cdm_engine_query_key_status_time_us = 21; + repeated CounterMetric cdm_engine_release_all_usage_info = 22; + repeated CounterMetric cdm_engine_release_usage_info = 23; + repeated CounterMetric cdm_engine_remove_all_usage_info = 24; + repeated CounterMetric cdm_engine_remove_keys = 25; + repeated CounterMetric cdm_engine_remove_usage_info = 26; + repeated DistributionMetric cdm_engine_restore_key_time_us = 27; + repeated CounterMetric cdm_engine_unprovision = 28; + } + + optional EngineMetrics engine_metrics = 1; + repeated SessionMetrics session_metrics = 2; +} + +// This message contains a collection of metrics, one per CDM engine instance. +message WvCdmMetricsGroup { + repeated WvCdmMetrics metrics = 1; +} + +// Test message to support unit testing. +message TestMetrics{ + optional ValueMetric test_value_metric = 1; + repeated CounterMetric test_counters = 3; + repeated DistributionMetric test_distributions = 2; } diff --git a/libwvdrmengine/cdm/metrics/src/metrics_collections.cpp b/libwvdrmengine/cdm/metrics/src/metrics_collections.cpp index 4861f6d3..7b3e4d93 100644 --- a/libwvdrmengine/cdm/metrics/src/metrics_collections.cpp +++ b/libwvdrmengine/cdm/metrics/src/metrics_collections.cpp @@ -7,333 +7,179 @@ #include "log.h" #include "metrics.pb.h" -using drm_metrics::MetricsGroup; -using wvcdm::metrics::MetricSerializer; +using ::drm_metrics::Attributes; +using ::drm_metrics::WvCdmMetrics; +using ::google::protobuf::RepeatedPtrField; +using ::wvcdm::metrics::EventMetric; namespace { // Helper struct for comparing session ids. struct CompareSessionIds { - const std::string& target_; + const std::string &target_; - CompareSessionIds(const wvcdm::CdmSessionId& target) : target_(target) {}; + CompareSessionIds(const wvcdm::CdmSessionId &target) : target_(target){}; - bool operator()(const wvcdm::metrics::SessionMetrics* metrics) const { + bool operator()(const wvcdm::metrics::SessionMetrics *metrics) const { return metrics->GetSessionId() == target_; } }; -// Local class used to serialize to the MetricsGroup proto message. -class ProtoMetricSerializer : public wvcdm::metrics::MetricSerializer { - public: - ProtoMetricSerializer(MetricsGroup* metric_group) - : metric_group_(metric_group) {} - - virtual void SetString(const std::string& metric_id, - const std::string& value) { - MetricsGroup::Metric* metric = metric_group_->add_metric(); - metric->set_name(metric_id); - metric->mutable_value()->set_string_value(value); - } - - virtual void SetInt32(const std::string& metric_id, int32_t value) { - MetricsGroup::Metric* metric = metric_group_->add_metric(); - metric->set_name(metric_id); - metric->mutable_value()->set_int_value(value); - } - - virtual void SetInt64(const std::string& metric_id, int64_t value) { - MetricsGroup::Metric* metric = metric_group_->add_metric(); - metric->set_name(metric_id); - metric->mutable_value()->set_int_value(value); - } - - virtual void SetDouble(const std::string& metric_id, double value) { - MetricsGroup::Metric* metric = metric_group_->add_metric(); - metric->set_name(metric_id); - metric->mutable_value()->set_double_value(value); - } - - private: - MetricsGroup* metric_group_; -}; - } // anonymous namespace namespace wvcdm { namespace metrics { -CryptoMetrics::CryptoMetrics() : - crypto_session_security_level_( - "/drm/widevine/crypto_session/security_level"), - crypto_session_delete_all_usage_reports_( - "/drm/widevine/crypto_session/delete_all_usage_reports", - "error"), - crypto_session_delete_multiple_usage_information_( - "/drm/widevine/crypto_session/delete_multiple_usage_information", - "error"), - crypto_session_generic_decrypt_( - "/drm/widevine/crypto_session/generic_decrypt/time", - "error", - "length", - "encryption_algorithm"), - crypto_session_generic_encrypt_( - "/drm/widevine/crypto_session/generic_encrypt/time", - "error", - "length", - "encryption_algorithm"), - crypto_session_generic_sign_( - "/drm/widevine/crypto_session/generic_sign/time", - "error", - "length", - "signing_algorithm"), - crypto_session_generic_verify_( - "/drm/widevine/crypto_session/generic_verify/time", - "error", - "length", - "signing_algorithm"), - crypto_session_get_device_unique_id_( - "/drm/widevine/crypto_session/get_device_unique_id", - "success"), - crypto_session_get_token_( - "/drm/widevine/crypto_session/get_token", - "success"), - crypto_session_life_span_( - "/drm/widevine/crypto_session/life_span"), - crypto_session_load_certificate_private_key_( - "/drm/widevine/crypto_session/load_certificate_private_key/time", - "success"), - crypto_session_open_( - "/drm/widevine/crypto_session/open/time", - "error", - "requested_security_level"), - crypto_session_system_id_( - "/drm/widevine/crypto_session/system_id"), - crypto_session_update_usage_information_( - "/drm/widevine/crypto_session/update_usage_information/time", - "error"), - crypto_session_usage_information_support_( - "/drm/widevine/crypto_session/usage_information_support"), - oemcrypto_api_version_( - "/drm/widevine/oemcrypto/api_version"), - oemcrypto_close_session_( - "/drm/widevine/oemcrypto/close_session", - "oemcrypto_error"), - oemcrypto_copy_buffer_( - "/drm/widevine/oemcrypto/copy_buffer/time", - "oemcrypto_error", - "length"), - oemcrypto_current_hdcp_capability_( - "/drm/widevine/oemcrypto/current_hdcp_capability"), - oemcrypto_deactivate_usage_entry_( - "/drm/widevine/oemcrypto/deactivate_usage_entry", - "oemcrypto_error"), - oemcrypto_decrypt_cenc_( - "/drm/widevine/oemcrypto/decrypt_cenc/time", - "oemcrypto_error", - "length"), - oemcrypto_delete_usage_entry_( - "/drm/widevine/oemcrypto/delete_usage_entry", - "oemcrypto_error"), - oemcrypto_delete_usage_table_( - "/drm/widevine/oemcrypto/delete_usage_table", - "oemcrypto_error"), - oemcrypto_derive_keys_from_session_key_( - "/drm/widevine/oemcrypto/derive_keys_from_session_key/time", - "oemcrypto_error"), - oemcrypto_force_delete_usage_entry_( - "/drm/widevine/oemcrypto/force_delete_usage_entry", - "oemcrypto_error"), - oemcrypto_generate_derived_keys_( - "/drm/widevine/oemcrypto/generate_derived_keys/time", - "oemcrypto_error"), - oemcrypto_generate_nonce_( - "/drm/widevine/oemcrypto/generate_nonce", - "oemcrypto_error"), - oemcrypto_generate_rsa_signature_( - "/drm/widevine/oemcrypto/generate_rsa_signature/time", - "oemcrypto_error", - "length"), - oemcrypto_generate_signature_( - "/drm/widevine/oemcrypto/generate_signature/time", - "oemcrypto_error", - "length"), - oemcrypto_generic_decrypt_( - "/drm/widevine/oemcrypto/generic_decrypt/time", - "oemcrypto_error", - "length"), - oemcrypto_generic_encrypt_( - "/drm/widevine/oemcrypto/generic_encrypt/time", - "oemcrypto_error", - "length"), - oemcrypto_generic_sign_( - "/drm/widevine/oemcrypto/generic_sign/time", - "oemcrypto_error", - "length"), - oemcrypto_generic_verify_( - "/drm/widevine/oemcrypto/generic_verify/time", - "oemcrypto_error", - "length"), - oemcrypto_get_device_id_( - "/drm/widevine/oemcrypto/get_device_id", - "oemcrypto_error"), - oemcrypto_get_key_data_( - "/drm/widevine/oemcrypto/get_key_data/time", - "oemcrypto_error", - "length"), - oemcrypto_get_oem_public_certificate_( - "/drm/widevine/oemcrypto/get_oem_public_certificate", - "oemcrypto_error"), - oemcrypto_get_random_( - "/drm/widevine/oemcrypto/get_random", - "oemcrypto_error"), - oemcrypto_initialize_( - "/drm/widevine/oemcrypto/initialize/time", - "oemcrypto_error"), - oemcrypto_is_anti_rollback_hw_present_( - "/drm/widevine/oemcrypto/is_anti_rollback_hw_present"), - oemcrypto_is_keybox_valid_( - "/drm/widevine/oemcrypto/is_keybox_valid"), - oemcrypto_load_device_rsa_key_( - "/drm/widevine/oemcrypto/load_device_rsa_key/time", - "oemcrypto_error"), - oemcrypto_load_entitled_keys_( - "/drm/widevine/oemcrypto/load_entitled_keys/time", - "oemcrypto_error"), - oemcrypto_load_keys_( - "/drm/widevine/oemcrypto/load_keys/time", - "oemcrypto_error"), - oemcrypto_max_hdcp_capability_( - "/drm/widevine/oemcrypto/max_hdcp_capability"), - oemcrypto_max_number_of_sessions_( - "/drm/widevine/oemcrypto/max_number_of_sessions"), - oemcrypto_number_of_open_sessions_( - "/drm/widevine/oemcrypto/number_of_open_sessions"), - oemcrypto_provisioning_method_( - "/drm/widevine/oemcrypto/provisioning_method"), - oemcrypto_refresh_keys_( - "/drm/widevine/oemcrypto/refresh_keys/time", - "oemcrypto_error"), - oemcrypto_report_usage_( - "/drm/widevine/oemcrypto/report_usage", - "oemcrypto_error"), - oemcrypto_rewrap_device_rsa_key_( - "/drm/widevine/oemcrypto/rewrap_device_rsa_key/time", - "oemcrypto_error"), - oemcrypto_rewrap_device_rsa_key_30_( - "/drm/widevine/oemcrypto/rewrap_device_rsa_key_30/time", - "oemcrypto_error"), - oemcrypto_security_patch_level_( - "/drm/widevine/oemcrypto/security_patch_level"), - oemcrypto_select_key_( - "/drm/widevine/oemcrypto/select_key/time", - "oemcrypto_error"), - oemcrypto_usage_table_support_( - "/drm/widevine/oemcrypto/usage_table_support"), - oemcrypto_update_usage_table_( - "/drm/widevine/oemcrypto/update_usage_table", - "oemcrypto_error") { -} - -void CryptoMetrics::Serialize(MetricsGroup* metrics) { - ProtoMetricSerializer serializer(metrics); +void CryptoMetrics::Serialize(WvCdmMetrics::CryptoMetrics *crypto_metrics) { /* CRYPTO SESSION */ - crypto_session_security_level_.Serialize(&serializer); - crypto_session_delete_all_usage_reports_.Serialize(&serializer); - crypto_session_delete_multiple_usage_information_.Serialize(&serializer); - crypto_session_generic_decrypt_.Serialize(&serializer); - crypto_session_generic_encrypt_.Serialize(&serializer); - crypto_session_generic_sign_.Serialize(&serializer); - crypto_session_generic_verify_.Serialize(&serializer); - crypto_session_get_device_unique_id_.Serialize(&serializer); - crypto_session_get_token_.Serialize(&serializer); - crypto_session_life_span_.Serialize(&serializer); - crypto_session_load_certificate_private_key_.Serialize(&serializer); - crypto_session_open_.Serialize(&serializer); - crypto_session_system_id_.Serialize(&serializer); - crypto_session_update_usage_information_.Serialize(&serializer); - crypto_session_usage_information_support_.Serialize(&serializer); + crypto_metrics->set_allocated_crypto_session_security_level( + crypto_session_security_level_.ToProto()); + crypto_session_delete_all_usage_reports_.ToProto( + crypto_metrics->mutable_crypto_session_delete_all_usage_reports()); + crypto_session_delete_multiple_usage_information_.ToProto( + crypto_metrics + ->mutable_crypto_session_delete_multiple_usage_information()); + crypto_session_generic_decrypt_.ToProto( + crypto_metrics->mutable_crypto_session_generic_decrypt_time_us()); + crypto_session_generic_encrypt_.ToProto( + crypto_metrics->mutable_crypto_session_generic_encrypt_time_us()); + crypto_session_generic_sign_.ToProto( + crypto_metrics->mutable_crypto_session_generic_sign_time_us()); + crypto_session_generic_verify_.ToProto( + crypto_metrics->mutable_crypto_session_generic_verify_time_us()); + crypto_session_get_device_unique_id_.ToProto( + crypto_metrics->mutable_crypto_session_get_device_unique_id()); + crypto_session_get_token_.ToProto( + crypto_metrics->mutable_crypto_session_get_token()); + crypto_metrics->set_allocated_crypto_session_life_span( + crypto_session_life_span_.ToProto()); + crypto_session_load_certificate_private_key_.ToProto( + crypto_metrics + ->mutable_crypto_session_load_certificate_private_key_time_us()); + crypto_session_open_.ToProto( + crypto_metrics->mutable_crypto_session_open_time_us()); + crypto_metrics->set_allocated_crypto_session_system_id( + crypto_session_system_id_.ToProto()); + crypto_session_update_usage_information_.ToProto( + crypto_metrics + ->mutable_crypto_session_update_usage_information_time_us()); + crypto_metrics->set_allocated_crypto_session_usage_information_support( + crypto_session_usage_information_support_.ToProto()); /* OEMCRYPTO */ - oemcrypto_api_version_.Serialize(&serializer); - oemcrypto_close_session_.Serialize(&serializer); - oemcrypto_copy_buffer_.Serialize(&serializer); - oemcrypto_current_hdcp_capability_.Serialize(&serializer); - oemcrypto_deactivate_usage_entry_.Serialize(&serializer); - oemcrypto_decrypt_cenc_.Serialize(&serializer); - oemcrypto_delete_usage_entry_.Serialize(&serializer); - oemcrypto_delete_usage_table_.Serialize(&serializer); - oemcrypto_derive_keys_from_session_key_.Serialize(&serializer); - oemcrypto_force_delete_usage_entry_.Serialize(&serializer); - oemcrypto_generate_derived_keys_.Serialize(&serializer); - oemcrypto_generate_nonce_.Serialize(&serializer); - oemcrypto_generate_rsa_signature_.Serialize(&serializer); - oemcrypto_generate_signature_.Serialize(&serializer); - oemcrypto_generic_decrypt_.Serialize(&serializer); - oemcrypto_generic_encrypt_.Serialize(&serializer); - oemcrypto_generic_sign_.Serialize(&serializer); - oemcrypto_generic_verify_.Serialize(&serializer); - oemcrypto_get_device_id_.Serialize(&serializer); - oemcrypto_get_key_data_.Serialize(&serializer); - oemcrypto_get_oem_public_certificate_.Serialize(&serializer); - oemcrypto_get_random_.Serialize(&serializer); - oemcrypto_initialize_.Serialize(&serializer); - oemcrypto_is_anti_rollback_hw_present_.Serialize(&serializer); - oemcrypto_is_keybox_valid_.Serialize(&serializer); - oemcrypto_load_device_rsa_key_.Serialize(&serializer); - oemcrypto_load_entitled_keys_.Serialize(&serializer); - oemcrypto_load_keys_.Serialize(&serializer); - oemcrypto_max_hdcp_capability_.Serialize(&serializer); - oemcrypto_max_number_of_sessions_.Serialize(&serializer); - oemcrypto_number_of_open_sessions_.Serialize(&serializer); - oemcrypto_provisioning_method_.Serialize(&serializer); - oemcrypto_refresh_keys_.Serialize(&serializer); - oemcrypto_report_usage_.Serialize(&serializer); - oemcrypto_rewrap_device_rsa_key_.Serialize(&serializer); - oemcrypto_rewrap_device_rsa_key_30_.Serialize(&serializer); - oemcrypto_security_patch_level_.Serialize(&serializer); - oemcrypto_select_key_.Serialize(&serializer); - oemcrypto_usage_table_support_.Serialize(&serializer); - oemcrypto_update_usage_table_.Serialize(&serializer); + crypto_metrics->set_allocated_oemcrypto_api_version( + oemcrypto_api_version_.ToProto()); + oemcrypto_close_session_.ToProto( + crypto_metrics->mutable_oemcrypto_close_session()); + oemcrypto_copy_buffer_.ToProto( + crypto_metrics->mutable_oemcrypto_copy_buffer_time_us()); + crypto_metrics->set_allocated_oemcrypto_current_hdcp_capability( + oemcrypto_current_hdcp_capability_.ToProto()); + oemcrypto_deactivate_usage_entry_.ToProto( + crypto_metrics->mutable_oemcrypto_deactivate_usage_entry()); + oemcrypto_decrypt_cenc_.ToProto( + crypto_metrics->mutable_oemcrypto_decrypt_cenc_time_us()); + oemcrypto_delete_usage_entry_.ToProto( + crypto_metrics->mutable_oemcrypto_delete_usage_entry()); + oemcrypto_delete_usage_table_.ToProto( + crypto_metrics->mutable_oemcrypto_delete_usage_table()); + oemcrypto_derive_keys_from_session_key_.ToProto( + crypto_metrics->mutable_oemcrypto_derive_keys_from_session_key_time_us()); + oemcrypto_force_delete_usage_entry_.ToProto( + crypto_metrics->mutable_oemcrypto_force_delete_usage_entry()); + oemcrypto_generate_derived_keys_.ToProto( + crypto_metrics->mutable_oemcrypto_generate_derived_keys_time_us()); + oemcrypto_generate_nonce_.ToProto( + crypto_metrics->mutable_oemcrypto_generate_nonce()); + oemcrypto_generate_rsa_signature_.ToProto( + crypto_metrics->mutable_oemcrypto_generate_rsa_signature_time_us()); + oemcrypto_generate_signature_.ToProto( + crypto_metrics->mutable_oemcrypto_generate_signature_time_us()); + oemcrypto_generic_decrypt_.ToProto( + crypto_metrics->mutable_oemcrypto_generic_decrypt_time_us()); + oemcrypto_generic_encrypt_.ToProto( + crypto_metrics->mutable_oemcrypto_generic_encrypt_time_us()); + oemcrypto_generic_sign_.ToProto( + crypto_metrics->mutable_oemcrypto_generic_sign_time_us()); + oemcrypto_generic_verify_.ToProto( + crypto_metrics->mutable_oemcrypto_generic_verify_time_us()); + oemcrypto_get_device_id_.ToProto( + crypto_metrics->mutable_oemcrypto_get_device_id()); + oemcrypto_get_key_data_.ToProto( + crypto_metrics->mutable_oemcrypto_get_key_data_time_us()); + oemcrypto_get_oem_public_certificate_.ToProto( + crypto_metrics->mutable_oemcrypto_get_oem_public_certificate()); + oemcrypto_get_random_.ToProto(crypto_metrics->mutable_oemcrypto_get_random()); + oemcrypto_initialize_.ToProto( + crypto_metrics->mutable_oemcrypto_initialize_time_us()); + crypto_metrics->set_allocated_oemcrypto_is_anti_rollback_hw_present( + oemcrypto_is_anti_rollback_hw_present_.ToProto()); + crypto_metrics->set_allocated_oemcrypto_is_keybox_valid( + oemcrypto_is_keybox_valid_.ToProto()); + oemcrypto_load_device_rsa_key_.ToProto( + crypto_metrics->mutable_oemcrypto_load_device_rsa_key_time_us()); + oemcrypto_load_entitled_keys_.ToProto( + crypto_metrics->mutable_oemcrypto_load_entitled_keys_time_us()); + oemcrypto_load_keys_.ToProto( + crypto_metrics->mutable_oemcrypto_load_keys_time_us()); + crypto_metrics->set_allocated_oemcrypto_max_hdcp_capability( + oemcrypto_max_hdcp_capability_.ToProto()); + crypto_metrics->set_allocated_oemcrypto_max_number_of_sessions( + oemcrypto_max_number_of_sessions_.ToProto()); + crypto_metrics->set_allocated_oemcrypto_number_of_open_sessions( + oemcrypto_number_of_open_sessions_.ToProto()); + crypto_metrics->set_allocated_oemcrypto_provisioning_method( + oemcrypto_provisioning_method_.ToProto()); + oemcrypto_refresh_keys_.ToProto( + crypto_metrics->mutable_oemcrypto_refresh_keys_time_us()); + oemcrypto_report_usage_.ToProto( + crypto_metrics->mutable_oemcrypto_report_usage()); + oemcrypto_rewrap_device_rsa_key_.ToProto( + crypto_metrics->mutable_oemcrypto_rewrap_device_rsa_key_time_us()); + oemcrypto_rewrap_device_rsa_key_30_.ToProto( + crypto_metrics->mutable_oemcrypto_rewrap_device_rsa_key_30_time_us()); + crypto_metrics->set_allocated_oemcrypto_security_patch_level( + oemcrypto_security_patch_level_.ToProto()); + oemcrypto_select_key_.ToProto( + crypto_metrics->mutable_oemcrypto_select_key_time_us()); + crypto_metrics->set_allocated_oemcrypto_usage_table_support( + oemcrypto_usage_table_support_.ToProto()); + oemcrypto_update_usage_table_.ToProto( + crypto_metrics->mutable_oemcrypto_update_usage_table()); } -SessionMetrics::SessionMetrics() : - cdm_session_life_span_( - "/drm/widevine/cdm_session/life_span"), - cdm_session_renew_key_( - "/drm/widevine/cdm_session/renew_key/time", - "error"), - cdm_session_restore_offline_session_( - "/drm/widevine/cdm_session/restore_offline_session", - "error"), - cdm_session_restore_usage_session_( - "/drm/widevine/cdm_session/restore_usage_session", - "error"), - completed_(false) { +SessionMetrics::SessionMetrics() + : cdm_session_life_span_(), + cdm_session_renew_key_(), + cdm_session_restore_offline_session_(), + cdm_session_restore_usage_session_(), + completed_(false) {} + +void SessionMetrics::Serialize(WvCdmMetrics::SessionMetrics *session_metrics) { + SerializeSessionMetrics(session_metrics); + crypto_metrics_.Serialize(session_metrics->mutable_crypto_metrics()); } -void SessionMetrics::Serialize(MetricsGroup* metric_group) { - SerializeSessionMetrics(metric_group); - crypto_metrics_.Serialize(metric_group); +void SessionMetrics::SerializeSessionMetrics( + WvCdmMetrics::SessionMetrics *session_metrics) { + // If the session id was set, add it to the metrics. It's possible that + // it's not set in some circumstances such as when provisioning is needed. + if (!session_id_.empty()) { + session_metrics->mutable_session_id()->set_string_value(session_id_); + } + session_metrics->set_allocated_cdm_session_life_span_ms( + cdm_session_life_span_.ToProto()); + cdm_session_renew_key_.ToProto( + session_metrics->mutable_cdm_session_renew_key_time_us()); + cdm_session_restore_offline_session_.ToProto( + session_metrics->mutable_cdm_session_restore_offline_session()); + cdm_session_restore_usage_session_.ToProto( + session_metrics->mutable_cdm_session_restore_usage_session()); } -void SessionMetrics::SerializeSessionMetrics(MetricsGroup* metric_group) { - ProtoMetricSerializer serializer(metric_group); - // Add the session id as a single-valued metric. - serializer.SetString("/drm/widevine/cdm_session/session_id", session_id_); - cdm_session_life_span_.Serialize(&serializer); - cdm_session_renew_key_.Serialize(&serializer); - cdm_session_restore_offline_session_.Serialize(&serializer); - cdm_session_restore_usage_session_.Serialize(&serializer); -} - -OemCryptoDynamicAdapterMetrics::OemCryptoDynamicAdapterMetrics() : - oemcrypto_initialization_mode_( - "/drm/widevine/oemcrypto/initialization_mode"), - oemcrypto_l1_api_version_( - "/drm/widevine/oemcrypto/l1_api_version"), - oemcrypto_l1_min_api_version_( - "/drm/widevine/oemcrypto/l1_min_api_version") { -} +OemCryptoDynamicAdapterMetrics::OemCryptoDynamicAdapterMetrics() + : oemcrypto_initialization_mode_(), + oemcrypto_l1_api_version_(), + oemcrypto_l1_min_api_version_() {} void OemCryptoDynamicAdapterMetrics::SetInitializationMode( OEMCryptoInitializationMode mode) { @@ -352,13 +198,15 @@ void OemCryptoDynamicAdapterMetrics::SetL1MinApiVersion(uint32_t version) { } void OemCryptoDynamicAdapterMetrics::Serialize( - drm_metrics::MetricsGroup* metric_group) { + WvCdmMetrics::EngineMetrics *engine_metrics) { AutoLock lock(adapter_lock_); - ProtoMetricSerializer serializer(metric_group); - oemcrypto_initialization_mode_.Serialize(&serializer); - oemcrypto_l1_api_version_.Serialize(&serializer); - oemcrypto_l1_min_api_version_.Serialize(&serializer); + engine_metrics->set_allocated_oemcrypto_initialization_mode( + oemcrypto_initialization_mode_.ToProto()); + engine_metrics->set_allocated_oemcrypto_l1_api_version( + oemcrypto_l1_api_version_.ToProto()); + engine_metrics->set_allocated_oemcrypto_l1_min_api_version( + oemcrypto_l1_min_api_version_.ToProto()); } void OemCryptoDynamicAdapterMetrics::Clear() { @@ -371,83 +219,42 @@ void OemCryptoDynamicAdapterMetrics::Clear() { // This method returns a reference. This means that the destructor is never // executed for the returned object. -OemCryptoDynamicAdapterMetrics& GetDynamicAdapterMetricsInstance() { +OemCryptoDynamicAdapterMetrics &GetDynamicAdapterMetricsInstance() { // This is safe in C++ 11 since the initialization is guaranteed to run // only once regardless of multi-threaded access. - static OemCryptoDynamicAdapterMetrics* adapter_metrics = + static OemCryptoDynamicAdapterMetrics *adapter_metrics = new OemCryptoDynamicAdapterMetrics(); return *adapter_metrics; } -EngineMetrics::EngineMetrics() : - cdm_engine_add_key_( - "/drm/widevine/cdm_engine/add_key/time", - "error"), - cdm_engine_cdm_version_( - "/drm/widevine/cdm_engine/version"), - cdm_engine_close_session_( - "/drm/widevine/cdm_engine/close_session", - "error"), - cdm_engine_creation_time_millis_( - "/drm/widevine/cdm_engine/creation_time_millis"), - cdm_engine_decrypt_( - "/drm/widevine/cdm_engine/decrypt/time", - "error", - "length"), - cdm_engine_find_session_for_key_( - "/drm/widevine/cdm_engine/find_session_for_key", - "success"), - cdm_engine_generate_key_request_( - "/drm/widevine/cdm_engine/generate_key_request/time", - "error"), - cdm_engine_get_provisioning_request_( - "/drm/widevine/cdm_engine/get_provisioning_request/time", - "error"), - cdm_engine_get_usage_info_( - "/drm/widevine/cdm_engine/get_usage_info/time", - "error"), - cdm_engine_handle_provisioning_response_( - "/drm/widevine/cdm_engine/handle_provisioning_response/time", - "error"), - cdm_engine_life_span_( - "/drm/widevine/cdm_engine/life_span"), - cdm_engine_open_key_set_session_( - "/drm/widevine/cdm_engine/open_key_set_session", - "error"), - cdm_engine_open_session_( - "/drm/widevine/cdm_engine/open_session", - "error"), - cdm_engine_query_key_status_( - "/drm/widevine/cdm_engine/query_key_status/time", - "error"), - cdm_engine_remove_all_usage_info_( - "/drm/widevine/cdm_engine/remove_all_usage_info", - "error"), - cdm_engine_remove_usage_info_( - "/drm/widevine/cdm_engine/remove_usage_info", - "error"), - cdm_engine_release_usage_info_( - "/drm/widevine/cdm_engine/release_usage_info", - "error"), - cdm_engine_get_secure_stop_ids_( - "/drm/widevine/cdm_engine/get_secure_stop_ids", - "error"), - cdm_engine_remove_keys_( - "/drm/widevine/cdm_engine/remove_keys", - "error"), - cdm_engine_restore_key_( - "/drm/widevine/cdm_engine/restore_key/time", - "error"), - cdm_engine_unprovision_( - "/drm/widevine/cdm_engine/unprovision", - "error", - "security_level"), - app_package_name_("") { -} +EngineMetrics::EngineMetrics() + : cdm_engine_add_key_(), + cdm_engine_cdm_version_(), + cdm_engine_close_session_(), + cdm_engine_creation_time_millis_(), + cdm_engine_decrypt_(), + cdm_engine_find_session_for_key_(), + cdm_engine_generate_key_request_(), + cdm_engine_get_provisioning_request_(), + cdm_engine_get_secure_stop_ids_(), + cdm_engine_get_usage_info_(), + cdm_engine_handle_provisioning_response_(), + cdm_engine_life_span_(), + cdm_engine_open_key_set_session_(), + cdm_engine_open_session_(), + cdm_engine_query_key_status_(), + cdm_engine_release_all_usage_info_(), + cdm_engine_release_usage_info_(), + cdm_engine_remove_all_usage_info_(), + cdm_engine_remove_keys_(), + cdm_engine_remove_usage_info_(), + cdm_engine_restore_key_(), + cdm_engine_unprovision_(), + app_package_name_("") {} EngineMetrics::~EngineMetrics() { AutoLock lock(session_metrics_lock_); - std::vector::iterator i; + std::vector::iterator i; if (!session_metrics_list_.empty()) { LOGV("EngineMetrics::~EngineMetrics. Session count: %d", session_metrics_list_.size()); @@ -459,9 +266,9 @@ EngineMetrics::~EngineMetrics() { session_metrics_list_.clear(); } -SessionMetrics* EngineMetrics::AddSession() { +SessionMetrics *EngineMetrics::AddSession() { AutoLock lock(session_metrics_lock_); - SessionMetrics* metrics = new SessionMetrics(); + SessionMetrics *metrics = new SessionMetrics(); session_metrics_list_.push_back(metrics); return metrics; } @@ -469,77 +276,87 @@ SessionMetrics* EngineMetrics::AddSession() { void EngineMetrics::RemoveSession(wvcdm::CdmSessionId session_id) { AutoLock lock(session_metrics_lock_); session_metrics_list_.erase( - std::remove_if(session_metrics_list_.begin(), - session_metrics_list_.end(), + std::remove_if(session_metrics_list_.begin(), session_metrics_list_.end(), CompareSessionIds(session_id)), session_metrics_list_.end()); } -void EngineMetrics::Serialize(drm_metrics::MetricsGroup* metric_group, - bool completed_only, - bool clear_serialized_sessions) { +void EngineMetrics::Serialize(WvCdmMetrics *wv_metrics) { AutoLock lock(session_metrics_lock_); - + WvCdmMetrics::EngineMetrics *engine_metrics = + wv_metrics->mutable_engine_metrics(); // Serialize the most recent metrics from the OemCyrpto dynamic adapter. - OemCryptoDynamicAdapterMetrics& adapter_metrics = + OemCryptoDynamicAdapterMetrics &adapter_metrics = GetDynamicAdapterMetricsInstance(); - adapter_metrics.Serialize(metric_group); + adapter_metrics.Serialize(engine_metrics); if (!app_package_name_.empty()) { - metric_group->set_app_package_name(app_package_name_); + engine_metrics->mutable_app_package_name()->set_string_value( + app_package_name_); } - SerializeEngineMetrics(metric_group); - std::vector::iterator i; - for (i = session_metrics_list_.begin(); i != session_metrics_list_.end(); - /* no increment */) { - bool serialized = false; - if (!completed_only || (*i)->IsCompleted()) { - MetricsGroup* metric_sub_group = metric_group->add_metric_sub_group(); - if (!app_package_name_.empty()) { - metric_sub_group->set_app_package_name(app_package_name_); - } - (*i)->Serialize(metric_sub_group); - serialized = true; - } + SerializeEngineMetrics(engine_metrics); + LOGE("Serializing session metrics. Session Count: %d", + session_metrics_list_.size()); - // Clear the serialized session metrics if requested. - if (serialized && clear_serialized_sessions) { - session_metrics_list_.erase(i); - } else { - i++; - } + for (std::vector::const_iterator it = + session_metrics_list_.begin(); it != session_metrics_list_.end(); it++) { + (*it)->Serialize(wv_metrics->add_session_metrics()); } } -void EngineMetrics::SetAppPackageName(const std::string& app_package_name) { +void EngineMetrics::SetAppPackageName(const std::string &app_package_name) { app_package_name_ = app_package_name; } -void EngineMetrics::SerializeEngineMetrics(MetricsGroup* metric_group) { - ProtoMetricSerializer serializer(metric_group); - cdm_engine_add_key_.Serialize(&serializer); - cdm_engine_cdm_version_.Serialize(&serializer); - cdm_engine_close_session_.Serialize(&serializer); - cdm_engine_creation_time_millis_.Serialize(&serializer); - cdm_engine_decrypt_.Serialize(&serializer); - cdm_engine_find_session_for_key_.Serialize(&serializer); - cdm_engine_generate_key_request_.Serialize(&serializer); - cdm_engine_get_provisioning_request_.Serialize(&serializer); - cdm_engine_get_usage_info_.Serialize(&serializer); - cdm_engine_handle_provisioning_response_.Serialize(&serializer); - cdm_engine_life_span_.Serialize(&serializer); - cdm_engine_open_key_set_session_.Serialize(&serializer); - cdm_engine_open_session_.Serialize(&serializer); - cdm_engine_query_key_status_.Serialize(&serializer); - cdm_engine_remove_all_usage_info_.Serialize(&serializer); - cdm_engine_remove_usage_info_.Serialize(&serializer); - cdm_engine_release_usage_info_.Serialize(&serializer); - cdm_engine_get_secure_stop_ids_.Serialize(&serializer); - cdm_engine_remove_keys_.Serialize(&serializer); - cdm_engine_restore_key_.Serialize(&serializer); - cdm_engine_unprovision_.Serialize(&serializer); +void EngineMetrics::SerializeEngineMetrics( + WvCdmMetrics::EngineMetrics *engine_metrics) { + cdm_engine_add_key_.ToProto( + engine_metrics->mutable_cdm_engine_add_key_time_us()); + engine_metrics->set_allocated_cdm_engine_cdm_version( + cdm_engine_cdm_version_.ToProto()); + cdm_engine_close_session_.ToProto( + engine_metrics->mutable_cdm_engine_close_session()); + engine_metrics->set_allocated_cdm_engine_creation_time_millis( + cdm_engine_creation_time_millis_.ToProto()); + cdm_engine_decrypt_.ToProto( + engine_metrics->mutable_cdm_engine_decrypt_time_us()); + cdm_engine_find_session_for_key_.ToProto( + engine_metrics->mutable_cdm_engine_find_session_for_key()); + cdm_engine_generate_key_request_.ToProto( + engine_metrics->mutable_cdm_engine_generate_key_request_time_us()); + cdm_engine_get_provisioning_request_.ToProto( + engine_metrics->mutable_cdm_engine_get_provisioning_request_time_us()); + cdm_engine_get_secure_stop_ids_.ToProto( + engine_metrics->mutable_cdm_engine_get_secure_stop_ids()); + cdm_engine_get_usage_info_.ToProto( + engine_metrics->mutable_cdm_engine_get_usage_info_time_us()); + cdm_engine_handle_provisioning_response_.ToProto( + engine_metrics + ->mutable_cdm_engine_handle_provisioning_response_time_us()); + engine_metrics->set_allocated_cdm_engine_life_span( + cdm_engine_life_span_.ToProto()), + cdm_engine_open_key_set_session_.ToProto( + engine_metrics->mutable_cdm_engine_open_key_set_session()); + cdm_engine_open_session_.ToProto( + engine_metrics->mutable_cdm_engine_open_session()); + cdm_engine_remove_all_usage_info_.ToProto( + engine_metrics->mutable_cdm_engine_remove_all_usage_info()); + cdm_engine_remove_usage_info_.ToProto( + engine_metrics->mutable_cdm_engine_remove_usage_info()); + cdm_engine_query_key_status_.ToProto( + engine_metrics->mutable_cdm_engine_query_key_status_time_us()); + cdm_engine_release_all_usage_info_.ToProto( + engine_metrics->mutable_cdm_engine_release_all_usage_info()); + cdm_engine_release_usage_info_.ToProto( + engine_metrics->mutable_cdm_engine_release_usage_info()); + cdm_engine_remove_keys_.ToProto( + engine_metrics->mutable_cdm_engine_remove_keys()); + cdm_engine_restore_key_.ToProto( + engine_metrics->mutable_cdm_engine_restore_key_time_us()); + cdm_engine_unprovision_.ToProto( + engine_metrics->mutable_cdm_engine_unprovision()); - crypto_metrics_.Serialize(metric_group); + crypto_metrics_.Serialize(engine_metrics->mutable_crypto_metrics()); } -} // metrics -} // wvcdm +} // namespace metrics +} // namespace wvcdm diff --git a/libwvdrmengine/cdm/metrics/src/value_metric.cpp b/libwvdrmengine/cdm/metrics/src/value_metric.cpp index 9bad2231..fca1a052 100644 --- a/libwvdrmengine/cdm/metrics/src/value_metric.cpp +++ b/libwvdrmengine/cdm/metrics/src/value_metric.cpp @@ -8,114 +8,100 @@ #include "value_metric.h" -#include "metrics_collections.h" #include "OEMCryptoCENC.h" +#include "metrics_collections.h" #include "wv_cdm_types.h" namespace wvcdm { namespace metrics { -// Private namespace for some helper implementation functions. -namespace impl { +namespace impl{ -template<> -void Serialize(MetricSerializer* serializer, - const std::string& metric_name, - const int32_t& value) { - serializer->SetInt32(metric_name, value); +template <> +void SetValue(drm_metrics::ValueMetric *value_proto, + const int &value) { + value_proto->set_int_value(value); } -template<> -void Serialize(MetricSerializer* serializer, - const std::string& metric_name, - const int64_t& value) { - serializer->SetInt64(metric_name, value); +template <> +void SetValue(drm_metrics::ValueMetric *value_proto, + const long &value) { + value_proto->set_int_value(value); } -// This specialization forces the uint32_t to an int32_t. -template<> -void Serialize(MetricSerializer* serializer, - const std::string& metric_name, - const uint32_t& value) { - serializer->SetInt32(metric_name, value); +template <> +void SetValue(drm_metrics::ValueMetric *value_proto, + const long long &value) { + value_proto->set_int_value(value); } -// This specialization forces the uint32_t to an int64_t. -template<> -void Serialize(MetricSerializer* serializer, - const std::string& metric_name, - const uint64_t& value) { - serializer->SetInt64(metric_name, value); +template <> +void SetValue(drm_metrics::ValueMetric *value_proto, + const unsigned int &value) { + value_proto->set_int_value((int64_t)value); } -// This specialization forces a bool to an int32_t. -template<> -void Serialize(MetricSerializer* serializer, - const std::string& metric_name, - const bool& value) { - serializer->SetInt32(metric_name, value); +template <> +void SetValue(drm_metrics::ValueMetric *value_proto, + const unsigned short &value) { + value_proto->set_int_value((int64_t)value); } -// This specialization forces an unsigned short to an int32_t. -template<> -void Serialize(MetricSerializer* serializer, - const std::string& metric_name, - const unsigned short& value) { - serializer->SetInt32(metric_name, value); +template <> +void SetValue(drm_metrics::ValueMetric *value_proto, + const unsigned long &value) { + value_proto->set_int_value((int64_t)value); } -template<> -void Serialize(MetricSerializer* serializer, - const std::string& metric_name, - const std::string& value) { - serializer->SetString(metric_name, value); +template <> +void SetValue(drm_metrics::ValueMetric *value_proto, + const bool &value) { + value_proto->set_int_value(value); } -template<> -void Serialize(MetricSerializer* serializer, - const std::string& metric_name, - const double& value) { - serializer->SetDouble(metric_name, value); +template <> +void SetValue( + drm_metrics::ValueMetric *value_proto, + const OEMCrypto_HDCP_Capability &value) { + value_proto->set_int_value(value); } -// These specializations force CDM-specific types to int32_t -template<> -void Serialize(MetricSerializer* serializer, - const std::string& metric_name, - const CdmSecurityLevel& value) { - serializer->SetInt32(metric_name, value); +template <> +void SetValue( + drm_metrics::ValueMetric *value_proto, + const OEMCrypto_ProvisioningMethod &value) { + value_proto->set_int_value(value); } -template<> -void Serialize( - MetricSerializer* serializer, - const std::string& metric_name, - const OEMCrypto_HDCP_Capability& value) { - serializer->SetInt32(metric_name, value); +template <> +void SetValue( + drm_metrics::ValueMetric *value_proto, + const OEMCryptoInitializationMode &value) { + value_proto->set_int_value(value); } -template<> -void Serialize( - MetricSerializer* serializer, - const std::string& metric_name, - const OEMCrypto_ProvisioningMethod& value) { - serializer->SetInt32(metric_name, value); +template <> +void SetValue(drm_metrics::ValueMetric *value_proto, + const CdmSecurityLevel &value) { + value_proto->set_int_value(value); } -template<> -void Serialize( - MetricSerializer* serializer, - const std::string& metric_name, - const OEMCryptoInitializationMode& value) { - serializer->SetInt32(metric_name, value); +template <> +void SetValue(drm_metrics::ValueMetric *value_proto, + const CdmUsageSupportType &value) { + value_proto->set_int_value(value); } -template<> -void Serialize( - MetricSerializer* serializer, - const std::string& metric_name, - const CdmUsageSupportType& value) { - serializer->SetInt32(metric_name, value); +template <> +void SetValue(drm_metrics::ValueMetric *value_proto, + const double &value) { + value_proto->set_double_value(value); +} + +template <> +void SetValue(drm_metrics::ValueMetric *value_proto, + const std::string &value) { + value_proto->set_string_value(value); } } // namespace impl diff --git a/libwvdrmengine/cdm/metrics/test/counter_metric_unittest.cpp b/libwvdrmengine/cdm/metrics/test/counter_metric_unittest.cpp index c3e26036..b728391a 100644 --- a/libwvdrmengine/cdm/metrics/test/counter_metric_unittest.cpp +++ b/libwvdrmengine/cdm/metrics/test/counter_metric_unittest.cpp @@ -6,171 +6,123 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "metric_serialization.h" #include "scoped_ptr.h" +#include "string_conversions.h" +using drm_metrics::TestMetrics; using testing::IsNull; using testing::NotNull; namespace wvcdm { namespace metrics { -class MockCounterMetricSerializer : public MetricSerializer { - public: - MOCK_METHOD2(SetString, void(const std::string& metric_id, - const std::string& value)); - MOCK_METHOD2(SetInt32, void(const std::string& metric_id, - int32_t value)); - MOCK_METHOD2(SetInt64, void(const std::string& metric_id, - int64_t value)); - MOCK_METHOD2(SetDouble, void(const std::string& metric_id, - double value)); -}; +TEST(CounterMetricTest, NoFieldsEmpty) { + wvcdm::metrics::CounterMetric<> metric; -class CounterMetricTest : public ::testing::Test { - public: - void SetUp() { - mock_serializer_.reset(new MockCounterMetricSerializer()); - } - protected: - template - const std::map - GetValueMap( - const wvcdm::metrics::CounterMetric& - metric) { - return metric.value_map_; - } + TestMetrics metric_proto; + metric.ToProto(metric_proto.mutable_test_counters()); + ASSERT_EQ(0, metric_proto.test_counters().size()); +} - scoped_ptr mock_serializer_; -}; - -TEST_F(CounterMetricTest, NoFieldsSuccessNullCallback) { - wvcdm::metrics::CounterMetric<> metric("no/fields/metric"); +TEST(CounterMetricTest, NoFieldsSuccess) { + wvcdm::metrics::CounterMetric<> metric; metric.Increment(); metric.Increment(10); - std::map value_map = GetValueMap(metric); - ASSERT_EQ(1u, GetValueMap(metric).size()); - EXPECT_EQ(11, value_map.begin()->second); - EXPECT_EQ("", value_map.begin()->first); + TestMetrics metric_proto; + std::string serialized_metrics; + metric.ToProto(metric_proto.mutable_test_counters()); + ASSERT_EQ(1, metric_proto.test_counters().size()); + + ASSERT_TRUE(metric_proto.SerializeToString(&serialized_metrics)); + + EXPECT_EQ(11, metric_proto.test_counters(0).count()); + EXPECT_FALSE(metric_proto.test_counters(0).has_attributes()) + << std::string("Unexpected attributes value. Serialized metrics: ") + << wvcdm::b2a_hex(serialized_metrics); } -TEST_F(CounterMetricTest, NoFieldsSuccessWithCallback) { - wvcdm::metrics::CounterMetric<> metric("no/fields/metric"); - EXPECT_CALL(*mock_serializer_, - SetInt64("no/fields/metric/count", 11)); - - metric.Increment(); - metric.Increment(10); - metric.Serialize(mock_serializer_.get()); - - std::map value_map = GetValueMap(metric); - ASSERT_EQ(1u, GetValueMap(metric).size()); - EXPECT_EQ(11, value_map.begin()->second); - EXPECT_EQ("", value_map.begin()->first); -} - -TEST_F(CounterMetricTest, NoFieldsSuccessSingleIncrementWithCallback) { - wvcdm::metrics::CounterMetric<> metric("no/fields/metric"); - EXPECT_CALL(*mock_serializer_, - SetInt64("no/fields/metric/count", 1)); - - metric.Increment(); - metric.Serialize(mock_serializer_.get()); - - std::map value_map = GetValueMap(metric); - ASSERT_EQ(1u, GetValueMap(metric).size()); - EXPECT_EQ(1, value_map.begin()->second); - EXPECT_EQ("", value_map.begin()->first); -} - -TEST_F(CounterMetricTest, OneFieldSuccessNoCallback) { - wvcdm::metrics::CounterMetric metric( - "single/fields/metric", - "error_code"); +TEST(CounterMetricTest, OneFieldSuccess) { + wvcdm::metrics::CounterMetric metric; metric.Increment(7); metric.Increment(10, 7); metric.Increment(13); metric.Increment(20, 13); - std::map value_map = GetValueMap(metric); - ASSERT_EQ(2u, GetValueMap(metric).size()); - // Verify both instances. - EXPECT_EQ(11, value_map["{error_code:7}"]); - EXPECT_EQ(21, value_map["{error_code:13}"]); + TestMetrics metric_proto; + metric.ToProto(metric_proto.mutable_test_counters()); + ASSERT_EQ(2, metric_proto.test_counters().size()); + + EXPECT_EQ(11u, metric_proto.test_counters(0).count()); + EXPECT_EQ(7, metric_proto.test_counters(0).attributes().error_code()); + EXPECT_EQ(21, metric_proto.test_counters(1).count()); + EXPECT_EQ(13, metric_proto.test_counters(1).attributes().error_code()); } -TEST_F(CounterMetricTest, TwoFieldsSuccess) { - wvcdm::metrics::CounterMetric metric( - "two/fields/metric", - "error_code", - "size"); - metric.Increment(7, 23); - metric.Increment(2, 7, 29); - metric.Increment(3, 11, 23); - metric.Increment(4, 11, 29); - metric.Increment(5, 7, 23); - metric.Increment(-5, 7, 29); +TEST(CounterMetricTest, TwoFieldsSuccess) { + CounterMetric metric; - std::map value_map = GetValueMap(metric); - ASSERT_EQ(4u, GetValueMap(metric).size()); + metric.Increment(7, Pow2Bucket(23)); // Increment by one. + metric.Increment(2, 7, Pow2Bucket(33)); + metric.Increment(3, 11, Pow2Bucket(23)); + metric.Increment(4, 11, Pow2Bucket(33)); + metric.Increment(5, 7, Pow2Bucket(23)); + metric.Increment(-5, 7, Pow2Bucket(33)); // Verify all instances. - EXPECT_EQ(6, value_map["{error_code:7&size:23}"]); - EXPECT_EQ(-3, value_map["{error_code:7&size:29}"]); - EXPECT_EQ(3, value_map["{error_code:11&size:23}"]); - EXPECT_EQ(4, value_map["{error_code:11&size:29}"]); + TestMetrics metric_proto; + metric.ToProto(metric_proto.mutable_test_counters()); + ASSERT_EQ(4, metric_proto.test_counters().size()); - // Verify that a non-existent distribution returns default 0 - EXPECT_EQ(0, value_map["error_code:1,size:1"]); + EXPECT_EQ(6, metric_proto.test_counters(0).count()); + EXPECT_EQ(7, metric_proto.test_counters(0).attributes().error_code()); + EXPECT_EQ(16u, metric_proto.test_counters(0).attributes().length()); + EXPECT_EQ(-3, metric_proto.test_counters(1).count()); + EXPECT_EQ(7, metric_proto.test_counters(1).attributes().error_code()); + EXPECT_EQ(32u, metric_proto.test_counters(1).attributes().length()); + EXPECT_EQ(3, metric_proto.test_counters(2).count()); + EXPECT_EQ(11, metric_proto.test_counters(2).attributes().error_code()); + EXPECT_EQ(16u, metric_proto.test_counters(2).attributes().length()); + EXPECT_EQ(4, metric_proto.test_counters(3).count()); + EXPECT_EQ(11, metric_proto.test_counters(3).attributes().error_code()); + EXPECT_EQ(32u, metric_proto.test_counters(3).attributes().length()); } -TEST_F(CounterMetricTest, TwoFieldsSuccessWithCallback) { - wvcdm::metrics::CounterMetric metric("two/fields/metric", - "error_code", - "stringval"); +TEST(CounterMetricTest, ThreeFieldsSuccess) { + CounterMetric + metric; + metric.Increment(7, Pow2Bucket(13), true); - EXPECT_CALL( - *mock_serializer_, - SetInt64("two/fields/metric/count{error_code:11&stringval:foo}", 5)); - metric.Increment(11, "foo"); - metric.Increment(4, 11, "foo"); - metric.Serialize(mock_serializer_.get()); + TestMetrics metric_proto; + metric.ToProto(metric_proto.mutable_test_counters()); + ASSERT_EQ(1, metric_proto.test_counters().size()); + EXPECT_EQ(1, metric_proto.test_counters(0).count()); + EXPECT_EQ(7, metric_proto.test_counters(0).attributes().error_code()); + EXPECT_EQ(8u, metric_proto.test_counters(0).attributes().length()); + EXPECT_TRUE(metric_proto.test_counters(0).attributes().error_code_bool()); } -TEST_F(CounterMetricTest, ThreeFieldsSuccess) { - wvcdm::metrics::CounterMetric metric( - "three/fields/metric", - "error_code", - "size", - "woke up happy"); - metric.Increment(7, 13, false); +TEST(CounterMetricTest, FourFieldsSuccess) { + CounterMetric metric; + metric.Increment(10LL, 7, Pow2Bucket(13), true, kLevel3); - std::map value_map = GetValueMap(metric); - ASSERT_EQ(1u, GetValueMap(metric).size()); - EXPECT_EQ("{error_code:7&size:13&woke up happy:0}", - value_map.begin()->first); - EXPECT_EQ(1, value_map.begin()->second); -} - -TEST_F(CounterMetricTest, FourFieldsSuccess) { - wvcdm::metrics::CounterMetric metric( - "Four/fields/metric", - "error_code", - "size", - "woke up happy", - "horoscope"); - metric.Increment(10LL, 7, 13, true, "find your true love"); - - std::map value_map = GetValueMap(metric); - ASSERT_EQ(1u, GetValueMap(metric).size()); - EXPECT_EQ( - "{error_code:7&size:13&woke up happy:1&horoscope:find your true love}", - value_map.begin()->first); - EXPECT_EQ(10, value_map.begin()->second); + TestMetrics metric_proto; + metric.ToProto(metric_proto.mutable_test_counters()); + ASSERT_EQ(1, metric_proto.test_counters().size()); + EXPECT_EQ(10, metric_proto.test_counters(0).count()); + EXPECT_EQ(7, metric_proto.test_counters(0).attributes().error_code()); + EXPECT_EQ(8u, metric_proto.test_counters(0).attributes().length()); + EXPECT_TRUE(metric_proto.test_counters(0).attributes().error_code_bool()); + EXPECT_EQ(kLevel3, + metric_proto.test_counters(0).attributes().security_level()); } } // namespace metrics diff --git a/libwvdrmengine/cdm/metrics/test/distribution_unittest.cpp b/libwvdrmengine/cdm/metrics/test/distribution_unittest.cpp index 787978c0..9a9ea92f 100644 --- a/libwvdrmengine/cdm/metrics/test/distribution_unittest.cpp +++ b/libwvdrmengine/cdm/metrics/test/distribution_unittest.cpp @@ -13,10 +13,10 @@ namespace metrics { TEST(DistributionTest, NoValuesRecorded) { Distribution distribution; - EXPECT_EQ(DBL_MAX, distribution.Min()); - EXPECT_EQ(-DBL_MAX, distribution.Max()); + EXPECT_EQ(FLT_MAX, distribution.Min()); + EXPECT_EQ(-FLT_MAX, distribution.Max()); EXPECT_EQ(0, distribution.Mean()); - EXPECT_EQ(0, distribution.Count()); + EXPECT_EQ(0u, distribution.Count()); EXPECT_EQ(0, distribution.Variance()); } @@ -26,7 +26,7 @@ TEST(DistributionTest, OneValueRecorded) { EXPECT_EQ(5, distribution.Min()); EXPECT_EQ(5, distribution.Max()); EXPECT_EQ(5, distribution.Mean()); - EXPECT_EQ(1, distribution.Count()); + EXPECT_EQ(1u, distribution.Count()); EXPECT_EQ(0, distribution.Variance()); } @@ -38,7 +38,7 @@ TEST(DistributionTest, MultipleValuesRecorded) { EXPECT_EQ(5, distribution.Min()); EXPECT_EQ(15, distribution.Max()); EXPECT_EQ(10, distribution.Mean()); - EXPECT_EQ(3, distribution.Count()); + EXPECT_EQ(3u, distribution.Count()); EXPECT_NEAR(16.6667, distribution.Variance(), 0.0001); } diff --git a/libwvdrmengine/cdm/metrics/test/event_metric_unittest.cpp b/libwvdrmengine/cdm/metrics/test/event_metric_unittest.cpp index ac376308..b0fedf83 100644 --- a/libwvdrmengine/cdm/metrics/test/event_metric_unittest.cpp +++ b/libwvdrmengine/cdm/metrics/test/event_metric_unittest.cpp @@ -3,213 +3,165 @@ // Unit tests for EventMetric #include "event_metric.h" -#include "metric_serialization.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "scoped_ptr.h" +#include "string_conversions.h" +using drm_metrics::TestMetrics; using testing::IsNull; using testing::NotNull; namespace wvcdm { namespace metrics { -class MockEventMetricSerializer : public MetricSerializer { - public: - MOCK_METHOD2(SetString, void(const std::string& metric_id, - const std::string& value)); - MOCK_METHOD2(SetInt32, void(const std::string& metric_id, - int32_t value)); - MOCK_METHOD2(SetInt64, void(const std::string& metric_id, - int64_t value)); - MOCK_METHOD2(SetDouble, void(const std::string& metric_id, - double value)); -}; - class EventMetricTest : public ::testing::Test { public: - void SetUp() { - mock_serializer_.reset(new MockEventMetricSerializer()); - } - protected: - template - const std::map - GetValueMap( - const wvcdm::metrics::EventMetric& - metric) { - return metric.value_map_; - } + void SetUp() {} - scoped_ptr mock_serializer_; + protected: }; -TEST_F(EventMetricTest, NoFieldsSuccessNullCallback) { - wvcdm::metrics::EventMetric<> metric("no/fields/metric"); +TEST_F(EventMetricTest, NoFieldsEmpty) { + wvcdm::metrics::EventMetric<> metric; + + TestMetrics metric_proto; + metric.ToProto(metric_proto.mutable_test_distributions()); + + ASSERT_EQ(0, metric_proto.test_distributions().size()); +} + +TEST_F(EventMetricTest, NoFieldsSuccess) { + wvcdm::metrics::EventMetric<> metric; metric.Record(10LL); metric.Record(10LL); - std::map value_map = GetValueMap(metric); - ASSERT_EQ(1u, GetValueMap(metric).size()); - EXPECT_EQ(2, value_map.begin()->second->Count()); - EXPECT_EQ("", value_map.begin()->first); + TestMetrics metric_proto; + metric.ToProto(metric_proto.mutable_test_distributions()); + + std::string serialized_metrics; + ASSERT_TRUE(metric_proto.SerializeToString(&serialized_metrics)); + + ASSERT_EQ(1, metric_proto.test_distributions().size()); + EXPECT_EQ(2u, metric_proto.test_distributions(0).operation_count()); + EXPECT_FALSE(metric_proto.test_distributions(0).has_attributes()) + << std::string("Unexpected attributes value. Serialized metrics: ") + << wvcdm::b2a_hex(serialized_metrics); } -TEST_F(EventMetricTest, NoFieldsSuccessWithCallback) { - wvcdm::metrics::EventMetric<> metric("no/fields/metric"); - EXPECT_CALL(*mock_serializer_, - SetInt64("no/fields/metric/count", 2)); - EXPECT_CALL(*mock_serializer_, - SetDouble("no/fields/metric/mean", 10.0)); - EXPECT_CALL(*mock_serializer_, - SetDouble("no/fields/metric/variance", 0.0)); - EXPECT_CALL(*mock_serializer_, - SetDouble("no/fields/metric/min", 10.0)); - EXPECT_CALL(*mock_serializer_, - SetDouble("no/fields/metric/max", 10.0)); - - metric.Record(10); - metric.Record(10); - metric.Serialize(mock_serializer_.get()); - - std::map value_map = GetValueMap(metric); - ASSERT_EQ(1u, GetValueMap(metric).size()); - EXPECT_EQ(2, value_map.begin()->second->Count()); - EXPECT_EQ("", value_map.begin()->first); -} - -TEST_F(EventMetricTest, NoFieldsSuccessSingleRecordWithCallback) { - wvcdm::metrics::EventMetric<> metric("no/fields/metric"); - EXPECT_CALL(*mock_serializer_, - SetInt64("no/fields/metric/count", 1.0)); - EXPECT_CALL(*mock_serializer_, - SetDouble("no/fields/metric/mean", 10.0)); - - metric.Record(10); - metric.Serialize(mock_serializer_.get()); - - std::map value_map = GetValueMap(metric); - ASSERT_EQ(1u, GetValueMap(metric).size()); - EXPECT_EQ(1, value_map.begin()->second->Count()); - EXPECT_EQ("", value_map.begin()->first); -} - -TEST_F(EventMetricTest, OneFieldSuccessNoCallback) { - wvcdm::metrics::EventMetric metric( - "single/fields/metric", - "error_code"); +TEST_F(EventMetricTest, OneFieldSuccess) { + EventMetric metric; metric.Record(10LL, 7); metric.Record(11LL, 13); metric.Record(12LL, 13); - std::map value_map = GetValueMap(metric); - ASSERT_EQ(2u, GetValueMap(metric).size()); - // Verify both instances. - // TODO(blueeyes): Export MakeFieldNameString so it can be used here. - Distribution* distribution_error_7 = value_map["{error_code:7}"]; - Distribution* distribution_error_13 = value_map["{error_code:13}"]; - ASSERT_THAT(distribution_error_7, NotNull()); - ASSERT_THAT(distribution_error_13, NotNull()); + TestMetrics metric_proto; + metric.ToProto(metric_proto.mutable_test_distributions()); + ASSERT_EQ(2, metric_proto.test_distributions().size()); - EXPECT_EQ(1, distribution_error_7->Count()); - EXPECT_EQ(2, distribution_error_13->Count()); + EXPECT_EQ(1u, metric_proto.test_distributions(0).operation_count()); + EXPECT_EQ(10LL, metric_proto.test_distributions(0).mean()); + + EXPECT_EQ(2u, metric_proto.test_distributions(1).operation_count()); + EXPECT_NEAR(11.5, metric_proto.test_distributions(1).mean(), 1.0); + EXPECT_NEAR(0.5, metric_proto.test_distributions(1).variance(), 0.5); + EXPECT_EQ(11, metric_proto.test_distributions(1).min()); + EXPECT_EQ(12, metric_proto.test_distributions(1).max()); } TEST_F(EventMetricTest, TwoFieldsSuccess) { - wvcdm::metrics::EventMetric metric( - "two/fields/metric", - "error_code", - "size"); - metric.Record(1, 7, 23); - metric.Record(2, 7, 29); - metric.Record(3, 11, 23); - metric.Record(4, 11, 29); - metric.Record(5, 7, 23); + EventMetric metric; - std::map value_map = GetValueMap(metric); - ASSERT_EQ(4u, GetValueMap(metric).size()); + metric.Record(1, 7, Pow2Bucket(23)); + metric.Record(2, 7, Pow2Bucket(33)); + metric.Record(3, 11, Pow2Bucket(23)); + metric.Record(4, 11, Pow2Bucket(33)); + metric.Record(5, 7, Pow2Bucket(23)); - // Verify all instances. - Distribution* distribution_7_23 = value_map["{error_code:7&size:23}"]; - Distribution* distribution_7_29 = value_map["{error_code:7&size:29}"]; - Distribution* distribution_11_23 = value_map["{error_code:11&size:23}"]; - Distribution* distribution_11_29 = value_map["{error_code:11&size:29}"]; - ASSERT_THAT(distribution_7_23, NotNull()); - ASSERT_THAT(distribution_7_29, NotNull()); - ASSERT_THAT(distribution_11_23, NotNull()); - ASSERT_THAT(distribution_11_29, NotNull()); + TestMetrics metric_proto; + metric.ToProto(metric_proto.mutable_test_distributions()); + ASSERT_EQ(4, metric_proto.test_distributions().size()); - EXPECT_EQ(2, distribution_7_23->Count()); - EXPECT_EQ(1, distribution_7_29->Count()); - EXPECT_EQ(1, distribution_11_23->Count()); - EXPECT_EQ(1, distribution_11_29->Count()); + // error 7, bucket 16 + EXPECT_EQ(2u, metric_proto.test_distributions(0).operation_count()); + EXPECT_EQ(3LL, metric_proto.test_distributions(0).mean()); + EXPECT_NEAR(3.5, metric_proto.test_distributions(0).variance(), 0.5); + EXPECT_EQ(1, metric_proto.test_distributions(0).min()); + EXPECT_EQ(5, metric_proto.test_distributions(0).max()); + EXPECT_EQ(7, metric_proto.test_distributions(0).attributes().error_code()); + EXPECT_EQ(16U, metric_proto.test_distributions(0).attributes().length()); - // Verify that a non-existent distribution returns nullptr. - Distribution* null_distribution = value_map["error_code:1,size:1"]; - ASSERT_THAT(null_distribution, IsNull()); -} + // error 7, bucket 32 + EXPECT_EQ(1u, metric_proto.test_distributions(1).operation_count()); + EXPECT_EQ(2, metric_proto.test_distributions(1).mean()); + EXPECT_EQ(7, metric_proto.test_distributions(1).attributes().error_code()); + EXPECT_EQ(32U, metric_proto.test_distributions(1).attributes().length()); -TEST_F(EventMetricTest, TwoFieldsSuccessWithCallback) { - wvcdm::metrics::EventMetric metric("two/fields/metric", - "error_code", - "pow2_size"); + // error 11, bucket 16 + EXPECT_EQ(1u, metric_proto.test_distributions(2).operation_count()); + EXPECT_EQ(3, metric_proto.test_distributions(2).mean()); + EXPECT_EQ(11, metric_proto.test_distributions(2).attributes().error_code()); + EXPECT_EQ(16U, metric_proto.test_distributions(2).attributes().length()); - // Callbacks from second record operation. - EXPECT_CALL( - *mock_serializer_, - SetInt64("two/fields/metric/count{error_code:11&pow2_size:16}", 2.0)); - EXPECT_CALL( - *mock_serializer_, - SetDouble("two/fields/metric/mean{error_code:11&pow2_size:16}", 3.5)); - EXPECT_CALL( - *mock_serializer_, - SetDouble("two/fields/metric/variance{error_code:11&pow2_size:16}", - 0.25)); - EXPECT_CALL( - *mock_serializer_, - SetDouble("two/fields/metric/min{error_code:11&pow2_size:16}", 3.0)); - EXPECT_CALL( - *mock_serializer_, - SetDouble("two/fields/metric/max{error_code:11&pow2_size:16}", 4.0)); - metric.Record(3, 11, Pow2Bucket(29)); - metric.Record(4, 11, Pow2Bucket(29)); - metric.Serialize(mock_serializer_.get()); + // error 11, bucket 32 + EXPECT_EQ(1u, metric_proto.test_distributions(3).operation_count()); + EXPECT_EQ(4, metric_proto.test_distributions(3).mean()); + EXPECT_EQ(11, metric_proto.test_distributions(3).attributes().error_code()); + EXPECT_EQ(32U, metric_proto.test_distributions(3).attributes().length()); } TEST_F(EventMetricTest, ThreeFieldsSuccess) { - wvcdm::metrics::EventMetric metric( - "three/fields/metric", - "error_code", - "size", - "woke up happy"); - metric.Record(10LL, 7, 13, false); + EventMetric metric; + metric.Record(10LL, 7, Pow2Bucket(13), false); + metric.Record(11LL, 8, Pow2Bucket(17), true); + TestMetrics metric_proto; + metric.ToProto(metric_proto.mutable_test_distributions()); + ASSERT_EQ(2, metric_proto.test_distributions().size()); - std::map value_map = GetValueMap(metric); - ASSERT_EQ(1u, GetValueMap(metric).size()); - EXPECT_EQ("{error_code:7&size:13&woke up happy:0}", - value_map.begin()->first); - EXPECT_EQ(1, value_map.begin()->second->Count()); + EXPECT_EQ(1u, metric_proto.test_distributions(0).operation_count()); + EXPECT_EQ(10LL, metric_proto.test_distributions(0).mean()); + EXPECT_FALSE(metric_proto.test_distributions(0).has_variance()); + EXPECT_EQ(7, metric_proto.test_distributions(0).attributes().error_code()); + EXPECT_EQ(8u, metric_proto.test_distributions(0).attributes().length()); + EXPECT_EQ(false, + metric_proto.test_distributions(0).attributes().error_code_bool()); + + EXPECT_EQ(1u, metric_proto.test_distributions(1).operation_count()); + EXPECT_EQ(11LL, metric_proto.test_distributions(1).mean()); + EXPECT_FALSE(metric_proto.test_distributions(1).has_variance()); + EXPECT_EQ(8, metric_proto.test_distributions(1).attributes().error_code()); + EXPECT_EQ(16u, metric_proto.test_distributions(1).attributes().length()); + EXPECT_EQ(true, + metric_proto.test_distributions(1).attributes().error_code_bool()); } TEST_F(EventMetricTest, FourFieldsSuccess) { - wvcdm::metrics::EventMetric metric( - "Four/fields/metric", - "error_code", - "size", - "woke up happy", - "horoscope"); - metric.Record(10LL, 7, 13, true, "find your true love"); + EventMetric metric; - std::map value_map = GetValueMap(metric); - ASSERT_EQ(1u, GetValueMap(metric).size()); + metric.Record(10LL, 7, Pow2Bucket(13), true, kSecurityLevelL3); + + TestMetrics metric_proto; + metric.ToProto(metric_proto.mutable_test_distributions()); + ASSERT_EQ(1, metric_proto.test_distributions().size()); + + EXPECT_EQ(1u, metric_proto.test_distributions(0).operation_count()); + EXPECT_EQ(10LL, metric_proto.test_distributions(0).mean()); + EXPECT_FALSE(metric_proto.test_distributions(0).has_variance()); + EXPECT_EQ(7, metric_proto.test_distributions(0).attributes().error_code()); + EXPECT_EQ(8u, metric_proto.test_distributions(0).attributes().length()); + EXPECT_EQ(true, + metric_proto.test_distributions(0).attributes().error_code_bool()); EXPECT_EQ( - "{error_code:7&size:13&woke up happy:1&horoscope:find your true love}", - value_map.begin()->first); - EXPECT_EQ(1, value_map.begin()->second->Count()); + 3u, metric_proto.test_distributions(0).attributes().cdm_security_level()); } TEST_F(EventMetricTest, Pow2BucketTest) { diff --git a/libwvdrmengine/cdm/metrics/test/value_metric_unittest.cpp b/libwvdrmengine/cdm/metrics/test/value_metric_unittest.cpp index 77f5570a..7c0e53a2 100644 --- a/libwvdrmengine/cdm/metrics/test/value_metric_unittest.cpp +++ b/libwvdrmengine/cdm/metrics/test/value_metric_unittest.cpp @@ -8,70 +8,57 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "metric_serialization.h" +#include "metrics.pb.h" #include "scoped_ptr.h" namespace wvcdm { namespace metrics { -class MockMetricSerializer : public MetricSerializer { - public: - MOCK_METHOD2(SetString, void(const std::string& metric_id, - const std::string& value)); - MOCK_METHOD2(SetInt32, void(const std::string& metric_id, - int32_t value)); - MOCK_METHOD2(SetInt64, void(const std::string& metric_id, - int64_t value)); - MOCK_METHOD2(SetDouble, void(const std::string& metric_id, - double value)); -}; +TEST(ValueMetricTest, StringValue) { + ValueMetric metric; + metric.Record("foo"); -class ValueMetricTest : public ::testing::Test { - public: - void SetUp() { - mock_serializer_.reset(new MockMetricSerializer()); - } - - protected: - scoped_ptr mock_serializer_; -}; - -TEST_F(ValueMetricTest, StringValue) { - ValueMetric value_metric("string/metric"); - value_metric.Record("foo"); - - EXPECT_CALL(*mock_serializer_, - SetString("string/metric", "foo")); - value_metric.Serialize(mock_serializer_.get()); + wvcdm::scoped_ptr metric_proto(metric.ToProto()); + ASSERT_EQ("foo", metric_proto->string_value()); + ASSERT_FALSE(metric_proto->has_error_code()); } -TEST_F(ValueMetricTest, DoubleValue) { - ValueMetric value_metric("double/metric"); - value_metric.Record(42.0); +TEST(ValueMetricTest, DoubleValue) { + ValueMetric metric; + metric.Record(42.0); - EXPECT_CALL(*mock_serializer_, - SetDouble("double/metric", 42.0)); - value_metric.Serialize(mock_serializer_.get()); + wvcdm::scoped_ptr metric_proto(metric.ToProto()); + ASSERT_EQ(42.0, metric_proto->double_value()); + ASSERT_FALSE(metric_proto->has_error_code()); } -TEST_F(ValueMetricTest, Int32Value) { - ValueMetric value_metric("int32/metric"); - value_metric.Record(42); +TEST(ValueMetricTest, Int32Value) { + ValueMetric metric; + metric.Record(42); - EXPECT_CALL(*mock_serializer_, - SetInt32("int32/metric", 42)); - value_metric.Serialize(mock_serializer_.get()); + wvcdm::scoped_ptr metric_proto(metric.ToProto()); + ASSERT_EQ(42, metric_proto->int_value()); + ASSERT_FALSE(metric_proto->has_error_code()); } -TEST_F(ValueMetricTest, Int64Value) { - ValueMetric value_metric("int64/metric"); - value_metric.Record(42); +TEST(ValueMetricTest, Int64Value) { + ValueMetric metric; + metric.Record(42); - EXPECT_CALL(*mock_serializer_, - SetInt64("int64/metric", 42)); - value_metric.Serialize(mock_serializer_.get()); + wvcdm::scoped_ptr metric_proto(metric.ToProto()); + ASSERT_EQ(42, metric_proto->int_value()); + ASSERT_FALSE(metric_proto->has_error_code()); +} + +TEST(ValueMetricTest, SetError) { + ValueMetric metric; + metric.Record(42); + metric.SetError(7); + + wvcdm::scoped_ptr metric_proto(metric.ToProto()); + ASSERT_EQ(7, metric_proto->error_code()); + ASSERT_FALSE(metric_proto->has_int_value()); } } // namespace metrics } // namespace wvcdm - diff --git a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp index 666fe7f2..8d50d172 100644 --- a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp +++ b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp @@ -100,18 +100,11 @@ CdmResponseType WvContentDecryptionModule::GenerateKeyRequest( cdm_by_session_id_[key_set_id] = cdm_engine; } InitializationData initialization_data(init_data_type, init_data); - M_TIME( - sts = cdm_engine->GenerateKeyRequest( - session_id, - key_set_id, - initialization_data, - license_type, - app_parameters, - key_request), - cdm_engine->GetMetrics(), - cdm_engine_generate_key_request_, - sts); - switch(license_type) { + M_TIME(sts = cdm_engine->GenerateKeyRequest(session_id, key_set_id, + initialization_data, license_type, + app_parameters, key_request), + cdm_engine->GetMetrics(), cdm_engine_generate_key_request_, sts); + switch (license_type) { case kLicenseTypeRelease: if (sts != KEY_MESSAGE) { cdm_engine->CloseKeySetSession(key_set_id); @@ -119,16 +112,14 @@ CdmResponseType WvContentDecryptionModule::GenerateKeyRequest( } break; default: - if (sts == KEY_MESSAGE) - EnablePolicyTimer(); + if (sts == KEY_MESSAGE) EnablePolicyTimer(); break; } return sts; } CdmResponseType WvContentDecryptionModule::AddKey( - const CdmSessionId& session_id, - const CdmKeyResponse& key_data, + const CdmSessionId& session_id, const CdmKeyResponse& key_data, CdmKeySetId* key_set_id) { CdmEngine* cdm_engine = session_id.empty() ? GetCdmForSessionId(*key_set_id) : GetCdmForSessionId(session_id); @@ -139,14 +130,8 @@ CdmResponseType WvContentDecryptionModule::AddKey( release_key_set_id = *key_set_id; } CdmResponseType sts; - M_TIME( - sts = cdm_engine->AddKey( - session_id, - key_data, - key_set_id), - cdm_engine->GetMetrics(), - cdm_engine_add_key_, - sts); + M_TIME(sts = cdm_engine->AddKey(session_id, key_data, key_set_id), + cdm_engine->GetMetrics(), cdm_engine_add_key_, sts); if (sts == KEY_ADDED && session_id.empty()) { // license type release cdm_engine->CloseKeySetSession(release_key_set_id); cdm_by_session_id_.erase(release_key_set_id); @@ -155,20 +140,13 @@ CdmResponseType WvContentDecryptionModule::AddKey( } CdmResponseType WvContentDecryptionModule::RestoreKey( - const CdmSessionId& session_id, - const CdmKeySetId& key_set_id) { + const CdmSessionId& session_id, const CdmKeySetId& key_set_id) { CdmEngine* cdm_engine = GetCdmForSessionId(session_id); if (!cdm_engine) return SESSION_NOT_FOUND_4; CdmResponseType sts; - M_TIME( - sts = cdm_engine->RestoreKey( - session_id, - key_set_id), - cdm_engine->GetMetrics(), - cdm_engine_restore_key_, - sts); - if (sts == KEY_ADDED) - EnablePolicyTimer(); + M_TIME(sts = cdm_engine->RestoreKey(session_id, key_set_id), + cdm_engine->GetMetrics(), cdm_engine_restore_key_, sts); + if (sts == KEY_ADDED) EnablePolicyTimer(); return sts; } @@ -182,9 +160,7 @@ CdmResponseType WvContentDecryptionModule::RemoveKeys( } CdmResponseType WvContentDecryptionModule::QueryStatus( - SecurityLevel security_level, - const std::string& key, - std::string* value) { + SecurityLevel security_level, const std::string& key, std::string* value) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier); return cdm_engine->QueryStatus(security_level, key, value); } @@ -201,13 +177,8 @@ CdmResponseType WvContentDecryptionModule::QueryKeyStatus( CdmEngine* cdm_engine = GetCdmForSessionId(session_id); if (!cdm_engine) return SESSION_NOT_FOUND_9; CdmResponseType sts; - M_TIME( - sts = cdm_engine->QueryKeyStatus( - session_id, - key_info), - cdm_engine->GetMetrics(), - cdm_engine_query_key_status_, - sts); + M_TIME(sts = cdm_engine->QueryKeyStatus(session_id, key_info), + cdm_engine->GetMetrics(), cdm_engine_query_key_status_, sts); return sts; } @@ -219,40 +190,25 @@ CdmResponseType WvContentDecryptionModule::QueryOemCryptoSessionId( } CdmResponseType WvContentDecryptionModule::GetProvisioningRequest( - CdmCertificateType cert_type, - const std::string& cert_authority, - const CdmIdentifier& identifier, - CdmProvisioningRequest* request, + CdmCertificateType cert_type, const std::string& cert_authority, + const CdmIdentifier& identifier, CdmProvisioningRequest* request, std::string* default_url) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier); CdmResponseType sts; - M_TIME( - sts = cdm_engine->GetProvisioningRequest( - cert_type, - cert_authority, - request, - default_url), - cdm_engine->GetMetrics(), - cdm_engine_get_provisioning_request_, - sts); + M_TIME(sts = cdm_engine->GetProvisioningRequest(cert_type, cert_authority, + request, default_url), + cdm_engine->GetMetrics(), cdm_engine_get_provisioning_request_, sts); return sts; } CdmResponseType WvContentDecryptionModule::HandleProvisioningResponse( - const CdmIdentifier& identifier, - CdmProvisioningResponse& response, - std::string* cert, - std::string* wrapped_key) { + const CdmIdentifier& identifier, CdmProvisioningResponse& response, + std::string* cert, std::string* wrapped_key) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier); CdmResponseType sts; M_TIME( - sts = cdm_engine->HandleProvisioningResponse( - response, - cert, - wrapped_key), - cdm_engine->GetMetrics(), - cdm_engine_handle_provisioning_response_, - sts); + sts = cdm_engine->HandleProvisioningResponse(response, cert, wrapped_key), + cdm_engine->GetMetrics(), cdm_engine_handle_provisioning_response_, sts); return sts; } @@ -269,31 +225,18 @@ CdmResponseType WvContentDecryptionModule::GetUsageInfo( CdmUsageInfo* usage_info) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier); CdmResponseType sts; - M_TIME( - sts = cdm_engine->GetUsageInfo( - app_id, - usage_info), - cdm_engine->GetMetrics(), - cdm_engine_get_usage_info_, - sts); + M_TIME(sts = cdm_engine->GetUsageInfo(app_id, usage_info), + cdm_engine->GetMetrics(), cdm_engine_get_usage_info_, sts); return sts; } CdmResponseType WvContentDecryptionModule::GetUsageInfo( - const std::string& app_id, - const CdmSecureStopId& ssid, - const CdmIdentifier& identifier, - CdmUsageInfo* usage_info) { + const std::string& app_id, const CdmSecureStopId& ssid, + const CdmIdentifier& identifier, CdmUsageInfo* usage_info) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier); CdmResponseType sts; - M_TIME( - sts = cdm_engine->GetUsageInfo( - app_id, - ssid, - usage_info), - cdm_engine->GetMetrics(), - cdm_engine_get_usage_info_, - sts); + M_TIME(sts = cdm_engine->GetUsageInfo(app_id, ssid, usage_info), + cdm_engine->GetMetrics(), cdm_engine_get_usage_info_, sts); return sts; } @@ -346,8 +289,7 @@ CdmResponseType WvContentDecryptionModule::GetSecureStopIds( } CdmResponseType WvContentDecryptionModule::Decrypt( - const CdmSessionId& session_id, - bool validate_key_id, + const CdmSessionId& session_id, bool validate_key_id, const CdmDecryptionParameters& parameters) { // First find the CdmEngine that has the given session_id. If we are using // key sharing, the shared session will still be in the same CdmEngine. @@ -355,26 +297,20 @@ CdmResponseType WvContentDecryptionModule::Decrypt( if (!cdm_engine) return SESSION_NOT_FOUND_FOR_DECRYPT; CdmSessionId local_session_id = session_id; - if (validate_key_id && - Properties::GetSessionSharingId(session_id) != 0) { - bool status = cdm_engine->FindSessionForKey( - *parameters.key_id, &local_session_id); - cdm_engine->GetMetrics()->cdm_engine_find_session_for_key_ - .Increment(status); + if (validate_key_id && Properties::GetSessionSharingId(session_id) != 0) { + bool status = + cdm_engine->FindSessionForKey(*parameters.key_id, &local_session_id); + cdm_engine->GetMetrics()->cdm_engine_find_session_for_key_.Increment( + status); if (!status && parameters.is_encrypted) { LOGE("WvContentDecryptionModule::Decrypt: unable to find session"); return KEY_NOT_FOUND_IN_SESSION; } } CdmResponseType sts; - M_TIME( - sts = cdm_engine->Decrypt( - local_session_id, - parameters), - cdm_engine->GetMetrics(), - cdm_engine_decrypt_, - sts, - metrics::Pow2Bucket(parameters.encrypt_length)); + M_TIME(sts = cdm_engine->Decrypt(local_session_id, parameters), + cdm_engine->GetMetrics(), cdm_engine_decrypt_, sts, + metrics::Pow2Bucket(parameters.encrypt_length)); return sts; } @@ -398,12 +334,12 @@ void WvContentDecryptionModule::GetSerializedMetrics( std::string* serialized_metrics) { AutoLock auto_lock(cdms_lock_); CloseCdmsWithoutSessions(); - metrics_.SerializeToString(serialized_metrics); - metrics_.Clear(); + metrics_group_.SerializeToString(serialized_metrics); + metrics_group_.Clear(); } WvContentDecryptionModule::CdmInfo::CdmInfo() - : cdm_engine(new CdmEngine(&file_system)) {} + : cdm_engine(new CdmEngine(&file_system)) {} CdmEngine* WvContentDecryptionModule::EnsureCdmForIdentifier( const CdmIdentifier& identifier) { @@ -415,12 +351,12 @@ CdmEngine* WvContentDecryptionModule::EnsureCdmForIdentifier( // this CDM. We concatenate all pieces of the CdmIdentifier in order to // create an ID that is unique to that identifier. cdms_[identifier].file_system.SetOrigin(identifier.origin); - cdms_[identifier].file_system.SetIdentifier( - identifier.spoid + identifier.origin); + cdms_[identifier].file_system.SetIdentifier(identifier.spoid + + identifier.origin); // Set the app package name for use by metrics. - cdms_[identifier].cdm_engine->GetMetrics() - ->SetAppPackageName(identifier.app_package_name); + cdms_[identifier].cdm_engine->GetMetrics()->SetAppPackageName( + identifier.app_package_name); } CdmEngine* cdm_engine = cdms_[identifier].cdm_engine.get(); @@ -447,14 +383,12 @@ void WvContentDecryptionModule::CloseCdmsWithoutSessions() { it->second.cdm_engine->GetMetrics(); // engine_metrics should never be null. if (engine_metrics != NULL) { - engine_metrics->Serialize( - metrics_.add_metric_sub_group(), - false, // Report complete AND incomplete sessions. - true); // Clear session metrics after reporting. + engine_metrics->Serialize(metrics_group_.add_metrics()); } else { // Engine metrics should never be null. - LOGI("WvContentDecryptionModule::CloseCdmsWithoutSessions." - "engine_metrics was unexpectedly NULL."); + LOGI( + "WvContentDecryptionModule::CloseCdmsWithoutSessions." + "engine_metrics was unexpectedly NULL."); } // The CDM is no longer used for this identifier, delete it. @@ -478,7 +412,7 @@ void WvContentDecryptionModule::DisablePolicyTimer() { } AutoLock auto_lock(policy_timer_lock_); - if(cdms_is_empty) { + if (cdms_is_empty) { if (policy_timer_.IsRunning()) { policy_timer_.Stop(); } diff --git a/libwvdrmengine/cdm/test/wv_cdm_metrics_test.cpp b/libwvdrmengine/cdm/test/wv_cdm_metrics_test.cpp index ab9bc760..e620a9cd 100644 --- a/libwvdrmengine/cdm/test/wv_cdm_metrics_test.cpp +++ b/libwvdrmengine/cdm/test/wv_cdm_metrics_test.cpp @@ -6,6 +6,7 @@ #include "gmock/gmock.h" #include "log.h" #include "metrics.pb.h" +#include "string_conversions.h" #include "test_base.h" #include "test_printers.h" #include "wv_cdm_types.h" @@ -14,6 +15,8 @@ using ::testing::Eq; using ::testing::StrEq; using ::testing::Ge; +using ::testing::Gt; +using ::testing::Lt; using ::testing::Test; using wvcdm::CdmResponseType; @@ -48,22 +51,27 @@ TEST_F(WvContentDecryptionModuleMetricsTest, EngineOnlyMetrics) { std::string serialized_metrics; decryptor_.GetSerializedMetrics(&serialized_metrics); - // Spot check some metric values. - drm_metrics::MetricsGroup metrics; - ASSERT_TRUE(metrics.ParseFromString(serialized_metrics)); - EXPECT_THAT(metrics.metric_size(), Eq(0)); - ASSERT_THAT(metrics.metric_sub_group_size(), Eq(1)); - ASSERT_THAT(metrics.metric_sub_group(0).metric_size(), Ge(6)); - EXPECT_THAT(metrics.metric_sub_group(0).metric_sub_group_size(), Eq(0)); - EXPECT_THAT(metrics.metric_sub_group(0).metric(0).name(), - StrEq("/drm/widevine/oemcrypto/initialization_mode")); - // Can't check the initialization mode value. Different devices will have - // different 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)); + + // 100 is an arbitrary high value that shouldn't ever occur. EXPECT_THAT( - metrics.metric_sub_group(0).metric(5).name(), - StrEq("/drm/widevine/cdm_engine/" - "get_provisioning_request/time/count{error:0}")); - EXPECT_THAT(metrics.metric_sub_group(0).metric(5).value().int_value(), Eq(1)); + metrics_group.metrics(0).engine_metrics() + .oemcrypto_initialization_mode().int_value(), + Lt(100)); + EXPECT_THAT( + metrics_group.metrics(0).engine_metrics() + .oemcrypto_initialization_mode().int_value(), + Ge(0)); + ASSERT_THAT(metrics_group.metrics(0).engine_metrics() + .cdm_engine_get_provisioning_request_time_us().size(), Eq(1)); + EXPECT_THAT(metrics_group.metrics(0).engine_metrics() + .cdm_engine_get_provisioning_request_time_us(0) + .operation_count(), + Eq(1u)); } @@ -82,25 +90,32 @@ TEST_F(WvContentDecryptionModuleMetricsTest, EngineAndSessionMetrics) { decryptor_.GetSerializedMetrics(&serialized_metrics); // Spot check some metric values. - drm_metrics::MetricsGroup metrics; - ASSERT_TRUE(metrics.ParseFromString(serialized_metrics)); - // The outer container will never have metrics. - EXPECT_THAT(metrics.metric_size(), Eq(0)); - ASSERT_THAT(metrics.metric_sub_group_size(), Eq(1)); - ASSERT_THAT(metrics.metric_sub_group(0).metric_size(), Ge(6)); + 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_THAT(metrics.metric_sub_group(0).metric(0).name(), - StrEq("/drm/widevine/oemcrypto/initialization_mode")); - EXPECT_THAT(metrics.metric_sub_group(0).metric(5).name(), - StrEq("/drm/widevine/cdm_engine/open_session/count{error:7}")); - EXPECT_THAT(metrics.metric_sub_group(0).metric(5).value().int_value(), Eq(1)); + 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() + .cdm_engine_open_session(0).attributes().error_code(), + Eq(CdmResponseType::NEED_PROVISIONING)); // Validate a session-level metric. - EXPECT_THAT(metrics.metric_sub_group(0).metric_sub_group_size(), Eq(1)); + ASSERT_THAT(metrics_group.metrics(0).session_metrics().size(), Eq(1)); EXPECT_THAT( - metrics.metric_sub_group(0).metric_sub_group(0).metric(0).name(), - StrEq("/drm/widevine/cdm_session/session_id")); + metrics_group.metrics(0).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) { @@ -123,33 +138,28 @@ TEST_F(WvContentDecryptionModuleMetricsTest, MultipleEngineMetric) { decryptor_.GetSerializedMetrics(&serialized_metrics); // Spot check some metric values. - drm_metrics::MetricsGroup metrics; - ASSERT_TRUE(metrics.ParseFromString(serialized_metrics)); - // The outer container will never have metrics. - EXPECT_THAT(metrics.metric_size(), Eq(0)); + drm_metrics::WvCdmMetricsGroup metrics_group; + ASSERT_TRUE(metrics_group.ParseFromString(serialized_metrics)); // Two engine-level metrics are expected. - ASSERT_THAT(metrics.metric_sub_group_size(), Eq(2)); + ASSERT_THAT(metrics_group.metrics().size(), Eq(2)); - for (int i = 0; i < metrics.metric_sub_group_size(); i++) { - // Validate the engine-level metric. - ASSERT_THAT(metrics.metric_sub_group(i).metric_size(), Ge(6)); - EXPECT_THAT(metrics.metric_sub_group(i).metric(0).name(), - StrEq("/drm/widevine/oemcrypto/initialization_mode")); - EXPECT_THAT(metrics.metric_sub_group(i).metric(5).name(), - StrEq("/drm/widevine/cdm_engine/open_session/count{error:7}")); - EXPECT_THAT(metrics.metric_sub_group(i).metric(5).value().int_value(), - Eq(1)); + 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( + engine_metrics.cdm_engine_open_session(0).attributes().error_code(), + Eq(CdmResponseType::NEED_PROVISIONING)); // Validate a session-level metric. - EXPECT_THAT(metrics.metric_sub_group(i).metric_sub_group_size(), Eq(1)); - EXPECT_THAT( - metrics.metric_sub_group(i).metric_sub_group(0).metric(0).name(), - StrEq("/drm/widevine/cdm_session/session_id")); + 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)); } - - // Verify that the second metrics app package name is set. - EXPECT_THAT(metrics.metric_sub_group(1).app_package_name(), StrEq("baz")); } }