diff --git a/libwvdrmengine/Android.mk b/libwvdrmengine/Android.mk index f689ec44..5c85356a 100644 --- a/libwvdrmengine/Android.mk +++ b/libwvdrmengine/Android.mk @@ -79,7 +79,9 @@ include $(CLEAR_VARS) LOCAL_MODULE := libcdm_protos LOCAL_MODULE_CLASS := STATIC_LIBRARIES -LOCAL_SRC_FILES := $(call all-proto-files-under, cdm/core/src) +CORE_PROTO_SRC_FILES := $(call all-proto-files-under, cdm/core/src) +METRICS_PROTO_SRC_FILES := $(call all-proto-files-under, cdm/metrics/src) +LOCAL_SRC_FILES := $(CORE_PROTO_SRC_FILES) $(METRICS_PROTO_SRC_FILES) generated_sources_dir := $(call local-generated-sources-dir) @@ -91,7 +93,8 @@ generated_sources_dir := $(call local-generated-sources-dir) # with this path. LOCAL_EXPORT_C_INCLUDE_DIRS := \ $(generated_sources_dir)/proto \ - $(generated_sources_dir)/proto/$(LOCAL_PATH)/cdm/core/src + $(generated_sources_dir)/proto/$(LOCAL_PATH)/cdm/core/src \ + $(generated_sources_dir)/proto/$(LOCAL_PATH)/cdm/metrics/src include $(BUILD_STATIC_LIBRARY) diff --git a/libwvdrmengine/cdm/Android.mk b/libwvdrmengine/cdm/Android.mk index bf02ae64..9c54844b 100644 --- a/libwvdrmengine/cdm/Android.mk +++ b/libwvdrmengine/cdm/Android.mk @@ -39,8 +39,7 @@ LOCAL_SRC_FILES := \ $(SRC_DIR)/wv_content_decryption_module.cpp \ $(METRICS_SRC_DIR)/distribution.cpp \ $(METRICS_SRC_DIR)/event_metric.cpp \ - $(METRICS_SRC_DIR)/metrics_front_end.cpp \ - $(METRICS_SRC_DIR)/metrics_group.cpp \ + $(METRICS_SRC_DIR)/metrics_collections.cpp \ $(METRICS_SRC_DIR)/timer_metric.cpp \ diff --git a/libwvdrmengine/cdm/core/include/cdm_engine.h b/libwvdrmengine/cdm/core/include/cdm_engine.h index 4e323e92..6adcda6e 100644 --- a/libwvdrmengine/cdm/core/include/cdm_engine.h +++ b/libwvdrmengine/cdm/core/include/cdm_engine.h @@ -12,6 +12,7 @@ #include "file_store.h" #include "initialization_data.h" #include "lock.h" +#include "metrics_collections.h" #include "oemcrypto_adapter.h" #include "scoped_ptr.h" #include "timer_metric.h" @@ -241,7 +242,7 @@ class CdmEngine { // dead lock. virtual void OnTimerEvent(); - virtual metrics::MetricsGroup* GetMetrics() { return &metrics_; } + virtual metrics::EngineMetrics* GetMetrics() { return &metrics_; } private: // private methods @@ -273,7 +274,7 @@ class CdmEngine { * ensure that all data has been properly recorded in the group before * it is published. */ - metrics::MetricsGroup metrics_; + metrics::EngineMetrics metrics_; metrics::TimerMetric life_span_; CdmSessionMap sessions_; diff --git a/libwvdrmengine/cdm/core/include/cdm_session.h b/libwvdrmengine/cdm/core/include/cdm_session.h index 4321ca76..0b3c97ee 100644 --- a/libwvdrmengine/cdm/core/include/cdm_session.h +++ b/libwvdrmengine/cdm/core/include/cdm_session.h @@ -12,7 +12,7 @@ #include "file_store.h" #include "initialization_data.h" #include "license.h" -#include "metrics_group.h" +#include "metrics_collections.h" #include "oemcrypto_adapter.h" #include "policy_engine.h" #include "scoped_ptr.h" @@ -27,10 +27,24 @@ class UsageTableHeader; class CdmSession { public: - CdmSession(FileSystem* file_system); + // Creates a new instance of the CdmSession with the given |file_system| + // and |metrics| parameters. Both parameters are owned by the caller and + // must remain in scope througout the scope of the new instance. + CdmSession(FileSystem* file_system, metrics::SessionMetrics* metrics); virtual ~CdmSession(); + // Initializes this instance of CdmSession with the given property set. + // |cdm_client_property_set| MAY be null, is owned by the caller, + // and must remain in scope throughout the scope of this session. virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set); + + // Initializes this instance of CdmSession with the given parmeters. + // All parameters are owned by the caller. + // |cdm_client_property_set| is caller owned, may be null, but must be + // in scope as long as the session is in scope. + // |forced_session_id| is caller owned and may be null. + // |event_listener| is caller owned, may be null, but must be in scope + // as long as the session is in scope. virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set, const CdmSessionId* forced_session_id, WvCdmEventListener* event_listener); @@ -166,7 +180,7 @@ class CdmSession { CdmSigningAlgorithm algorithm, const std::string& signature); - virtual metrics::MetricsGroup* GetMetrics() { return &metrics_; } + virtual metrics::SessionMetrics* GetMetrics() { return metrics_; } private: friend class CdmSessionTest; @@ -185,19 +199,13 @@ class CdmSession { void set_file_handle(DeviceFiles* file_handle); // instance variables - - /* - * The metrics group must be the first variable declared to ensure - * that it is the last member destroyed so that no child members - * try to use a reference to it after it is destroyed. This will - * ensure that all data has been properly recorded in the group before - * it is published. - */ - metrics::MetricsGroup metrics_; + metrics::SessionMetrics* metrics_; + metrics::CryptoMetrics* crypto_metrics_; metrics::TimerMetric life_span_; bool initialized_; CdmSessionId session_id_; + FileSystem* file_system_; scoped_ptr license_parser_; scoped_ptr crypto_session_; scoped_ptr policy_engine_; diff --git a/libwvdrmengine/cdm/core/include/certificate_provisioning.h b/libwvdrmengine/cdm/core/include/certificate_provisioning.h index b124fb70..d54d859c 100644 --- a/libwvdrmengine/cdm/core/include/certificate_provisioning.h +++ b/libwvdrmengine/cdm/core/include/certificate_provisioning.h @@ -6,7 +6,7 @@ #include #include "crypto_session.h" -#include "metrics_group.h" +#include "metrics_collections.h" #include "oemcrypto_adapter.h" #include "service_certificate.h" #include "wv_cdm_types.h" @@ -18,7 +18,7 @@ class FileSystem; class CertificateProvisioning { public: - CertificateProvisioning(metrics::MetricsGroup* metrics) : + CertificateProvisioning(metrics::CryptoMetrics* metrics) : crypto_session_(metrics), cert_type_(kCertificateWidevine), service_certificate_(NULL) {}; diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index b6214789..17029e55 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -9,7 +9,7 @@ #include "OEMCryptoCENC.h" #include "lock.h" -#include "metrics_group.h" +#include "metrics_collections.h" #include "oemcrypto_adapter.h" #include "timer_metric.h" #include "wv_cdm_types.h" @@ -36,7 +36,10 @@ class CryptoSession { bool rsa_cast; }; - CryptoSession(metrics::MetricsGroup* metrics); + // Creates an instance of CryptoSession with the given |crypto_metrics|. + // |crypto_metrics| is owned by the caller, must NOT be null, and must + // exist as long as the new CryptoSession exists. + CryptoSession(metrics::CryptoMetrics* crypto_metrics); virtual ~CryptoSession(); virtual bool GetClientToken(std::string* client_token); @@ -206,7 +209,7 @@ class CryptoSession { static bool initialized_; static int session_count_; - metrics::MetricsGroup* metrics_; + metrics::CryptoMetrics* metrics_; metrics::TimerMetric life_span_; bool open_; diff --git a/libwvdrmengine/cdm/core/include/usage_table_header.h b/libwvdrmengine/cdm/core/include/usage_table_header.h index 3357a3c8..0fb8f748 100644 --- a/libwvdrmengine/cdm/core/include/usage_table_header.h +++ b/libwvdrmengine/cdm/core/include/usage_table_header.h @@ -9,7 +9,7 @@ #include "device_files.h" #include "file_store.h" #include "lock.h" -#include "metrics_group.h" +#include "metrics_collections.h" #include "scoped_ptr.h" #include "wv_cdm_types.h" @@ -66,29 +66,29 @@ class UsageTableHeader { // should not be in use by any open CryptoSession objects when calls // to DeleteEntry and MoveEntry are made. CdmResponseType DeleteEntry(uint32_t usage_entry_number, DeviceFiles* handle, - metrics::MetricsGroup* metrics); + metrics::CryptoMetrics* metrics); private: CdmResponseType MoveEntry(uint32_t from /* usage entry number */, const CdmUsageEntry& from_usage_entry, uint32_t to /* usage entry number */, DeviceFiles* handle, - metrics::MetricsGroup* metrics); + metrics::CryptoMetrics* metrics); CdmResponseType GetEntry(uint32_t usage_entry_number, DeviceFiles* handle, CdmUsageEntry* usage_entry); CdmResponseType StoreEntry(uint32_t usage_entry_number, DeviceFiles* handle, const CdmUsageEntry& usage_entry); - CdmResponseType Shrink(metrics::MetricsGroup* metrics, + CdmResponseType Shrink(metrics::CryptoMetrics* metrics, uint32_t number_of_usage_entries_to_delete); CdmResponseType UpgradeFromUsageTable(DeviceFiles* handle, - metrics::MetricsGroup* metrics); + metrics::CryptoMetrics* metrics); bool UpgradeLicensesFromUsageTable(DeviceFiles* handle, - metrics::MetricsGroup* metrics); + metrics::CryptoMetrics* metrics); bool UpgradeUsageInfoFromUsageTable(DeviceFiles* handle, - metrics::MetricsGroup* metrics); + metrics::CryptoMetrics* metrics); virtual bool is_inited() { return is_inited_; } diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index 556b5f94..a25c5753 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -14,7 +14,6 @@ #include "file_store.h" #include "license_protocol.pb.h" #include "log.h" -#include "metrics_front_end.h" #include "properties.h" #include "string_conversions.h" #include "wv_cdm_constants.h" @@ -130,7 +129,8 @@ CdmResponseType CdmEngine::OpenSession(const CdmKeySystem& key_system, CloseExpiredReleaseSessions(); - scoped_ptr new_session(new CdmSession(file_system_)); + scoped_ptr new_session(new CdmSession(file_system_, + metrics_.AddSession())); CdmResponseType sts = new_session->Init(property_set, forced_session_id, event_listener); if (sts != NO_ERROR) { @@ -498,13 +498,13 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, const std::string& query_token, std::string* query_response) { LOGI("CdmEngine::QueryStatus"); - CryptoSession crypto_session(&metrics_); + CryptoSession crypto_session(metrics_.GetCryptoMetrics()); if (security_level == kLevel3) { CdmResponseType status; M_TIME( status = crypto_session.Open( kLevel3), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_open_, status, kLevel3); @@ -520,7 +520,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, CdmSecurityLevel security_level; M_TIME( security_level = crypto_session.GetSecurityLevel(), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_get_security_level_, security_level); switch (security_level) { @@ -548,7 +548,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, M_TIME( got_id = crypto_session.GetExternalDeviceUniqueId( &deviceId), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_get_device_unique_id_, got_id); if (!got_id) { @@ -563,7 +563,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, M_TIME( got_id = crypto_session.GetSystemId( &system_id), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_get_system_id_, got_id, system_id); @@ -600,7 +600,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, M_TIME( got_info = crypto_session.UsageInformationSupport( &supports_usage_reporting), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_usage_information_support_, got_info); if (!got_info) { @@ -782,7 +782,8 @@ CdmResponseType CdmEngine::GetProvisioningRequest( DeleteAllUsageReportsUponFactoryReset(); if (NULL == cert_provisioning_.get()) { - cert_provisioning_.reset(new CertificateProvisioning(&metrics_)); + cert_provisioning_.reset( + new CertificateProvisioning(metrics_.GetCryptoMetrics())); } CdmResponseType ret = cert_provisioning_->GetProvisioningRequest( cert_provisioning_requested_security_level_, cert_type, cert_authority, @@ -824,12 +825,12 @@ CdmResponseType CdmEngine::HandleProvisioningResponse( if (NULL == cert_provisioning_.get()) { // Certificate provisioning object has been released. Check if a concurrent // provisioning attempt has succeeded before declaring failure. - CryptoSession crypto_session(&metrics_); + CryptoSession crypto_session(metrics_.GetCryptoMetrics()); CdmResponseType status; M_TIME( status = crypto_session.Open( cert_provisioning_requested_security_level_), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_open_, status, cert_provisioning_requested_security_level_); @@ -842,7 +843,7 @@ CdmResponseType CdmEngine::HandleProvisioningResponse( CdmSecurityLevel security_level; M_TIME( security_level = crypto_session.GetSecurityLevel(), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_get_security_level_, security_level); if (!IsProvisioned(security_level)) { @@ -892,14 +893,14 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) { return UNPROVISION_ERROR_3; } - CryptoSession crypto_session(&metrics_); + CryptoSession crypto_session(metrics_.GetCryptoMetrics()); CdmResponseType status; M_TIME( status = crypto_session.Open( security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_open_, status, security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault); @@ -909,7 +910,7 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) { } M_TIME( status = crypto_session.DeleteAllUsageReports(), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_delete_all_usage_reports_, status); if (status != NO_ERROR) { @@ -948,7 +949,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, } usage_property_set_->set_security_level(kLevelDefault); usage_property_set_->set_app_id(app_id); - usage_session_.reset(new CdmSession(file_system_)); + usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession())); CdmResponseType status = usage_session_->Init(usage_property_set_.get()); if (NO_ERROR != status) { LOGE("CdmEngine::GetUsageInfo: session init error: %d", status); @@ -968,7 +969,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, ssid, &usage_data)) { usage_property_set_->set_security_level(kLevel3); usage_property_set_->set_app_id(app_id); - usage_session_.reset(new CdmSession(file_system_)); + usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession())); status = usage_session_->Init(usage_property_set_.get()); if (NO_ERROR != status) { LOGE("CdmEngine::GetUsageInfo: session init error"); @@ -1042,7 +1043,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, usage_property_set_->set_security_level(requested_security_level); usage_property_set_->set_app_id(app_id); - usage_session_.reset(new CdmSession(file_system_)); + usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession())); CdmResponseType status = usage_session_->Init(usage_property_set_.get()); if (NO_ERROR != status) { @@ -1120,7 +1121,8 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) { ? kLevel3 : kLevelDefault; usage_property_set_->set_security_level(security_level); - usage_session_.reset(new CdmSession(file_system_)); + usage_session_.reset( + new CdmSession(file_system_, metrics_.AddSession())); usage_session_->Init(usage_property_set_.get()); if (usage_session_->get_usage_support_type() == kUsageEntrySupport) { @@ -1544,19 +1546,20 @@ void CdmEngine::DeleteAllUsageReportsUponFactoryReset() { if (!file_system_->Exists(device_base_path_level1) && !file_system_->Exists(device_base_path_level3)) { - scoped_ptr crypto_session(new CryptoSession(&metrics_)); + scoped_ptr crypto_session( + new CryptoSession(metrics_.GetCryptoMetrics())); CdmResponseType status; M_TIME( status = crypto_session->Open( cert_provisioning_requested_security_level_), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_open_, status, cert_provisioning_requested_security_level_); if (NO_ERROR == status) { M_TIME( status = crypto_session->DeleteAllUsageReports(), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_delete_all_usage_reports_, status); if (NO_ERROR != status) { diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index 91fe43ac..073d01d6 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -12,7 +12,6 @@ #include "clock.h" #include "file_store.h" #include "log.h" -#include "metrics_front_end.h" #include "properties.h" #include "string_conversions.h" #include "wv_cdm_constants.h" @@ -25,9 +24,10 @@ const size_t kKeySetIdLength = 14; namespace wvcdm { -CdmSession::CdmSession(FileSystem* file_system) : +CdmSession::CdmSession(FileSystem* file_system, + metrics::SessionMetrics* metrics) : + metrics_(metrics), initialized_(false), - crypto_session_(new CryptoSession(&metrics_)), file_handle_(new DeviceFiles(file_system)), license_received_(false), is_offline_(false), @@ -44,6 +44,9 @@ CdmSession::CdmSession(FileSystem* file_system) : usage_entry_number_(0), mock_license_parser_in_use_(false), mock_policy_engine_in_use_(false) { + // If metrics was not provided, then use a NULL CryptoMetrics instance, too. + crypto_metrics_ = metrics_ == NULL ? NULL : metrics_->GetCryptoMetrics(); + crypto_session_.reset(new CryptoSession(crypto_metrics_)); life_span_.Start(); } @@ -54,7 +57,10 @@ CdmSession::~CdmSession() { } Properties::RemoveSessionPropertySet(session_id_); - M_RECORD(&metrics_, cdm_session_life_span_, life_span_.AsMs()); + if (metrics_) { + M_RECORD(metrics_, cdm_session_life_span_, life_span_.AsMs()); + metrics_->SetCompleted(); + } } CdmResponseType CdmSession::Init( @@ -78,16 +84,15 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set, } CdmResponseType sts; M_TIME( - sts = crypto_session_->Open( - requested_security_level_), - &metrics_, + sts = crypto_session_->Open(requested_security_level_), + crypto_metrics_, crypto_session_open_, sts, requested_security_level_); if (NO_ERROR != sts) return sts; M_TIME( security_level_ = crypto_session_->GetSecurityLevel(), - &metrics_, + crypto_metrics_, crypto_session_get_security_level_, security_level_); if (!file_handle_->Init(security_level_)) { @@ -121,7 +126,7 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set, M_TIME( get_client_token_sts = crypto_session_->GetClientToken( &client_token), - &metrics_, + crypto_metrics_, crypto_session_get_token_, get_client_token_sts); if (!get_client_token_sts) { @@ -138,7 +143,7 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set, M_TIME( load_cert_sts = crypto_session_->LoadCertificatePrivateKey( wrapped_key), - &metrics_, + crypto_metrics_, crypto_session_load_certificate_private_key_, load_cert_sts); if(!load_cert_sts) { @@ -157,6 +162,7 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set, session_id_ = Properties::AlwaysUseKeySetIds() ? key_set_id_ : GenerateSessionId(); + metrics_->SetSessionId(session_id_); if (session_id_.empty()) { LOGE("CdmSession::Init: empty session ID"); @@ -454,7 +460,8 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) { if (sts != KEY_ADDED) { CdmResponseType sts = usage_table_header_->DeleteEntry(usage_entry_number_, - file_handle_.get(), &metrics_); + file_handle_.get(), + crypto_metrics_); if (sts != NO_ERROR) { LOGW("CdmSession::AddKey: Delete usage entry failed = %d", sts); } @@ -687,10 +694,10 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) { // it, so close and reopen session. CdmResponseType sts; crypto_session_->Close(); - crypto_session_.reset(new CryptoSession(&metrics_)); + crypto_session_.reset(new CryptoSession(crypto_metrics_)); M_TIME( sts = crypto_session_->Open(requested_security_level_), - &metrics_, + crypto_metrics_, crypto_session_open_, sts, requested_security_level_); @@ -711,7 +718,7 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) { return usage_table_header_->DeleteEntry(usage_entry_number, file_handle_.get(), - &metrics_); + crypto_metrics_); } bool CdmSession::IsKeyLoaded(const KeyId& key_id) { @@ -861,7 +868,7 @@ CdmResponseType CdmSession::DeleteMultipleUsageInformation( M_TIME( sts = crypto_session_->DeleteMultipleUsageInformation( provider_session_tokens), - &metrics_, + crypto_metrics_, crypto_session_delete_multiple_usage_information_, sts); return sts; @@ -871,7 +878,7 @@ CdmResponseType CdmSession::UpdateUsageTableInformation() { CdmResponseType sts; M_TIME( sts = crypto_session_->UpdateUsageInformation(), - &metrics_, + crypto_metrics_, crypto_session_update_usage_information_, sts); return sts; @@ -917,7 +924,7 @@ CdmResponseType CdmSession::GenericEncrypt(const std::string& in_buffer, iv, algorithm, out_buffer), - &metrics_, + crypto_metrics_, crypto_session_generic_encrypt_, sts, metrics::Pow2Bucket(in_buffer.size()), @@ -942,7 +949,7 @@ CdmResponseType CdmSession::GenericDecrypt(const std::string& in_buffer, iv, algorithm, out_buffer), - &metrics_, + crypto_metrics_, crypto_session_generic_decrypt_, sts, metrics::Pow2Bucket(in_buffer.size()), @@ -965,7 +972,7 @@ CdmResponseType CdmSession::GenericSign(const std::string& message, key_id, algorithm, signature), - &metrics_, + crypto_metrics_, crypto_session_generic_sign_, sts, metrics::Pow2Bucket(message.size()), @@ -984,7 +991,7 @@ CdmResponseType CdmSession::GenericVerify(const std::string& message, key_id, algorithm, signature), - &metrics_, + crypto_metrics_, crypto_session_generic_verify_, sts, metrics::Pow2Bucket(message.size()), diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 8cd99493..cb2693ab 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -12,7 +12,6 @@ #include "crypto_key.h" #include "log.h" -#include "metrics_front_end.h" #include "openssl/sha.h" #include "properties.h" #include "pst_report.h" @@ -45,7 +44,7 @@ uint64_t CryptoSession::request_id_index_ = 0; UsageTableHeader* CryptoSession::usage_table_header_l1_ = NULL; UsageTableHeader* CryptoSession::usage_table_header_l3_ = NULL; -CryptoSession::CryptoSession(metrics::MetricsGroup* metrics) +CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics) : metrics_(metrics), open_(false), update_usage_table_after_close_session_(false), diff --git a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp index 5cc3027e..231ca0da 100644 --- a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp +++ b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp @@ -29,8 +29,7 @@ #include "level3.h" #include "lock.h" #include "log.h" -#include "metrics_front_end.h" -#include "metrics_group.h" +#include "metrics_collections.h" #include "properties.h" #include "wv_cdm_constants.h" @@ -425,8 +424,12 @@ class Adapter { * To avoid changing the function signature and function contract - declare * a one-off metrics group to collect detailed information about how * oemcrypto was intialized. + * + * TODO(blueeyes): Refactor this to allow Initialize to provide the + * details to the caller or to use the metrics instance provided by + * the caller. */ - wvcdm::metrics::MetricsGroup metrics; + wvcdm::metrics::CryptoMetrics metrics; level1_ = FunctionPointers(); // start with all null pointers. level3_ = FunctionPointers(); // start with all null pointers. @@ -474,7 +477,7 @@ class Adapter { wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_L1_OPEN_FAILED); return result; } - if (LoadLevel1(metrics)) { + if (LoadLevel1(&metrics)) { LOGD("OEMCrypto_Initialize Level 1 success. I will use level 1."); } else { level1_ = FunctionPointers(); // revert to all null pointers. @@ -485,7 +488,7 @@ class Adapter { return result; } - bool LoadLevel1(wvcdm::metrics::MetricsGroup& metrics) { + bool LoadLevel1(wvcdm::metrics::CryptoMetrics* metrics) { level1_valid_ = true; const uint32_t kMinimumVersion = 8; const uint32_t kMaximumVersion = 13; @@ -495,7 +498,7 @@ class Adapter { LOOKUP_ALL(8, Terminate, OEMCrypto_Terminate); if (!level1_valid_) { M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_INVALID_L1); @@ -505,7 +508,7 @@ class Adapter { if (st != OEMCrypto_SUCCESS) { LOGW("Could not initialize L1. Falling Back to L3."); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INITIALIZE_L1); @@ -513,7 +516,7 @@ class Adapter { } level1_.version = level1_.APIVersion(); M_RECORD( - &metrics, + metrics, oemcrypto_l1_api_version_, NO_TIME, level1_.version, @@ -522,7 +525,7 @@ class Adapter { LOGW("liboemcrypto.so is version %d, not %d. Falling Back to L3.", level1_.version, kMinimumVersion); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_WRONG_L1_VERSION); @@ -600,7 +603,7 @@ class Adapter { // If we have a valid keybox, initialization is done. We're good. if (OEMCrypto_SUCCESS == level1_.IsKeyboxValid()) { M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_KEYBOX); @@ -612,7 +615,7 @@ class Adapter { if (level1_.version > 11 && (level1_.GetProvisioningMethod() == OEMCrypto_OEMCertificate)) { M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0); @@ -632,13 +635,13 @@ class Adapter { LOGE("OEMCrypto uses cert as identification, but cdm does not!"); LOGE("This will not work on a production device."); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_CERTIFICATE_MIX); } else { M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_CERTIFICATE); @@ -651,7 +654,7 @@ class Adapter { LOGW("Bad Level 1 Keybox. Falling Back to L3."); level1_.Terminate(); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_BAD_KEYBOX); @@ -663,7 +666,7 @@ class Adapter { LOGW("Could not open %s. Falling Back to L3.", filename.c_str()); level1_.Terminate(); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX); @@ -677,7 +680,7 @@ class Adapter { filename.c_str()); level1_.Terminate(); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INSTALL_KEYBOX); @@ -685,7 +688,7 @@ class Adapter { } LOGI("Installed keybox from %s", filename.c_str()); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_INSTALLED_KEYBOX); diff --git a/libwvdrmengine/cdm/core/src/usage_table_header.cpp b/libwvdrmengine/cdm/core/src/usage_table_header.cpp index 790aeffb..dc547ace 100644 --- a/libwvdrmengine/cdm/core/src/usage_table_header.cpp +++ b/libwvdrmengine/cdm/core/src/usage_table_header.cpp @@ -5,7 +5,6 @@ #include "crypto_session.h" #include "license.h" #include "log.h" -#include "metrics_group.h" namespace { std::string kEmptyString; @@ -140,7 +139,7 @@ CdmResponseType UsageTableHeader::UpdateEntry(CryptoSession* crypto_session, CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number, DeviceFiles* handle, - metrics::MetricsGroup* metrics) { + metrics::CryptoMetrics* metrics) { LOGV("UsageTableHeader::DeleteEntry: Lock"); AutoLock auto_lock(usage_table_header_lock_); if (usage_entry_number >= usage_entry_info_.size()) @@ -189,14 +188,13 @@ CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number, number_of_entries_to_be_deleted = usage_entry_info_.size() - swap_entry_number; } - return Shrink(metrics, number_of_entries_to_be_deleted); } CdmResponseType UsageTableHeader::MoveEntry( uint32_t from_usage_entry_number, const CdmUsageEntry& from_usage_entry, uint32_t to_usage_entry_number, DeviceFiles* handle, - metrics::MetricsGroup* metrics) { + metrics::CryptoMetrics* metrics) { LOGV("UsageTableHeader::MoveEntry"); // crypto_session points to an object whose scope is this method or a test @@ -373,7 +371,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number, } CdmResponseType UsageTableHeader::Shrink( - metrics::MetricsGroup* metrics, + metrics::CryptoMetrics* metrics, uint32_t number_of_usage_entries_to_delete) { if (usage_entry_info_.empty()) { LOGE("UsageTableHeader::Shrink: usage entry info table unexpectedly empty"); @@ -414,14 +412,14 @@ CdmResponseType UsageTableHeader::Shrink( } CdmResponseType UsageTableHeader::UpgradeFromUsageTable( - DeviceFiles* handle, metrics::MetricsGroup* metrics) { + DeviceFiles* handle, metrics::CryptoMetrics* metrics) { UpgradeLicensesFromUsageTable(handle, metrics); UpgradeUsageInfoFromUsageTable(handle, metrics); return NO_ERROR; } bool UsageTableHeader::UpgradeLicensesFromUsageTable( - DeviceFiles* handle, metrics::MetricsGroup* metrics) { + DeviceFiles* handle, metrics::CryptoMetrics* metrics) { // Fetch the key set IDs for each offline license. For each license // * retrieve the provider session token, // * create a new usage entry @@ -510,7 +508,7 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable( } bool UsageTableHeader::UpgradeUsageInfoFromUsageTable( - DeviceFiles* handle, metrics::MetricsGroup* metrics) { + DeviceFiles* handle, metrics::CryptoMetrics* metrics) { // Fetch all usage files. For each file retrieve all the usage info records // within the file. For each piece of usage information // * create a new usage entry diff --git a/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp b/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp index b4083a14..34437826 100644 --- a/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp @@ -139,7 +139,7 @@ using ::testing::StrEq; class CdmSessionTest : public ::testing::Test { protected: virtual void SetUp() { - cdm_session_.reset(new CdmSession(NULL)); + cdm_session_.reset(new CdmSession(NULL, &metrics_)); // Inject testing mocks. license_parser_ = new MockCdmLicense(cdm_session_->session_id()); cdm_session_->set_license_parser(license_parser_); @@ -151,6 +151,13 @@ class CdmSessionTest : public ::testing::Test { cdm_session_->set_file_handle(file_handle_); } + virtual void TearDown() { + // Force the cdm_session_ to be deleted. This enforces a requirement that + // the CDM session metrics exist at least as long as the CDM session. + cdm_session_.reset(); + } + + metrics::SessionMetrics metrics_; scoped_ptr cdm_session_; MockCdmLicense* license_parser_; MockCryptoSession* crypto_session_; diff --git a/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp b/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp index 26bb500e..075a40ac 100644 --- a/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp @@ -395,7 +395,7 @@ TEST_F(UsageTableHeaderTest, UpdateEntry) { TEST_F(UsageTableHeaderTest, DeleteEntry_InvalidUsageEntryNumber) { Init(kSecurityLevelL1, kUsageTableHeader, kUsageEntryInfoVector); uint32_t usage_entry_number = kUsageEntryInfoVector.size(); - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_NE(NO_ERROR, usage_table_header_->DeleteEntry( usage_entry_number, device_files_, &metrics)); @@ -426,7 +426,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_CryptoSessionError) { Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -462,7 +462,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastOfflineEntry) { Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -507,7 +507,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntry) { Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop2 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -558,7 +558,7 @@ TEST_F(UsageTableHeaderTest, Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; device_files_->DeleteAllLicenses(); EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); @@ -608,7 +608,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntriesAreMissing) { Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -671,7 +671,7 @@ TEST_F(UsageTableHeaderTest, Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_TRUE(device_files_->StoreLicense( usage_entry_info_vector[usage_entry_info_vector.size() - 1].key_set_id, @@ -739,7 +739,7 @@ TEST_F(UsageTableHeaderTest, usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1 uint32_t usage_entry_number_after_deleted_entry = usage_entry_number_to_be_deleted + 1; - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -812,7 +812,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreStorageTypeUnknown) { Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -867,7 +867,7 @@ TEST_F(UsageTableHeaderTest, usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1 uint32_t last_usage_entry_number = usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_TRUE(device_files_->StoreLicense( usage_entry_info_vector[last_usage_entry_number].key_set_id, @@ -933,7 +933,7 @@ TEST_F(UsageTableHeaderTest, usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1 uint32_t last_usage_entry_number = usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL(*crypto_session_, @@ -1007,7 +1007,7 @@ TEST_F(UsageTableHeaderTest, usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1 uint32_t last_valid_usage_entry_number = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_TRUE(device_files_->StoreLicense( usage_entry_info_vector[last_valid_usage_entry_number].key_set_id, @@ -1085,7 +1085,7 @@ TEST_F(UsageTableHeaderTest, usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1 uint32_t last_valid_usage_entry_number = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)) .Times(2) @@ -1157,7 +1157,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsOffline) { usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1 uint32_t last_usage_entry_number = usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_TRUE(device_files_->StoreLicense( usage_entry_info_vector[last_usage_entry_number].key_set_id, @@ -1271,7 +1271,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsSecureStop) { usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1 uint32_t last_usage_entry_number = usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)) .Times(2) @@ -1371,7 +1371,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreOfflineAndUnknknown) { usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1 uint32_t last_valid_usage_entry_number = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_TRUE(device_files_->StoreLicense( usage_entry_info_vector[last_valid_usage_entry_number].key_set_id, @@ -1490,7 +1490,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreSecureStopAndUnknknown) { usage_entry_info_vector.size() - 5; // kUsageEntryInfoSecureStop1 uint32_t last_valid_usage_entry_number = usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)) .Times(2) diff --git a/libwvdrmengine/cdm/include/ami_adapter.h b/libwvdrmengine/cdm/include/ami_adapter.h index 75999233..42bc4b1f 100644 --- a/libwvdrmengine/cdm/include/ami_adapter.h +++ b/libwvdrmengine/cdm/include/ami_adapter.h @@ -4,22 +4,19 @@ #define CDM_AMI_ADAPTER_H_ #include +#include #include -#include "report.h" - namespace wvcdm { -class AmiAdapter : public metrics::Report { +class AmiAdapter { public: AmiAdapter(); AmiAdapter(int64_t parent); ~AmiAdapter(); - metrics::Report* NewReport() const; - void UpdateString(const std::string& metric_id, const std::string& value); void UpdateInt32(const std::string& metric_id, int32_t value); void UpdateInt64(const std::string& metric_id, int64_t value); diff --git a/libwvdrmengine/cdm/include/wv_content_decryption_module.h b/libwvdrmengine/cdm/include/wv_content_decryption_module.h index 35cb0042..dcf8797a 100644 --- a/libwvdrmengine/cdm/include/wv_content_decryption_module.h +++ b/libwvdrmengine/cdm/include/wv_content_decryption_module.h @@ -11,7 +11,6 @@ #include "cdm_identifier.h" #include "file_store.h" #include "lock.h" -#include "metrics_front_end.h" #include "timer.h" #include "wv_cdm_types.h" @@ -126,6 +125,9 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler { // Validate a passed-in service certificate virtual bool IsValidServiceCertificate(const std::string& certificate); + // Retrieve the serialized metrics from the CDM. + virtual void GetSerializedMetrics(std::string* serialized_metrics); + private: struct CdmInfo { CdmInfo(); @@ -160,9 +162,6 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler { // This contains weak pointers to the CDM instances contained in |cdms_|. std::map cdm_by_session_id_; - metrics::Report* report_root_; - metrics::MetricsFrontEnd* front_end_; - CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule); }; diff --git a/libwvdrmengine/cdm/metrics/include/event_metric.h b/libwvdrmengine/cdm/metrics/include/event_metric.h index f9179b64..61012fa2 100644 --- a/libwvdrmengine/cdm/metrics/include/event_metric.h +++ b/libwvdrmengine/cdm/metrics/include/event_metric.h @@ -18,7 +18,7 @@ #include "lock.h" #include "distribution.h" -#include "metric_publisher.h" +#include "metric_serialization.h" namespace wvcdm { namespace metrics { @@ -27,11 +27,11 @@ class EventMetricTest; // This base class provides the common defintion used by all templated // instances of EventMetric. -class BaseEventMetric : public MetricPublisher { +class BaseEventMetric : public MetricSerializable { public: - // Publish metric values to the MetricNotification. |subscriber| must + // Send metric values to the MetricSerializer. |serializer| must // not be null and is owned by the caller. - virtual void Publish(MetricNotification* subscriber); + virtual void Serialize(MetricSerializer* serializer); protected: // Instantiates a BaseEventMetric. diff --git a/libwvdrmengine/cdm/metrics/include/metric_publisher.h b/libwvdrmengine/cdm/metrics/include/metric_publisher.h deleted file mode 100644 index 11a1a3ed..00000000 --- a/libwvdrmengine/cdm/metrics/include/metric_publisher.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_PUBLISHER_H_ -#define WVCDM_METRICS_METRIC_PUBLISHER_H_ - -namespace wvcdm { -namespace metrics { - -// The MetricNotification is implemented by the code that instantiates -// MetricPublisher instances. The caller provides this MetricNotification -// instance to MetricPublisher::Publish. In turn, Publish will make a call to -// UpdateMetric for each value to be published. The Metric may contain zero or -// more values to be updated. -class MetricNotification { - public: - virtual ~MetricNotification() {}; - - // 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 UpdateString(const std::string& metric_id, - const std::string& value) = 0; - virtual void UpdateInt32(const std::string& metric_id, int32_t value) = 0; - virtual void UpdateInt64(const std::string& metric_id, int64_t value) = 0; - virtual void UpdateDouble(const std::string& metric_id, double value) = 0; -}; - -// This abstract class merely provides the definition for publishing the value -// of the metric. -class MetricPublisher { - public: - virtual ~MetricPublisher() { } - // Publish metric values to the MetricNotification. |subscriber| must - // not be null and is owned by the caller. - virtual void Publish(MetricNotification* subscriber) = 0; -}; - -} // namespace metrics -} // namespace wvcdm - -#endif // WVCDM_METRICS_METRIC_PUBLISHER_H_ diff --git a/libwvdrmengine/cdm/metrics/include/metric_serialization.h b/libwvdrmengine/cdm/metrics/include/metric_serialization.h new file mode 100644 index 00000000..b2aa3a2b --- /dev/null +++ b/libwvdrmengine/cdm/metrics/include/metric_serialization.h @@ -0,0 +1,46 @@ +// 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_group.h b/libwvdrmengine/cdm/metrics/include/metrics_collections.h similarity index 59% rename from libwvdrmengine/cdm/metrics/include/metrics_group.h rename to libwvdrmengine/cdm/metrics/include/metrics_collections.h index 495044b4..2b5e4fdd 100644 --- a/libwvdrmengine/cdm/metrics/include/metrics_group.h +++ b/libwvdrmengine/cdm/metrics/include/metrics_collections.h @@ -1,19 +1,62 @@ // Copyright 2016 Google Inc. All Rights Reserved. +// +// This file contains definitions for metrics being collected throughout the +// CDM. #ifndef WVCDM_METRICS_METRICS_GROUP_H_ #define WVCDM_METRICS_METRICS_GROUP_H_ +#include #include #include -#include "OEMCryptoCENC.h" #include "event_metric.h" -#include "metric_publisher.h" +#include "metrics.pb.h" +#include "OEMCryptoCENC.h" #include "wv_cdm_types.h" +// This definition indicates that a given metric does not need timing +// stats. Example: +// +// M_RECORD(my_metrics, my_metric_name, NO_TIME); +#define NO_TIME 0 + +// Used to record metric timing and additional information about a specific +// event. Assumes that a microsecond timing has been provided. Example: +// +// 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__ ); \ + } + +// This definition automatically times an operation and records the time and +// additional information such as error code to the provided metric. +// Example: +// +// OEMCryptoResult sts; +// M_TIME( +// sts = OEMCrypto_Initialize(), +// 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; \ + } + namespace wvcdm { namespace metrics { +// 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, @@ -33,35 +76,14 @@ typedef enum OEMCryptoInitializationMode { OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0 = 15 } OEMCryptoInitializationMode; -/* - * The metrics group is the group of all metrics that be be recorded. They - * are kept together to allow calls to be correlated to one another. - */ -class MetricsGroup { + +// This class contains metrics for Crypto Session and OEM Crypto. +class CryptoMetrics { public: - /* CDM ENGINE */ - EventMetric cdm_engine_add_key_; - EventMetric cdm_engine_close_session_; - EventMetric cdm_engine_decrypt_; - EventMetric 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_life_span_; - EventMetric cdm_engine_open_key_set_session_; - EventMetric cdm_engine_open_session_; - EventMetric cdm_engine_query_key_status_; - EventMetric cdm_engine_release_all_usage_info_; - EventMetric cdm_engine_release_usage_info_; - EventMetric cdm_engine_remove_keys_; - EventMetric cdm_engine_restore_key_; - EventMetric cdm_engine_unprovision_; - /* CDM SESSION */ - EventMetric<> cdm_session_life_span_; - EventMetric cdm_session_renew_key_; - EventMetric cdm_session_restore_offline_session_; - EventMetric cdm_session_restore_usage_session_; + CryptoMetrics(); + + void Serialize(drm_metrics::MetricsGroup* metrics); + /* CRYPTO SESSION */ EventMetric crypto_session_delete_all_usage_reports_; EventMetric crypto_session_delete_multiple_usage_information_; @@ -127,14 +149,111 @@ class MetricsGroup { /* Internal OEMCrypto Metrics */ EventMetric oemcrypto_initialization_mode_; EventMetric oemcrypto_l1_api_version_; +}; - MetricsGroup(); - ~MetricsGroup(); +// This class contains session-scoped metrics. All properties and +// statistics related to operations within a single session are +// recorded here. +class SessionMetrics { + public: + 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; } + + // Returns the session id or an empty session id if it has not been set. + const CdmSessionId& GetSessionId() const { return session_id_; } + + // Marks the metrics object as completed and ready for serialization. + void SetCompleted() { completed_ = true; } + + // Returns true if the object is completed. This is used to determine + // when the stats are ready to be published. + bool IsCompleted() const { return completed_; } + + // Returns a pointer to the crypto metrics belonging to the engine instance. + // This instance retains ownership of the object. + CryptoMetrics* GetCryptoMetrics() { return &crypto_metrics_; } + + // 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); + + // Metrics collected at the session level. + EventMetric<> cdm_session_life_span_; + EventMetric cdm_session_renew_key_; + EventMetric cdm_session_restore_offline_session_; + EventMetric cdm_session_restore_usage_session_; private: - void Publish(MetricNotification* subscriber); - + void SerializeSessionMetrics(drm_metrics::MetricsGroup* metric_group); + CdmSessionId session_id_; + bool completed_; + CryptoMetrics crypto_metrics_; }; + +// This class contains engine-scoped metrics. All properties and +// statistics related to operations within the engine, but outside +// the scope of a session are recorded here. +class EngineMetrics { + public: + EngineMetrics(); + ~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(); + + // Removes the metrics object for the given session id. This should only + // be called when the SessionMetrics instance is no longer in use. + void RemoveSession(CdmSessionId session_id); + + // 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_; } + + // Serialize engine and session metrics into a serialized MetricsGroup + // instance and output that instance to the provided |metric_group|. + // |metric_group| is owned by the caller and must NOT be null. + // |completed_only| indicates that this call should only publish + // SessionMetrics instances that are marked as completed. + // |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); + + // Metrics recorded at the engine level. + EventMetric cdm_engine_add_key_; + EventMetric cdm_engine_close_session_; + EventMetric cdm_engine_decrypt_; + EventMetric 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_life_span_; + EventMetric cdm_engine_open_key_set_session_; + EventMetric cdm_engine_open_session_; + EventMetric cdm_engine_query_key_status_; + EventMetric cdm_engine_release_all_usage_info_; + EventMetric cdm_engine_release_usage_info_; + EventMetric cdm_engine_remove_keys_; + EventMetric cdm_engine_restore_key_; + EventMetric cdm_engine_unprovision_; + + private: + Lock session_metrics_lock_; + std::vector session_metrics_list_; + CryptoMetrics crypto_metrics_; + + void SerializeEngineMetrics(drm_metrics::MetricsGroup* out); +}; + } // namespace metrics } // namespace wvcdm #endif diff --git a/libwvdrmengine/cdm/metrics/include/metrics_front_end.h b/libwvdrmengine/cdm/metrics/include/metrics_front_end.h deleted file mode 100644 index 12838a82..00000000 --- a/libwvdrmengine/cdm/metrics/include/metrics_front_end.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. - -#ifndef WVCDM_METRICS_METRICS_FRONT_END_H_ -#define WVCDM_METRICS_METRICS_FRONT_END_H_ - -#include - -#include "report.h" -#include "timer_metric.h" /* needed for the macro */ - -namespace wvcdm { -namespace metrics { - -class MetricsFrontEnd { - - public: - - MetricsFrontEnd(Report* root); - - MetricNotification* CreateSubscriber(); - - static MetricsFrontEnd& Instance(); - static void OverrideInstance(MetricsFrontEnd* instance); - - private: - - static MetricsFrontEnd* instance_; - - Report* root_; - - /* Disallow copy and assign. */ - MetricsFrontEnd(const MetricsFrontEnd&); - void operator=(const MetricsFrontEnd&); -}; - -} // namespace metrics -} // namespace wvcdm - -#define MFE wvcdm::metrics::MetricsFrontEnd::Instance() - -#define NO_TIME 0 - -#define M_RECORD(GROUP, METRIC, TIME, ...) \ - if ( GROUP ) { \ - ( GROUP ) -> METRIC . Record( TIME, ##__VA_ARGS__ ); \ - } - -#define M_TIME(CALL, GROUP, METRIC, ...) \ - if ( GROUP ) { \ - wvcdm::metrics::TimerMetric timer; \ - timer.Start(); \ - CALL; \ - ( GROUP ) -> METRIC . Record(timer.AsUs(), ##__VA_ARGS__ ); \ - } else { \ - CALL; \ - } - -#endif diff --git a/libwvdrmengine/cdm/metrics/include/report.h b/libwvdrmengine/cdm/metrics/include/report.h deleted file mode 100644 index 49216e69..00000000 --- a/libwvdrmengine/cdm/metrics/include/report.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. - -#ifndef WVCDM_METRICS_REPORT_H_ -#define WVCDM_METRICS_REPORT_H_ - -#include - -#include "event_metric.h" - -namespace wvcdm { -namespace metrics { - -class Report : public MetricNotification { - - public: - - virtual ~Report() { } - - /* Create a new report of the same type. The new report is not - * a copy of this report. The pointer is to be owned by whoever - * calls this function. */ - virtual Report* NewReport() const; - -}; - -} // metrics -} //wvcdm - -#endif diff --git a/libwvdrmengine/cdm/metrics/src/event_metric.cpp b/libwvdrmengine/cdm/metrics/src/event_metric.cpp index 1f9bba5d..06e2ac51 100644 --- a/libwvdrmengine/cdm/metrics/src/event_metric.cpp +++ b/libwvdrmengine/cdm/metrics/src/event_metric.cpp @@ -32,26 +32,29 @@ void BaseEventMetric::Record(const std::string& field_names_values, distribution->Record(value); } -void BaseEventMetric::Publish(MetricNotification* notification) { +void BaseEventMetric::Serialize(MetricSerializer* serializer) { AutoLock lock(internal_lock_); for (std::map::iterator it = value_map_.begin(); it != value_map_.end(); it++) { - notification->UpdateInt64( + serializer->SetInt64( metric_name_ + "/count" + it->first, it->second->Count()); - notification->UpdateDouble( + serializer->SetDouble( metric_name_ + "/mean" + it->first, it->second->Mean()); - notification->UpdateDouble( - metric_name_ + "/variance" + it->first, - it->second->Variance()); - notification->UpdateDouble( - metric_name_ + "/min" + it->first, - it->second->Min()); - notification->UpdateDouble( - metric_name_ + "/max" + it->first, - it->second->Max()); + // 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()); + } } } diff --git a/libwvdrmengine/cdm/metrics/src/metrics.proto b/libwvdrmengine/cdm/metrics/src/metrics.proto new file mode 100644 index 00000000..4df1fe53 --- /dev/null +++ b/libwvdrmengine/cdm/metrics/src/metrics.proto @@ -0,0 +1,36 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// This file contains a proto definition for serialization of metrics data. +// +syntax = "proto2"; + +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 name of the metric. Must be valid UTF-8. Required. + optional string name = 1; + + // The value of the metric. Required. + optional MetricValue value = 2; + } + + // The list of name/value pairs of metrics. + repeated Metric metric = 1; + + // Allow multiple sub groups of metrics. + repeated MetricsGroup metric_sub_group = 2; +} diff --git a/libwvdrmengine/cdm/metrics/src/metrics_group.cpp b/libwvdrmengine/cdm/metrics/src/metrics_collections.cpp similarity index 53% rename from libwvdrmengine/cdm/metrics/src/metrics_group.cpp rename to libwvdrmengine/cdm/metrics/src/metrics_collections.cpp index b9a8904a..936cae8b 100644 --- a/libwvdrmengine/cdm/metrics/src/metrics_group.cpp +++ b/libwvdrmengine/cdm/metrics/src/metrics_collections.cpp @@ -1,75 +1,67 @@ // Copyright 2016 Google Inc. All Rights Reserved. -#include "metrics_group.h" +#include "metrics_collections.h" -#include "metrics_front_end.h" +#include + +#include "metrics.pb.h" + +using drm_metrics::MetricsGroup; +using wvcdm::metrics::MetricSerializer; + +namespace { +// Helper struct for comparing session ids. +struct CompareSessionIds { + const std::string& target_; + + CompareSessionIds(const wvcdm::CdmSessionId& target) : target_(target) {}; + + 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 { -MetricsGroup::MetricsGroup() : - cdm_engine_add_key_( - "/drm/widevine/cdm_engine/add_key/time", - "error"), - cdm_engine_close_session_( - "/drm/widevine/cdm_engine/close_session/time", - "error"), - cdm_engine_decrypt_( - "/drm/widevine/cdm_engine/decrypt/time", - "error"), - cdm_engine_find_session_for_key_( - "/drm/widevine/cdm_engine/find_session_for_key/time", - "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/time"), - cdm_engine_open_key_set_session_( - "/drm/widevine/cdm_engine/open_key_set_session/time", - "error"), - cdm_engine_open_session_( - "/drm/widevine/cdm_engine/open_session/time", - "error"), - cdm_engine_query_key_status_( - "/drm/widevine/cdm_engine/query_key_status/time", - "error"), - cdm_engine_release_all_usage_info_( - "/drm/widevine/cdm_engine/release_all_usage_info/time", - "error"), - cdm_engine_release_usage_info_( - "/drm/widevine/cdm_engine/release_usage_info/time", - "error"), - cdm_engine_remove_keys_( - "/drm/widevine/cdm_engine/remove_keys/time", - "error"), - cdm_engine_restore_key_( - "/drm/widevine/cdm_engine/restore_key/time", - "error"), - cdm_engine_unprovision_( - "/drm/widevine/cdm_engine/unprovision/time", - "error", - "security_level"), - cdm_session_life_span_( - "/drm/widevine/cdm_session/life_span/time"), - cdm_session_renew_key_( - "/drm/widevine/cdm_session/renew_key/time", - "error"), - cdm_session_restore_offline_session_( - "/drm/widevine/cdm_session/restore_offline_session/time", - "error"), - cdm_session_restore_usage_session_( - "/drm/widevine/cdm_session/restore_usage_session/time", - "error"), +CryptoMetrics::CryptoMetrics() : crypto_session_delete_all_usage_reports_( "/drm/widevine/crypto_session/delete_all_usage_reports/time", "error"), @@ -287,99 +279,234 @@ MetricsGroup::MetricsGroup() : oemcrypto_l1_api_version_( "/drm/widevine/oemcrypto/l1_api_version", "version", - "min_version") { } + "min_version") {} -MetricsGroup::~MetricsGroup() { -#if 0 // Disable metrics for now to work around P0:b/35093325 - MetricNotification* subscriber = MFE.CreateSubscriber(); - if (subscriber) { - Publish(subscriber); +void CryptoMetrics::Serialize(MetricsGroup* metrics) { + ProtoMetricSerializer serializer(metrics); + /* CRYPTO SESSION */ + 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_security_level_.Serialize(&serializer); + crypto_session_get_system_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_update_usage_information_.Serialize(&serializer); + crypto_session_usage_information_support_.Serialize(&serializer); + + /* OEMCRYPTO */ + oemcrypto_api_version_.Serialize(&serializer); + oemcrypto_close_session_.Serialize(&serializer); + oemcrypto_copy_buffer_.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_hdcp_capability_.Serialize(&serializer); + oemcrypto_get_key_data_.Serialize(&serializer); + oemcrypto_get_max_number_of_sessions_.Serialize(&serializer); + oemcrypto_get_number_of_open_sessions_.Serialize(&serializer); + oemcrypto_get_oem_public_certificate_.Serialize(&serializer); + oemcrypto_get_provisioning_method_.Serialize(&serializer); + oemcrypto_get_random_.Serialize(&serializer); + oemcrypto_initialize_.Serialize(&serializer); + oemcrypto_install_keybox_.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_keys_.Serialize(&serializer); + oemcrypto_load_test_keybox_.Serialize(&serializer); + oemcrypto_load_test_rsa_key_.Serialize(&serializer); + oemcrypto_open_session_.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_level_.Serialize(&serializer); + oemcrypto_security_patch_level_.Serialize(&serializer); + oemcrypto_select_key_.Serialize(&serializer); + oemcrypto_supports_usage_table_.Serialize(&serializer); + oemcrypto_update_usage_table_.Serialize(&serializer); + oemcrypto_wrap_keybox_.Serialize(&serializer); + + /* Internal OEMCrypto Metrics */ + oemcrypto_initialization_mode_.Serialize(&serializer); + oemcrypto_l1_api_version_.Serialize(&serializer); +} + +SessionMetrics::SessionMetrics() : + cdm_session_life_span_( + "/drm/widevine/cdm_session/life_span/time"), + cdm_session_renew_key_( + "/drm/widevine/cdm_session/renew_key/time", + "error"), + cdm_session_restore_offline_session_( + "/drm/widevine/cdm_session/restore_offline_session/time", + "error"), + cdm_session_restore_usage_session_( + "/drm/widevine/cdm_session/restore_usage_session/time", + "error"), + completed_(false) { +} + +void SessionMetrics::Serialize(MetricsGroup* metric_group) { + SerializeSessionMetrics(metric_group); + crypto_metrics_.Serialize(metric_group); +} + +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); +} + +EngineMetrics::EngineMetrics() : + cdm_engine_add_key_( + "/drm/widevine/cdm_engine/add_key/time", + "error"), + cdm_engine_close_session_( + "/drm/widevine/cdm_engine/close_session/time", + "error"), + cdm_engine_decrypt_( + "/drm/widevine/cdm_engine/decrypt/time", + "error"), + cdm_engine_find_session_for_key_( + "/drm/widevine/cdm_engine/find_session_for_key/time", + "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/time"), + cdm_engine_open_key_set_session_( + "/drm/widevine/cdm_engine/open_key_set_session/time", + "error"), + cdm_engine_open_session_( + "/drm/widevine/cdm_engine/open_session/time", + "error"), + cdm_engine_query_key_status_( + "/drm/widevine/cdm_engine/query_key_status/time", + "error"), + cdm_engine_release_all_usage_info_( + "/drm/widevine/cdm_engine/release_all_usage_info/time", + "error"), + cdm_engine_release_usage_info_( + "/drm/widevine/cdm_engine/release_usage_info/time", + "error"), + cdm_engine_remove_keys_( + "/drm/widevine/cdm_engine/remove_keys/time", + "error"), + cdm_engine_restore_key_( + "/drm/widevine/cdm_engine/restore_key/time", + "error"), + cdm_engine_unprovision_( + "/drm/widevine/cdm_engine/unprovision/time", + "error", + "security_level") { +} + +EngineMetrics::~EngineMetrics() { + AutoLock kock(session_metrics_lock_); + std::vector::iterator i; + for (i = session_metrics_list_.begin(); i != session_metrics_list_.end(); + i++) { + delete *i; } - delete subscriber; -#endif + session_metrics_list_.clear(); } -void MetricsGroup::Publish(MetricNotification* subscriber) { - cdm_engine_add_key_.Publish(subscriber); - cdm_engine_close_session_.Publish(subscriber); - cdm_engine_decrypt_.Publish(subscriber); - cdm_engine_find_session_for_key_.Publish(subscriber); - cdm_engine_generate_key_request_.Publish(subscriber); - cdm_engine_get_provisioning_request_.Publish(subscriber); - cdm_engine_get_usage_info_.Publish(subscriber); - cdm_engine_handle_provisioning_response_.Publish(subscriber); - cdm_engine_life_span_.Publish(subscriber); - cdm_engine_open_key_set_session_.Publish(subscriber); - cdm_engine_open_session_.Publish(subscriber); - cdm_engine_query_key_status_.Publish(subscriber); - cdm_engine_release_all_usage_info_.Publish(subscriber); - cdm_engine_release_usage_info_.Publish(subscriber); - cdm_engine_remove_keys_.Publish(subscriber); - cdm_engine_restore_key_.Publish(subscriber); - cdm_engine_unprovision_.Publish(subscriber); - cdm_session_life_span_.Publish(subscriber); - cdm_session_renew_key_.Publish(subscriber); - cdm_session_restore_offline_session_.Publish(subscriber); - cdm_session_restore_usage_session_.Publish(subscriber); - crypto_session_delete_all_usage_reports_.Publish(subscriber); - crypto_session_delete_multiple_usage_information_.Publish(subscriber); - crypto_session_generic_decrypt_.Publish(subscriber); - crypto_session_generic_sign_.Publish(subscriber); - crypto_session_generic_verify_.Publish(subscriber); - crypto_session_get_device_unique_id_.Publish(subscriber); - crypto_session_get_security_level_.Publish(subscriber); - crypto_session_get_system_id_.Publish(subscriber); - crypto_session_get_token_.Publish(subscriber); - crypto_session_life_span_.Publish(subscriber); - crypto_session_load_certificate_private_key_.Publish(subscriber); - crypto_session_open_.Publish(subscriber); - crypto_session_update_usage_information_.Publish(subscriber); - crypto_session_usage_information_support_.Publish(subscriber); - oemcrypto_api_version_.Publish(subscriber); - oemcrypto_close_session_.Publish(subscriber); - oemcrypto_copy_buffer_.Publish(subscriber); - oemcrypto_deactivate_usage_entry_.Publish(subscriber); - oemcrypto_decrypt_cenc_.Publish(subscriber); - oemcrypto_delete_usage_entry_.Publish(subscriber); - oemcrypto_delete_usage_table_.Publish(subscriber); - oemcrypto_derive_keys_from_session_key_.Publish(subscriber); - oemcrypto_force_delete_usage_entry_.Publish(subscriber); - oemcrypto_generate_derived_keys_.Publish(subscriber); - oemcrypto_generate_nonce_.Publish(subscriber); - oemcrypto_generate_rsa_signature_.Publish(subscriber); - oemcrypto_generate_signature_.Publish(subscriber); - oemcrypto_generic_decrypt_.Publish(subscriber); - oemcrypto_generic_encrypt_.Publish(subscriber); - oemcrypto_generic_sign_.Publish(subscriber); - oemcrypto_generic_verify_.Publish(subscriber); - oemcrypto_get_device_id_.Publish(subscriber); - oemcrypto_get_hdcp_capability_.Publish(subscriber); - oemcrypto_get_key_data_.Publish(subscriber); - oemcrypto_get_max_number_of_sessions_.Publish(subscriber); - oemcrypto_get_number_of_open_sessions_.Publish(subscriber); - oemcrypto_get_oem_public_certificate_.Publish(subscriber); - oemcrypto_get_provisioning_method_.Publish(subscriber); - oemcrypto_get_random_.Publish(subscriber); - oemcrypto_install_keybox_.Publish(subscriber); - oemcrypto_is_anti_rollback_hw_present_.Publish(subscriber); - oemcrypto_is_keybox_valid_.Publish(subscriber); - oemcrypto_load_device_rsa_key_.Publish(subscriber); - oemcrypto_load_keys_.Publish(subscriber); - oemcrypto_load_test_keybox_.Publish(subscriber); - oemcrypto_load_test_rsa_key_.Publish(subscriber); - oemcrypto_open_session_.Publish(subscriber); - oemcrypto_refresh_keys_.Publish(subscriber); - oemcrypto_report_usage_.Publish(subscriber); - oemcrypto_rewrap_device_rsa_key_.Publish(subscriber); - oemcrypto_rewrap_device_rsa_key_30_.Publish(subscriber); - oemcrypto_security_level_.Publish(subscriber); - oemcrypto_security_patch_level_.Publish(subscriber); - oemcrypto_select_key_.Publish(subscriber); - oemcrypto_supports_usage_table_.Publish(subscriber); - oemcrypto_update_usage_table_.Publish(subscriber); - oemcrypto_wrap_keybox_.Publish(subscriber); - oemcrypto_initialization_mode_.Publish(subscriber); - oemcrypto_l1_api_version_.Publish(subscriber); +SessionMetrics* EngineMetrics::AddSession() { + AutoLock lock(session_metrics_lock_); + SessionMetrics* metrics = new SessionMetrics(); + session_metrics_list_.push_back(metrics); + return metrics; } + +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(), + CompareSessionIds(session_id)), + session_metrics_list_.end()); +} + +void EngineMetrics::Serialize(drm_metrics::MetricsGroup* metric_group, + bool completed_only, + bool clear_serialized_sessions) { + AutoLock lock(session_metrics_lock_); + + 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()) { + (*i)->Serialize(metric_group->add_metric_sub_group()); + serialized = true; + } + + // Clear the serialized session metrics if requested. + if (serialized && clear_serialized_sessions) { + session_metrics_list_.erase(i); + } else { + i++; + } + } +} + +void EngineMetrics::SerializeEngineMetrics(MetricsGroup* metric_group) { + ProtoMetricSerializer serializer(metric_group); + cdm_engine_add_key_.Serialize(&serializer); + cdm_engine_close_session_.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_release_all_usage_info_.Serialize(&serializer); + cdm_engine_release_usage_info_.Serialize(&serializer); + cdm_engine_remove_keys_.Serialize(&serializer); + cdm_engine_restore_key_.Serialize(&serializer); + cdm_engine_unprovision_.Serialize(&serializer); + + crypto_metrics_.Serialize(metric_group); +} + } // metrics } // wvcdm diff --git a/libwvdrmengine/cdm/metrics/src/metrics_front_end.cpp b/libwvdrmengine/cdm/metrics/src/metrics_front_end.cpp deleted file mode 100644 index 13658cc4..00000000 --- a/libwvdrmengine/cdm/metrics/src/metrics_front_end.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved - -#include "metrics_front_end.h" - -#include - -#include - -namespace wvcdm { -namespace metrics { - -MetricsFrontEnd* MetricsFrontEnd::instance_ = NULL; - -MetricsFrontEnd::MetricsFrontEnd(Report* root) : - root_(root) { } - -MetricNotification* MetricsFrontEnd::CreateSubscriber() { - return root_ == NULL ? NULL : root_->NewReport(); -} - -MetricsFrontEnd& MetricsFrontEnd::Instance() { - static MetricsFrontEnd kDummy(NULL); - return instance_ == NULL ? kDummy : *instance_; -} - -void MetricsFrontEnd::OverrideInstance(MetricsFrontEnd* instance) { - instance_ = instance; -} - -} // namespace metrics -} // namespace wvcdm diff --git a/libwvdrmengine/cdm/metrics/test/event_metric_test.cpp b/libwvdrmengine/cdm/metrics/test/event_metric_test.cpp index bbcb7dcf..ac376308 100644 --- a/libwvdrmengine/cdm/metrics/test/event_metric_test.cpp +++ b/libwvdrmengine/cdm/metrics/test/event_metric_test.cpp @@ -3,7 +3,7 @@ // Unit tests for EventMetric #include "event_metric.h" -#include "metric_publisher.h" +#include "metric_serialization.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -15,22 +15,22 @@ using testing::NotNull; namespace wvcdm { namespace metrics { -class MockEventMetricNotification : public MetricNotification { +class MockEventMetricSerializer : public MetricSerializer { public: - MOCK_METHOD2(UpdateString, void(const std::string& metric_id, + MOCK_METHOD2(SetString, void(const std::string& metric_id, const std::string& value)); - MOCK_METHOD2(UpdateInt32, void(const std::string& metric_id, + MOCK_METHOD2(SetInt32, void(const std::string& metric_id, int32_t value)); - MOCK_METHOD2(UpdateInt64, void(const std::string& metric_id, + MOCK_METHOD2(SetInt64, void(const std::string& metric_id, int64_t value)); - MOCK_METHOD2(UpdateDouble, void(const std::string& metric_id, + MOCK_METHOD2(SetDouble, void(const std::string& metric_id, double value)); }; class EventMetricTest : public ::testing::Test { public: void SetUp() { - mock_notification_.reset(new MockEventMetricNotification()); + mock_serializer_.reset(new MockEventMetricSerializer()); } protected: template mock_notification_; + scoped_ptr mock_serializer_; }; TEST_F(EventMetricTest, NoFieldsSuccessNullCallback) { @@ -60,19 +60,36 @@ TEST_F(EventMetricTest, NoFieldsSuccessNullCallback) { TEST_F(EventMetricTest, NoFieldsSuccessWithCallback) { wvcdm::metrics::EventMetric<> metric("no/fields/metric"); - EXPECT_CALL(*mock_notification_, - UpdateInt64("no/fields/metric/count", 1.0)); - EXPECT_CALL(*mock_notification_, - UpdateDouble("no/fields/metric/mean", 10.0)); - EXPECT_CALL(*mock_notification_, - UpdateDouble("no/fields/metric/variance", 0.0)); - EXPECT_CALL(*mock_notification_, - UpdateDouble("no/fields/metric/min", 10.0)); - EXPECT_CALL(*mock_notification_, - UpdateDouble("no/fields/metric/max", 10.0)); + 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.Publish(mock_notification_.get()); + 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()); @@ -142,24 +159,24 @@ TEST_F(EventMetricTest, TwoFieldsSuccessWithCallback) { // Callbacks from second record operation. EXPECT_CALL( - *mock_notification_, - UpdateInt64("two/fields/metric/count{error_code:11&pow2_size:16}", 2.0)); + *mock_serializer_, + SetInt64("two/fields/metric/count{error_code:11&pow2_size:16}", 2.0)); EXPECT_CALL( - *mock_notification_, - UpdateDouble("two/fields/metric/mean{error_code:11&pow2_size:16}", 3.5)); + *mock_serializer_, + SetDouble("two/fields/metric/mean{error_code:11&pow2_size:16}", 3.5)); EXPECT_CALL( - *mock_notification_, - UpdateDouble("two/fields/metric/variance{error_code:11&pow2_size:16}", + *mock_serializer_, + SetDouble("two/fields/metric/variance{error_code:11&pow2_size:16}", 0.25)); EXPECT_CALL( - *mock_notification_, - UpdateDouble("two/fields/metric/min{error_code:11&pow2_size:16}", 3.0)); + *mock_serializer_, + SetDouble("two/fields/metric/min{error_code:11&pow2_size:16}", 3.0)); EXPECT_CALL( - *mock_notification_, - UpdateDouble("two/fields/metric/max{error_code:11&pow2_size:16}", 4.0)); + *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.Publish(mock_notification_.get()); + metric.Serialize(mock_serializer_.get()); } TEST_F(EventMetricTest, ThreeFieldsSuccess) { diff --git a/libwvdrmengine/cdm/metrics/test/metrics_collections_test.cpp b/libwvdrmengine/cdm/metrics/test/metrics_collections_test.cpp new file mode 100644 index 00000000..7a724e19 --- /dev/null +++ b/libwvdrmengine/cdm/metrics/test/metrics_collections_test.cpp @@ -0,0 +1,444 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Unit tests for the metrics collections, +// EngineMetrics, SessionMetrics and CrytpoMetrics. + +#include "metrics_collections.h" + +#include + +#include "gmock/gmock.h" +#include "google/protobuf/text_format.h" +#include "gtest/gtest.h" +#include "log.h" +#include "metrics.pb.h" +#include "wv_cdm_types.h" + +using drm_metrics::MetricsGroup; +using google::protobuf::TextFormat; + +namespace wvcdm { +namespace metrics { + +// TODO(blueeyes): Improve this implementation by supporting full message +// API In CDM. That allows us to use MessageDifferencer. +class EngineMetricsTest : public ::testing::Test { +}; + +TEST_F(EngineMetricsTest, AllEngineMetrics) { + EngineMetrics engine_metrics; + + // Set some values in all of the engine metrics. + engine_metrics.cdm_engine_add_key_.Record(1.0, KEY_ADDED); + engine_metrics.cdm_engine_close_session_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_decrypt_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_find_session_for_key_.Record(1.0, false); + engine_metrics.cdm_engine_generate_key_request_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_get_provisioning_request_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_get_usage_info_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_handle_provisioning_response_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_life_span_.Record(1.0); + engine_metrics.cdm_engine_open_key_set_session_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_open_session_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_query_key_status_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_release_all_usage_info_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_release_usage_info_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_remove_keys_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_restore_key_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_unprovision_.Record(1.0, NO_ERROR, kSecurityLevelL1); + + drm_metrics::MetricsGroup actual_metrics; + engine_metrics.Serialize(&actual_metrics, true, false); + + // For each EventMetric, 2 metrics get serialized since only one sample was + // taken. So, the total number of serialized metrics are 2*17. + ASSERT_EQ(2 * 17, actual_metrics.metric_size()); + EXPECT_EQ(0, actual_metrics.metric_sub_group_size()); + + // Spot check some metrics. + EXPECT_EQ("/drm/widevine/cdm_engine/add_key/time/count{error:2}", + actual_metrics.metric(0).name()); + EXPECT_EQ("/drm/widevine/cdm_engine/close_session/time/mean{error:0}", + actual_metrics.metric(3).name()); + EXPECT_EQ("/drm/widevine/cdm_engine/decrypt/time/mean{error:0}", + actual_metrics.metric(5).name()); + EXPECT_EQ(1.0, actual_metrics.metric(5).value().double_value()); +} + +TEST_F(EngineMetricsTest, EngineAndCryptoMetrics) { + EngineMetrics engine_metrics; + + // Set some values in some of the engine metrics and some crypto metrics. + engine_metrics.cdm_engine_add_key_.Record(1.0, KEY_ADDED); + engine_metrics.cdm_engine_close_session_.Record(1.0, NO_ERROR); + CryptoMetrics* crypto_metrics = engine_metrics.GetCryptoMetrics(); + + crypto_metrics->crypto_session_generic_decrypt_ + .Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128); + crypto_metrics->crypto_session_get_device_unique_id_ + .Record(4.0, false); + + drm_metrics::MetricsGroup actual_metrics; + engine_metrics.Serialize(&actual_metrics, true, false); + + // For each EventMetric, 2 metrics get serialized since only one sample was + // taken. So, the total number of serialized metrics are 2*4 since we + // touched 4 metrics. + ASSERT_EQ(2 * 4, actual_metrics.metric_size()); + EXPECT_EQ(0, actual_metrics.metric_sub_group_size()); + + // Spot check some metrics. + EXPECT_EQ("/drm/widevine/cdm_engine/add_key/time/count{error:2}", + actual_metrics.metric(0).name()); + EXPECT_EQ( + "/drm/widevine/crypto_session/generic_decrypt/time/count" + "{error:0&length:1024&algorithm:1}", + actual_metrics.metric(4).name()); + EXPECT_EQ( + "/drm/widevine/crypto_session/get_device_unique_id/time/mean{success:0}", + actual_metrics.metric(7).name()); + EXPECT_EQ(4.0, actual_metrics.metric(7).value().double_value()); +} + +TEST_F(EngineMetricsTest, EmptyEngineMetrics) { + EngineMetrics engine_metrics; + + drm_metrics::MetricsGroup actual_metrics; + engine_metrics.Serialize(&actual_metrics, true, false); + + EXPECT_EQ(0, actual_metrics.metric_size()); + EXPECT_EQ(0, actual_metrics.metric_sub_group_size()); +} + +TEST_F(EngineMetricsTest, EngineMetricsWithCompletedSessions) { + EngineMetrics engine_metrics; + + // Set a values in an engine metric and in a crypto metric. + engine_metrics.cdm_engine_add_key_.Record(1.0, KEY_ADDED); + engine_metrics.GetCryptoMetrics() + ->crypto_session_load_certificate_private_key_.Record(2.0, true); + + // Create two sessions and record some metrics. + SessionMetrics* session_metrics_1 = engine_metrics.AddSession(); + session_metrics_1->SetSessionId("session_id_1"); + SessionMetrics* session_metrics_2 = engine_metrics.AddSession(); + session_metrics_2->SetSessionId("session_id_2"); + // Record a CryptoMetrics metric in the session. + session_metrics_2->GetCryptoMetrics()->crypto_session_generic_decrypt_ + .Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128); + session_metrics_2->SetSessionId("session_id_2"); + // Mark only session 2 as completed. + session_metrics_2->SetCompleted(); + + drm_metrics::MetricsGroup actual_metrics; + engine_metrics.Serialize(&actual_metrics, true, false); + + // Validate metric counts. + // For each EventMetric, 2 metrics get serialized since only one sample was + // taken. So, the total number of serialized metrics are 2*2 since we + // touched 2 metrics. + ASSERT_EQ(2 * 2, actual_metrics.metric_size()); + ASSERT_EQ(1, actual_metrics.metric_sub_group_size()); + ASSERT_EQ(3, actual_metrics.metric_sub_group(0).metric_size()); + + // Spot check some metrics. + EXPECT_EQ("/drm/widevine/cdm_engine/add_key/time/count{error:2}", + actual_metrics.metric(0).name()); + EXPECT_EQ("/drm/widevine/crypto_session/load_certificate_private_key" + "/time/count{success:1}", + actual_metrics.metric(2).name()); + EXPECT_EQ("/drm/widevine/cdm_session/session_id", + actual_metrics.metric_sub_group(0).metric(0).name()); + EXPECT_EQ( + "session_id_2", + actual_metrics.metric_sub_group(0).metric(0).value().string_value()); + EXPECT_EQ( + "/drm/widevine/crypto_session/generic_decrypt/time/count" + "{error:0&length:1024&algorithm:1}", + actual_metrics.metric_sub_group(0).metric(1).name()); +} + +TEST_F(EngineMetricsTest, EngineMetricsSerializeAllSessions) { + EngineMetrics engine_metrics; + + // Create two sessions and record some metrics. + SessionMetrics* session_metrics_1 = engine_metrics.AddSession(); + session_metrics_1->SetSessionId("session_id_1"); + SessionMetrics* session_metrics_2 = engine_metrics.AddSession(); + session_metrics_2->SetSessionId("session_id_2"); + // Mark only session 2 as completed. + session_metrics_2->SetCompleted(); + + drm_metrics::MetricsGroup actual_metrics; + engine_metrics.Serialize(&actual_metrics, false, false); + + // Validate metric counts. + // No Engine-level metrics were recorded. + ASSERT_EQ(0, actual_metrics.metric_size()); + // Two sub groups, 1 per session. + ASSERT_EQ(2, actual_metrics.metric_sub_group_size()); + ASSERT_EQ(1, actual_metrics.metric_sub_group(0).metric_size()); + + // Spot check some metrics. + EXPECT_EQ("/drm/widevine/cdm_session/session_id", + actual_metrics.metric_sub_group(0).metric(0).name()); + EXPECT_EQ( + "session_id_1", + actual_metrics.metric_sub_group(0).metric(0).value().string_value()); + EXPECT_EQ("/drm/widevine/cdm_session/session_id", + actual_metrics.metric_sub_group(1).metric(0).name()); + EXPECT_EQ( + "session_id_2", + actual_metrics.metric_sub_group(1).metric(0).value().string_value()); +} + +TEST_F(EngineMetricsTest, EngineMetricsRemoveSessions) { + EngineMetrics engine_metrics; + + // Create two sessions and record some metrics. + SessionMetrics* session_metrics_1 = engine_metrics.AddSession(); + session_metrics_1->SetSessionId("session_id_1"); + SessionMetrics* session_metrics_2 = engine_metrics.AddSession(); + session_metrics_2->SetSessionId("session_id_2"); + // Mark only session 2 as completed. + session_metrics_2->SetCompleted(); + + // Serialize all metrics, don't remove any. + drm_metrics::MetricsGroup actual_metrics; + engine_metrics.Serialize(&actual_metrics, false, false); + + // Validate metric counts. + // Two sub groups, 1 per session. + ASSERT_EQ(2, actual_metrics.metric_sub_group_size()); + + // Serialize completed metrics, remove them. + actual_metrics.Clear(); + engine_metrics.Serialize(&actual_metrics, true, true); + // Validate metric counts. + // Only one, completed session should exist. + ASSERT_EQ(1, actual_metrics.metric_sub_group_size()); + ASSERT_EQ(1, actual_metrics.metric_sub_group(0).metric_size()); + EXPECT_EQ( + "session_id_2", + actual_metrics.metric_sub_group(0).metric(0).value().string_value()); + + // Serialize all metrics, remove them. + actual_metrics.Clear(); + engine_metrics.Serialize(&actual_metrics, false, true); + // Validate metric counts. + // Only one, non-complete session should exist. + ASSERT_EQ(1, actual_metrics.metric_sub_group_size()); + ASSERT_EQ(1, actual_metrics.metric_sub_group(0).metric_size()); + EXPECT_EQ( + "session_id_1", + actual_metrics.metric_sub_group(0).metric(0).value().string_value()); + + // Serialize all metrics, don't remove any. + actual_metrics.Clear(); + engine_metrics.Serialize(&actual_metrics, false, false); + // Validate metric counts. + // There should be no more metric subgroups left. + ASSERT_EQ(0, actual_metrics.metric_sub_group_size()); +} + +class SessionMetricsTest : public ::testing::Test { +}; + +TEST_F(SessionMetricsTest, AllSessionMetrics) { + SessionMetrics session_metrics; + session_metrics.SetSessionId("session_id 1"); + + session_metrics.cdm_session_life_span_.Record(1.0); + session_metrics.cdm_session_renew_key_.Record(1.0, NO_ERROR); + session_metrics.cdm_session_restore_offline_session_.Record(1.0, NO_ERROR); + session_metrics.cdm_session_restore_usage_session_.Record(1.0, NO_ERROR); + + // Record a CryptoMetrics metric in the session. + session_metrics.GetCryptoMetrics()->crypto_session_generic_decrypt_ + .Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128); + + MetricsGroup actual_metrics; + session_metrics.Serialize(&actual_metrics); + + ASSERT_EQ(11, actual_metrics.metric_size()); + EXPECT_EQ(0, actual_metrics.metric_sub_group_size()); + + // Spot check some metrics. + EXPECT_EQ("/drm/widevine/cdm_session/session_id", + actual_metrics.metric(0).name()); + EXPECT_EQ("/drm/widevine/cdm_session/life_span/time/count", + actual_metrics.metric(1).name()); + EXPECT_EQ("/drm/widevine/cdm_session/renew_key/time/mean{error:0}", + actual_metrics.metric(4).name()); + EXPECT_EQ(1.0, actual_metrics.metric(4).value().double_value()); + EXPECT_EQ("/drm/widevine/crypto_session/generic_decrypt/time/count" + "{error:0&length:1024&algorithm:1}", + actual_metrics.metric(9).name()); +} + +TEST_F(SessionMetricsTest, EmptySessionMetrics) { + SessionMetrics session_metrics; + + MetricsGroup actual_metrics; + session_metrics.Serialize(&actual_metrics); + + // Session metric always has a session id. + ASSERT_EQ(1, actual_metrics.metric_size()); + EXPECT_EQ("/drm/widevine/cdm_session/session_id", + actual_metrics.metric(0).name()); + EXPECT_EQ("", actual_metrics.metric(0).value().string_value()); + EXPECT_EQ(0, actual_metrics.metric_sub_group_size()); +} + +class CryptoMetricsTest : public ::testing::Test { +}; + +TEST_F(CryptoMetricsTest, AllCryptoMetrics) { + CryptoMetrics crypto_metrics; + + // Crypto session metrics. + crypto_metrics.crypto_session_delete_all_usage_reports_ + .Record(1.0, NO_ERROR); + crypto_metrics.crypto_session_delete_multiple_usage_information_ + .Record(1.0, NO_ERROR); + crypto_metrics.crypto_session_generic_decrypt_ + .Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128); + crypto_metrics.crypto_session_generic_encrypt_ + .Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128); + crypto_metrics.crypto_session_generic_sign_ + .Record(2.0, NO_ERROR, Pow2Bucket(1025), kSigningAlgorithmHmacSha256); + crypto_metrics.crypto_session_generic_verify_ + .Record(2.0, NO_ERROR, Pow2Bucket(1025), kSigningAlgorithmHmacSha256); + crypto_metrics.crypto_session_get_device_unique_id_.Record(1.0, true); + crypto_metrics.crypto_session_get_security_level_ + .Record(1.0, kSecurityLevelL1); + crypto_metrics.crypto_session_get_system_id_.Record(1.0, true, 1234); + crypto_metrics.crypto_session_get_token_.Record(1.0, true); + crypto_metrics.crypto_session_life_span_.Record(1.0); + crypto_metrics.crypto_session_load_certificate_private_key_ + .Record(1.0, true); + crypto_metrics.crypto_session_open_.Record(1.0, NO_ERROR, kLevelDefault); + crypto_metrics.crypto_session_update_usage_information_ + .Record(1.0, NO_ERROR); + crypto_metrics.crypto_session_usage_information_support_.Record(1.0, true); + + // Oem crypto metrics. + crypto_metrics.oemcrypto_api_version_.Record(1.0, 123, kLevelDefault); + crypto_metrics.oemcrypto_close_session_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_copy_buffer_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, + kLevelDefault, Pow2Bucket(1025)); + crypto_metrics.oemcrypto_deactivate_usage_entry_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_decrypt_cenc_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025)); + crypto_metrics.oemcrypto_delete_usage_entry_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_delete_usage_table_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_derive_keys_from_session_key_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_force_delete_usage_entry_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_generate_derived_keys_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_generate_nonce_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_generate_rsa_signature_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025)); + crypto_metrics.oemcrypto_generate_signature_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025)); + crypto_metrics.oemcrypto_generic_decrypt_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025)); + crypto_metrics.oemcrypto_generic_encrypt_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025)); + crypto_metrics.oemcrypto_generic_sign_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025)); + crypto_metrics.oemcrypto_generic_verify_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025)); + crypto_metrics.oemcrypto_get_device_id_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault); + crypto_metrics.oemcrypto_get_hdcp_capability_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault); + crypto_metrics.oemcrypto_get_key_data_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, + Pow2Bucket(1025), kLevelDefault); + crypto_metrics.oemcrypto_get_max_number_of_sessions_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault); + crypto_metrics.oemcrypto_get_number_of_open_sessions_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault); + crypto_metrics.oemcrypto_get_oem_public_certificate_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + + crypto_metrics.oemcrypto_get_provisioning_method_ + .Record(1.0, OEMCrypto_Keybox, kLevelDefault); + + crypto_metrics.oemcrypto_get_random_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025)); + crypto_metrics.oemcrypto_initialize_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_install_keybox_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault); + crypto_metrics.oemcrypto_is_anti_rollback_hw_present_ + .Record(1.0, true, kLevelDefault); + + crypto_metrics.oemcrypto_is_keybox_valid_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault); + crypto_metrics.oemcrypto_load_device_rsa_key_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_load_keys_.Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_load_test_keybox_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_load_test_rsa_key_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_open_session_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault); + crypto_metrics.oemcrypto_refresh_keys_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_report_usage_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_rewrap_device_rsa_key_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_rewrap_device_rsa_key_30_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_security_level_.Record(1.0, "test", kLevelDefault); + crypto_metrics.oemcrypto_security_patch_level_ + .Record(1.0, 123, kLevelDefault); + crypto_metrics.oemcrypto_select_key_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_supports_usage_table_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault); + crypto_metrics.oemcrypto_update_usage_table_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + crypto_metrics.oemcrypto_wrap_keybox_ + .Record(1.0, OEMCrypto_ERROR_INIT_FAILED); + + // Internal OEMCrypto Metrics + crypto_metrics.oemcrypto_initialization_mode_ + .Record(1.0, OEMCrypto_INITIALIZED_FORCING_L3); + crypto_metrics.oemcrypto_l1_api_version_.Record(1.0, 12, 123); + + MetricsGroup actual_metrics; + crypto_metrics.Serialize(&actual_metrics); + + // 61 EventMetric instances, 2 values each. + ASSERT_EQ(122, actual_metrics.metric_size()); + + // Spot check some metrics. + EXPECT_EQ( + "/drm/widevine/crypto_session/delete_all_usage_reports/time/count" + "{error:0}", + actual_metrics.metric(0).name()); + EXPECT_EQ(1, actual_metrics.metric(0).value().int_value()); + EXPECT_EQ( + "/drm/widevine/oemcrypto/l1_api_version/mean{version:12&min_version:123}", + actual_metrics.metric(121).name()); + EXPECT_EQ(1.0, actual_metrics.metric(121).value().double_value()); + + // No subgroups should exist. + EXPECT_EQ(0, actual_metrics.metric_sub_group_size()); +} + +} // namespace metrics +} // namespace wvcdm diff --git a/libwvdrmengine/cdm/src/ami_adapter.cpp b/libwvdrmengine/cdm/src/ami_adapter.cpp index 73dd4ee9..4c7cfc29 100644 --- a/libwvdrmengine/cdm/src/ami_adapter.cpp +++ b/libwvdrmengine/cdm/src/ami_adapter.cpp @@ -22,10 +22,6 @@ AmiAdapter::~AmiAdapter() { analytics_item_.selfrecord(); } -metrics::Report* AmiAdapter::NewReport() const { - return new AmiAdapter(analytics_item_.getSessionID()); -} - void AmiAdapter::UpdateString(const std::string& metric_id, const std::string& value) { analytics_item_.setCString(metric_id.c_str(), value.c_str()); diff --git a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp index 44bdecbd..385de117 100644 --- a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp +++ b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp @@ -7,7 +7,7 @@ #include "initialization_data.h" #include "license.h" #include "log.h" -#include "metrics_front_end.h" +#include "metrics.pb.h" #include "properties.h" #include "service_certificate.h" #include "wv_cdm_constants.h" @@ -21,22 +21,10 @@ namespace wvcdm { Lock WvContentDecryptionModule::session_sharing_id_generation_lock_; -WvContentDecryptionModule::WvContentDecryptionModule() { - // TODO (b/36497276) - // replace call to new AmiAdapter() and remove ami_apdater.* - report_root_ = NULL; // new AmiAdapter(); - front_end_ = new metrics::MetricsFrontEnd(report_root_); - metrics::MetricsFrontEnd::OverrideInstance(front_end_); -} +WvContentDecryptionModule::WvContentDecryptionModule() {} WvContentDecryptionModule::~WvContentDecryptionModule() { DisablePolicyTimer(true); - - metrics::MetricsFrontEnd::OverrideInstance(NULL); - delete front_end_; - delete report_root_; - front_end_ = NULL; - report_root_ = NULL; } bool WvContentDecryptionModule::IsSupported(const std::string& init_data_type) { @@ -409,6 +397,25 @@ bool WvContentDecryptionModule::IsValidServiceCertificate( NO_ERROR; } +void WvContentDecryptionModule::GetSerializedMetrics( + std::string* serialized_metrics) { + drm_metrics::MetricsGroup metric_group; + { + AutoLock auto_lock(cdms_lock_); + for (auto it = cdms_.begin(); it != cdms_.end(); it++) { + metrics::EngineMetrics* engine_metrics = + it->second.cdm_engine->GetMetrics(); + if (engine_metrics) { + // Serialize the metrics from the engine and any completed sessions. + // Clear the metrics from any completed sessions. + engine_metrics->Serialize( + metric_group.add_metric_sub_group(), true, true); + } + } + } + metric_group.SerializeToString(serialized_metrics); +} + WvContentDecryptionModule::CdmInfo::CdmInfo() : cdm_engine(new CdmEngine(&file_system)) {} diff --git a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp index e5e8bd56..77793b6c 100644 --- a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp @@ -529,13 +529,16 @@ status_t WVDrmPlugin::getPropertyString(const String8& name, status_t WVDrmPlugin::getPropertyByteArray(const String8& name, Vector& value) const { - if (name == "deviceUniqueId") { return queryProperty(QUERY_KEY_DEVICE_ID, value); } else if (name == "provisioningUniqueId") { return queryProperty(QUERY_KEY_PROVISIONING_ID, value); } else if (name == "serviceCertificate") { value = ToVector(mPropertySet.service_certificate()); + } else if (name == "metrics") { + std::string metrics_value; + mCDM->GetSerializedMetrics(&metrics_value); + value = ToVector(metrics_value); } else { ALOGE("App requested unknown byte array property %s", name.string()); return android::ERROR_DRM_CANNOT_HANDLE; diff --git a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp index 254ebf2c..5202e45b 100644 --- a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp @@ -714,6 +714,10 @@ Return WVDrmPlugin::getPropertyByteArray( } } else if (name == "serviceCertificate") { value = StrToVector(mPropertySet.service_certificate()); + } else if (name == "metrics") { + std::string metrics_value; + mCDM->GetSerializedMetrics(&metrics_value); + value = StrToVector(metrics_value); } else { ALOGE("App requested unknown byte array property %s", name.c_str()); status = android::ERROR_DRM_CANNOT_HANDLE; diff --git a/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp b/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp index 1d12d40f..080f7103 100644 --- a/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp +++ b/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp @@ -114,7 +114,17 @@ const std::string kAppId("com.unittest.mock.app.id"); const uint8_t* const kUnprovisionResponse = reinterpret_cast("unprovision"); const size_t kUnprovisionResponseSize = 11; -} +const std::string kDeviceId = "0123456789ABCDEF"; + +// This is a serialized MetricsGroup message containing a small amount of +// sample data. This ensures we're able to extract it via a property. +const char kSerializedMetrics[] = { + 0x0a, 0x0a, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x02, 0x08, 0x00, + 0x0a, 0x12, 0x0a, 0x05, 0x74, 0x65, 0x73, 0x74, 0x32, 0x12, 0x09, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x15, 0x0a, 0x05, + 0x74, 0x65, 0x73, 0x74, 0x33, 0x12, 0x0c, 0x1a, 0x0a, 0x74, 0x65, 0x73, + 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65}; +} // anonymous namespace class MockCDM : public WvContentDecryptionModule { public: @@ -180,6 +190,8 @@ class MockCDM : public WvContentDecryptionModule { CdmResponseType(const CdmUsageInfoReleaseMessage&, const CdmIdentifier&)); MOCK_METHOD1(IsValidServiceCertificate, bool(const std::string&)); + + MOCK_METHOD1(GetSerializedMetrics, void(std::string*)); }; class MockCrypto : public WVGenericCryptoInterface { @@ -1044,6 +1056,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { static const std::string openSessions = "42"; static const std::string maxSessions = "54"; static const std::string oemCryptoApiVersion = "13"; + std::string serializedMetrics( + kSerializedMetrics, kSerializedMetrics + sizeof(kSerializedMetrics)); EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _)) .WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1), @@ -1075,6 +1089,9 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { .WillOnce(DoAll(SetArgPointee<2>(oemCryptoApiVersion), testing::Return(wvcdm::NO_ERROR))); + EXPECT_CALL(*cdm, GetSerializedMetrics(_)) + .WillOnce(SetArgPointee<0>(serializedMetrics)); + WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto, false); std::string stringResult; std::vector vectorResult; @@ -1161,6 +1178,15 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { ASSERT_EQ(Status::OK, status); EXPECT_EQ(oemCryptoApiVersion, stringResult.c_str()); }); + + plugin.getPropertyByteArray( + hidl_string("metrics"), + [&](Status status, hidl_vec vectorResult) { + ASSERT_EQ(Status::OK, status); + std::vector id(vectorResult); + EXPECT_THAT(id, ElementsAreArray(serializedMetrics.data(), + serializedMetrics.size())); + }); } TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) { diff --git a/libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp b/libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp index 8be056f0..61b15756 100644 --- a/libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp +++ b/libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp @@ -32,7 +32,16 @@ const String8 kAppId("com.unittest.mock.app.id"); const uint8_t* const kUnprovisionResponse = reinterpret_cast("unprovision"); const size_t kUnprovisionResponseSize = 11; -} + +// This is a serialized MetricsGroup message containing a small amount of +// sample data. This ensures we're able to extract it via a property. +const char kSerializedMetrics[] = { + 0x0a, 0x0a, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x02, 0x08, 0x00, + 0x0a, 0x12, 0x0a, 0x05, 0x74, 0x65, 0x73, 0x74, 0x32, 0x12, 0x09, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x15, 0x0a, 0x05, + 0x74, 0x65, 0x73, 0x74, 0x33, 0x12, 0x0c, 0x1a, 0x0a, 0x74, 0x65, 0x73, + 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65}; +} // anonymous namespace class MockCDM : public WvContentDecryptionModule { public: @@ -98,6 +107,8 @@ class MockCDM : public WvContentDecryptionModule { CdmResponseType(const CdmUsageInfoReleaseMessage&, const CdmIdentifier&)); MOCK_METHOD1(IsValidServiceCertificate, bool(const std::string&)); + + MOCK_METHOD1(GetSerializedMetrics, void(std::string*)); }; class MockCrypto : public WVGenericCryptoInterface { @@ -837,6 +848,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { static const string openSessions = "15"; static const string maxSessions = "18"; static const string oemCryptoApiVersion = "10"; + string serializedMetrics(kSerializedMetrics, + kSerializedMetrics + sizeof(kSerializedMetrics)); EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _)) .WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1), @@ -868,6 +881,9 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { .WillOnce(DoAll(SetArgPointee<2>(oemCryptoApiVersion), Return(wvcdm::NO_ERROR))); + EXPECT_CALL(*cdm, GetSerializedMetrics(_)) + .WillOnce(SetArgPointee<0>(serializedMetrics)); + String8 stringResult; Vector vectorResult; @@ -919,6 +935,12 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { res = plugin.getPropertyString(String8("oemCryptoApiVersion"), stringResult); ASSERT_EQ(OK, res); EXPECT_EQ(oemCryptoApiVersion, stringResult.string()); + + vectorResult.clear(); + res = plugin.getPropertyByteArray(String8("metrics"), vectorResult); + ASSERT_EQ(OK, res); + EXPECT_THAT(vectorResult, ElementsAreArray(serializedMetrics.data(), + serializedMetrics.size())); } TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) {