diff --git a/libwvdrmengine/Android.mk b/libwvdrmengine/Android.mk index ff3e09bd..c6f29870 100644 --- a/libwvdrmengine/Android.mk +++ b/libwvdrmengine/Android.mk @@ -79,6 +79,7 @@ LOCAL_C_INCLUDES := \ frameworks/av/include \ frameworks/native/include \ vendor/widevine/libwvdrmengine/cdm/core/include \ + vendor/widevine/libwvdrmengine/cdm/metrics/include \ vendor/widevine/libwvdrmengine/cdm/include \ vendor/widevine/libwvdrmengine/include \ vendor/widevine/libwvdrmengine/mediacrypto/include \ @@ -98,6 +99,7 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libdl \ liblog \ + libmedia \ libprotobuf-cpp-lite \ libstagefright_foundation \ libutils \ diff --git a/libwvdrmengine/cdm/Android.mk b/libwvdrmengine/cdm/Android.mk index 2e0e6ade..01994f68 100644 --- a/libwvdrmengine/cdm/Android.mk +++ b/libwvdrmengine/cdm/Android.mk @@ -6,6 +6,7 @@ include $(CLEAR_VARS) LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/cdm/core/include \ + vendor/widevine/libwvdrmengine/cdm/metrics/include \ vendor/widevine/libwvdrmengine/cdm/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ vendor/widevine/libwvdrmengine/third_party/stringencoders/src @@ -18,6 +19,7 @@ LOCAL_STATIC_LIBRARIES := libcdm_protos libcrypto_static SRC_DIR := src CORE_SRC_DIR := core/src +METRICS_SRC_DIR := metrics/src LOCAL_SRC_FILES := \ $(CORE_SRC_DIR)/buffer_reader.cpp \ @@ -33,7 +35,13 @@ LOCAL_SRC_FILES := \ $(CORE_SRC_DIR)/policy_engine.cpp \ $(CORE_SRC_DIR)/privacy_crypto_openssl.cpp \ $(CORE_SRC_DIR)/service_certificate.cpp \ + $(SRC_DIR)/ami_adapter.cpp \ $(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)/timer_metric.cpp \ LOCAL_MODULE := libcdm diff --git a/libwvdrmengine/cdm/core/include/cdm_engine.h b/libwvdrmengine/cdm/core/include/cdm_engine.h index 6f9dad11..375982c2 100644 --- a/libwvdrmengine/cdm/core/include/cdm_engine.h +++ b/libwvdrmengine/cdm/core/include/cdm_engine.h @@ -13,6 +13,7 @@ #include "lock.h" #include "oemcrypto_adapter.h" #include "scoped_ptr.h" +#include "timer_metric.h" #include "wv_cdm_constants.h" #include "wv_cdm_types.h" @@ -210,6 +211,8 @@ class CdmEngine { // dead lock. virtual void OnTimerEvent(); + virtual metrics::MetricsGroup* GetMetrics() { return &metrics_; } + private: // private methods CdmResponseType OpenSession(const CdmKeySystem& key_system, @@ -231,6 +234,18 @@ class CdmEngine { void CloseExpiredReleaseSessions(); // 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::TimerMetric life_span_; + CdmSessionMap sessions_; CdmReleaseKeySetMap release_key_sets_; scoped_ptr cert_provisioning_; diff --git a/libwvdrmengine/cdm/core/include/cdm_session.h b/libwvdrmengine/cdm/core/include/cdm_session.h index 63c1908d..ec6ad0ef 100644 --- a/libwvdrmengine/cdm/core/include/cdm_session.h +++ b/libwvdrmengine/cdm/core/include/cdm_session.h @@ -11,9 +11,11 @@ #include "file_store.h" #include "initialization_data.h" #include "license.h" +#include "metrics_group.h" #include "oemcrypto_adapter.h" #include "policy_engine.h" #include "scoped_ptr.h" +#include "timer_metric.h" #include "wv_cdm_types.h" namespace wvcdm { @@ -151,6 +153,8 @@ class CdmSession { CdmSigningAlgorithm algorithm, const std::string& signature); + virtual metrics::MetricsGroup* GetMetrics() { return &metrics_; } + private: friend class CdmSessionTest; @@ -166,6 +170,17 @@ 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::TimerMetric life_span_; + bool initialized_; CdmSessionId session_id_; scoped_ptr license_parser_; diff --git a/libwvdrmengine/cdm/core/include/certificate_provisioning.h b/libwvdrmengine/cdm/core/include/certificate_provisioning.h index fd9a9dac..b124fb70 100644 --- a/libwvdrmengine/cdm/core/include/certificate_provisioning.h +++ b/libwvdrmengine/cdm/core/include/certificate_provisioning.h @@ -6,6 +6,7 @@ #include #include "crypto_session.h" +#include "metrics_group.h" #include "oemcrypto_adapter.h" #include "service_certificate.h" #include "wv_cdm_types.h" @@ -17,7 +18,8 @@ class FileSystem; class CertificateProvisioning { public: - CertificateProvisioning() : + CertificateProvisioning(metrics::MetricsGroup* metrics) : + crypto_session_(metrics), cert_type_(kCertificateWidevine), service_certificate_(NULL) {}; ~CertificateProvisioning() {}; diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index b1a2f3f9..cf817877 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -7,9 +7,11 @@ #include #include -#include "lock.h" -#include "oemcrypto_adapter.h" #include "OEMCryptoCENC.h" +#include "lock.h" +#include "metrics_group.h" +#include "oemcrypto_adapter.h" +#include "timer_metric.h" #include "wv_cdm_types.h" namespace wvcdm { @@ -32,7 +34,7 @@ class CryptoSession { bool rsa_cast; }; - CryptoSession(); + CryptoSession(metrics::MetricsGroup* metrics); virtual ~CryptoSession(); virtual bool GetClientToken(std::string* client_token); @@ -210,6 +212,9 @@ class CryptoSession { uint64_t request_id_base_; static uint64_t request_id_index_; + metrics::MetricsGroup* metrics_; + metrics::TimerMetric life_span_; + CdmCipherMode cipher_mode_; CORE_DISALLOW_COPY_AND_ASSIGN(CryptoSession); diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index 2574ac4a..ea5d81e3 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -14,6 +14,7 @@ #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" @@ -73,6 +74,8 @@ CdmEngine::CdmEngine(FileSystem* file_system, const std::string& spoid) srand(clock_.GetCurrentTime()); seeded_ = true; } + + life_span_.Start(); } CdmEngine::~CdmEngine() { @@ -82,6 +85,8 @@ CdmEngine::~CdmEngine() { delete i->second; } sessions_.clear(); + + M_RECORD(&metrics_, cdm_engine_life_span_, life_span_.AsMs()); } CdmResponseType CdmEngine::OpenSession(const CdmKeySystem& key_system, @@ -278,7 +283,13 @@ CdmResponseType CdmEngine::GenerateKeyRequest( if (license_type == kLicenseTypeRelease && !iter->second->license_received()) { - sts = iter->second->RestoreOfflineSession(key_set_id, kLicenseTypeRelease); + M_TIME( + sts = iter->second->RestoreOfflineSession( + key_set_id, + kLicenseTypeRelease), + iter->second->GetMetrics(), + cdm_session_restore_offline_session_, + sts); if (sts != KEY_ADDED) { LOGE("CdmEngine::GenerateKeyRequest: key release restoration failed," "sts = %d", static_cast(sts)); @@ -286,13 +297,24 @@ CdmResponseType CdmEngine::GenerateKeyRequest( } } - sts = iter->second->GenerateKeyRequest( - init_data, license_type, app_parameters, key_request); + M_TIME( + sts = iter->second->GenerateKeyRequest( + init_data, + license_type, + app_parameters, + key_request), + iter->second->GetMetrics(), + cdm_session_generate_key_request_, + sts); if (KEY_MESSAGE != sts) { if (sts == NEED_PROVISIONING) { - cert_provisioning_requested_security_level_ = - iter->second->GetRequestedSecurityLevel(); + M_TIME( + cert_provisioning_requested_security_level_ = + iter->second->GetRequestedSecurityLevel(), + iter->second->GetMetrics(), + cdm_session_get_requested_security_level_, + cert_provisioning_requested_security_level_); } LOGE("CdmEngine::GenerateKeyRequest: key request generation failed, " "sts = %d", static_cast(sts)); @@ -347,7 +369,13 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id, return EMPTY_KEY_DATA_1; } - CdmResponseType sts = iter->second->AddKey(key_data); + CdmResponseType sts; + M_TIME( + sts = iter->second->AddKey( + key_data), + iter->second->GetMetrics(), + cdm_session_add_key_, + sts); if (key_set_id) { *key_set_id = iter->second->key_set_id(); } @@ -382,11 +410,21 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id, return SESSION_NOT_FOUND_4; } - CdmResponseType sts = - iter->second->RestoreOfflineSession(key_set_id, kLicenseTypeOffline); + CdmResponseType sts; + M_TIME( + sts = iter->second->RestoreOfflineSession( + key_set_id, + kLicenseTypeOffline), + iter->second->GetMetrics(), + cdm_session_restore_offline_session_, + sts); if (sts == NEED_PROVISIONING) { - cert_provisioning_requested_security_level_ = - iter->second->GetRequestedSecurityLevel(); + M_TIME( + cert_provisioning_requested_security_level_ = + iter->second->GetRequestedSecurityLevel(), + iter->second->GetMetrics(), + cdm_session_get_requested_security_level_, + cert_provisioning_requested_security_level_); } if (sts != KEY_ADDED && sts != GET_RELEASED_LICENSE_ERROR) { LOGE("CdmEngine::RestoreKey: restore offline session failed = %d", sts); @@ -404,7 +442,11 @@ CdmResponseType CdmEngine::RemoveKeys(const CdmSessionId& session_id) { return SESSION_NOT_FOUND_5; } - iter->second->ReleaseCrypto(); + M_TIME( + iter->second->ReleaseCrypto(), + iter->second->GetMetrics(), + cdm_session_release_crypto_); + return NO_ERROR; } @@ -426,7 +468,13 @@ CdmResponseType CdmEngine::GenerateRenewalRequest( key_request->message.clear(); - CdmResponseType sts = iter->second->GenerateRenewalRequest(key_request); + CdmResponseType sts; + M_TIME( + sts= iter->second->GenerateRenewalRequest( + key_request), + iter->second->GetMetrics(), + cdm_session_generate_renewal_request_, + sts); if (KEY_MESSAGE != sts) { LOGE("CdmEngine::GenerateRenewalRequest: key request gen. failed, sts=%d", @@ -452,7 +500,13 @@ CdmResponseType CdmEngine::RenewKey(const CdmSessionId& session_id, return EMPTY_KEY_DATA_2; } - CdmResponseType sts = iter->second->RenewKey(key_data); + CdmResponseType sts; + M_TIME( + sts = iter->second->RenewKey( + key_data), + iter->second->GetMetrics(), + cdm_session_renew_key_, + sts); if (KEY_ADDED != sts) { LOGE("CdmEngine::RenewKey: keys not added, sts=%d", static_cast(sts)); return sts; @@ -465,9 +519,16 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, const std::string& query_token, std::string* query_response) { LOGI("CdmEngine::QueryStatus"); - CryptoSession crypto_session; + CryptoSession crypto_session(&metrics_); if (security_level == kLevel3) { - CdmResponseType status = crypto_session.Open(kLevel3); + CdmResponseType status; + M_TIME( + status = crypto_session.Open( + kLevel3), + &metrics_, + crypto_session_open_, + status, + kLevel3); if (NO_ERROR != status) return INVALID_QUERY_STATUS; } @@ -477,7 +538,12 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, } if (query_token == QUERY_KEY_SECURITY_LEVEL) { - CdmSecurityLevel security_level = crypto_session.GetSecurityLevel(); + CdmSecurityLevel security_level; + M_TIME( + security_level = crypto_session.GetSecurityLevel(), + &metrics_, + crypto_session_get_security_level_, + security_level); switch (security_level) { case kSecurityLevelL1: *query_response = QUERY_VALUE_SECURITY_LEVEL_L1; @@ -499,7 +565,14 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, } } else if (query_token == QUERY_KEY_DEVICE_ID) { std::string deviceId; - if (!crypto_session.GetDeviceUniqueId(&deviceId)) { + bool got_id; + M_TIME( + got_id = crypto_session.GetDeviceUniqueId( + &deviceId), + &metrics_, + crypto_session_get_device_unique_id_, + got_id); + if (!got_id) { LOGW("CdmEngine::QueryStatus: QUERY_KEY_DEVICE_ID unknown failure"); return UNKNOWN_ERROR; } @@ -507,7 +580,15 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, *query_response = deviceId; } else if (query_token == QUERY_KEY_SYSTEM_ID) { uint32_t system_id; - if (!crypto_session.GetSystemId(&system_id)) { + bool got_id; + M_TIME( + got_id = crypto_session.GetSystemId( + &system_id), + &metrics_, + crypto_session_get_system_id_, + got_id, + system_id); + if (!got_id) { LOGW("CdmEngine::QueryStatus: QUERY_KEY_SYSTEM_ID unknown failure"); return UNKNOWN_ERROR; } @@ -517,7 +598,14 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, *query_response = system_id_stream.str(); } else if (query_token == QUERY_KEY_PROVISIONING_ID) { std::string provisioning_id; - if (!crypto_session.GetProvisioningId(&provisioning_id)) { + bool got_id; + M_TIME( + got_id = crypto_session.GetProvisioningId( + &provisioning_id), + &metrics_, + crypto_session_get_provisioning_id_, + got_id); + if (!got_id) { LOGW("CdmEngine::QueryStatus: GetProvisioningId failed"); return UNKNOWN_ERROR; } @@ -527,7 +615,15 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, query_token == QUERY_KEY_MAX_HDCP_LEVEL) { CryptoSession::HdcpCapability current_hdcp; CryptoSession::HdcpCapability max_hdcp; - if (!crypto_session.GetHdcpCapabilities(¤t_hdcp, &max_hdcp)) { + bool got_hdcp; + M_TIME( + got_hdcp = crypto_session.GetHdcpCapabilities( + ¤t_hdcp, + &max_hdcp), + &metrics_, + crypto_session_get_hdcp_capabilities_, + got_hdcp); + if (!got_hdcp) { LOGW("CdmEngine::QueryStatus: GetHdcpCapabilities failed"); return UNKNOWN_ERROR; } @@ -536,7 +632,14 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, current_hdcp : max_hdcp); } else if (query_token == QUERY_KEY_USAGE_SUPPORT) { bool supports_usage_reporting; - if (!crypto_session.UsageInformationSupport(&supports_usage_reporting)) { + bool got_info; + M_TIME( + got_info = crypto_session.UsageInformationSupport( + &supports_usage_reporting), + &metrics_, + crypto_session_usage_information_support_, + got_info); + if (!got_info) { LOGW("CdmEngine::QueryStatus: UsageInformationSupport failed"); return UNKNOWN_ERROR; } @@ -545,7 +648,14 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, supports_usage_reporting ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE; } else if (query_token == QUERY_KEY_NUMBER_OF_OPEN_SESSIONS) { size_t number_of_open_sessions; - if (!crypto_session.GetNumberOfOpenSessions(&number_of_open_sessions)) { + bool got_num; + M_TIME( + got_num = crypto_session.GetNumberOfOpenSessions( + &number_of_open_sessions), + &metrics_, + crypto_session_get_number_of_open_sessions_, + got_num); + if (!got_num) { LOGW("CdmEngine::QueryStatus: GetNumberOfOpenSessions failed"); return UNKNOWN_ERROR; } @@ -555,7 +665,14 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, *query_response = open_sessions_stream.str(); } else if (query_token == QUERY_KEY_MAX_NUMBER_OF_SESSIONS) { size_t maximum_number_of_sessions; - if (!crypto_session.GetMaxNumberOfSessions(&maximum_number_of_sessions)) { + bool got_num; + M_TIME( + got_num = crypto_session.GetMaxNumberOfSessions( + &maximum_number_of_sessions), + &metrics_, + crypto_session_get_max_number_of_sessions_, + got_num); + if (!got_num) { LOGW("CdmEngine::QueryStatus: GetMaxNumberOfOpenSessions failed"); return UNKNOWN_ERROR; } @@ -565,7 +682,14 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, *query_response = max_sessions_stream.str(); } else if (query_token == QUERY_KEY_OEMCRYPTO_API_VERSION) { uint32_t api_version; - if (!crypto_session.GetApiVersion(&api_version)) { + bool got_version; + M_TIME( + got_version = crypto_session.GetApiVersion( + &api_version), + &metrics_, + crypto_session_get_api_version_, + got_version); + if (!got_version) { LOGW("CdmEngine::QueryStatus: GetApiVersion failed"); return UNKNOWN_ERROR; } @@ -591,7 +715,15 @@ CdmResponseType CdmEngine::QuerySessionStatus(const CdmSessionId& session_id, session_id.c_str()); return SESSION_NOT_FOUND_8; } - return iter->second->QueryStatus(query_response); + + CdmResponseType sts; + M_TIME( + sts = iter->second->QueryStatus( + query_response), + iter->second->GetMetrics(), + cdm_session_query_status_, + sts); + return sts; } bool CdmEngine::IsReleaseSession(const CdmSessionId& session_id) { @@ -625,7 +757,14 @@ CdmResponseType CdmEngine::QueryKeyStatus(const CdmSessionId& session_id, session_id.c_str()); return SESSION_NOT_FOUND_9; } - return iter->second->QueryKeyStatus(query_response); + CdmResponseType sts; + M_TIME( + sts = iter->second->QueryKeyStatus( + query_response), + iter->second->GetMetrics(), + cdm_session_query_key_status_, + sts); + return sts; } CdmResponseType CdmEngine::QueryKeyAllowedUsage(const CdmSessionId& session_id, @@ -642,7 +781,15 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const CdmSessionId& session_id, session_id.c_str()); return SESSION_NOT_FOUND_12; } - return iter->second->QueryKeyAllowedUsage(key_id, key_usage); + CdmResponseType sts; + M_TIME( + sts = iter->second->QueryKeyAllowedUsage( + key_id, + key_usage), + iter->second->GetMetrics(), + cdm_session_query_key_allowed_usage_, + sts); + return sts; } CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id, @@ -658,8 +805,13 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id, key_usage->Clear(); for (CdmSessionMap::iterator iter = sessions_.begin(); iter != sessions_.end(); ++iter) { - session_sts = iter->second->QueryKeyAllowedUsage(key_id, - &found_in_this_session); + M_TIME( + session_sts = iter->second->QueryKeyAllowedUsage( + key_id, + &found_in_this_session), + iter->second->GetMetrics(), + cdm_session_query_key_allowed_usage_, + session_sts); if (session_sts == NO_ERROR) { if (found) { // Found another key. If usage settings do not match, fail. @@ -690,7 +842,14 @@ CdmResponseType CdmEngine::QueryOemCryptoSessionId( session_id.c_str()); return SESSION_NOT_FOUND_10; } - return iter->second->QueryOemCryptoSessionId(query_response); + CdmResponseType sts; + M_TIME( + sts = iter->second->QueryOemCryptoSessionId( + query_response), + iter->second->GetMetrics(), + cdm_session_query_oemcrypto_session_id_, + sts); + return sts; } /* @@ -715,7 +874,7 @@ CdmResponseType CdmEngine::GetProvisioningRequest( DeleteAllUsageReportsUponFactoryReset(); if (NULL == cert_provisioning_.get()) { - cert_provisioning_.reset(new CertificateProvisioning()); + cert_provisioning_.reset(new CertificateProvisioning(&metrics_)); } CdmResponseType ret = cert_provisioning_->GetProvisioningRequest( cert_provisioning_requested_security_level_, cert_type, cert_authority, @@ -757,16 +916,27 @@ 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; - CdmResponseType status = - crypto_session.Open(cert_provisioning_requested_security_level_); + CryptoSession crypto_session(&metrics_); + CdmResponseType status; + M_TIME( + status = crypto_session.Open( + cert_provisioning_requested_security_level_), + &metrics_, + crypto_session_open_, + status, + cert_provisioning_requested_security_level_); if (NO_ERROR != status) { LOGE( "CdmEngine::HandleProvisioningResponse: provisioning object " "missing and crypto session open failed."); return EMPTY_PROVISIONING_CERTIFICATE_2; } - CdmSecurityLevel security_level = crypto_session.GetSecurityLevel(); + CdmSecurityLevel security_level; + M_TIME( + security_level = crypto_session.GetSecurityLevel(), + &metrics_, + crypto_session_get_security_level_, + security_level); if (!IsProvisioned(security_level)) { LOGE( "CdmEngine::HandleProvisioningResponse: provisioning object " @@ -814,14 +984,26 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) { return UNPROVISION_ERROR_3; } - CryptoSession crypto_session; - CdmResponseType status = crypto_session.Open( + CryptoSession crypto_session(&metrics_); + CdmResponseType status; + M_TIME( + status = crypto_session.Open( + security_level == kSecurityLevelL3 ? + kLevel3 : + kLevelDefault), + &metrics_, + crypto_session_open_, + status, security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault); if (NO_ERROR != status) { LOGE("CdmEngine::Unprovision: error opening crypto session: %d", status); return UNPROVISION_ERROR_4; } - status = crypto_session.DeleteAllUsageReports(); + M_TIME( + status = crypto_session.DeleteAllUsageReports(), + &metrics_, + crypto_session_delete_all_usage_reports_, + status); if (status != NO_ERROR) { LOGE("CdmEngine::Unprovision: error deleteing usage reports: %d", status); } @@ -1093,22 +1275,38 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id, return LOAD_USAGE_INFO_MISSING; } - CdmResponseType status = - iter->second->RestoreUsageSession(key_message, key_response); + CdmResponseType status; + M_TIME( + status = iter->second->RestoreUsageSession( + key_message, + key_response), + iter->second->GetMetrics(), + cdm_session_restore_usage_session_, + status); if (KEY_ADDED != status) { LOGE("CdmEngine::LoadUsageSession: usage session error %ld", status); return status; } CdmKeyRequest request; - status = iter->second->GenerateReleaseRequest(&request); + M_TIME( + status = iter->second->GenerateReleaseRequest( + &request), + iter->second->GetMetrics(), + cdm_session_generate_release_request_, + status); + *release_message = request.message; switch (status) { case KEY_MESSAGE: break; - case KEY_CANCELED: // usage information not present in - iter->second->DeleteLicense(); // OEMCrypto, delete and try again + case KEY_CANCELED: + /* usage information not present in OEMCrypto, delete and try again */ + M_TIME( + iter->second->DeleteLicense(), + iter->second->GetMetrics(), + cdm_session_delete_license_); break; default: LOGE("CdmEngine::LoadUsageSession: generate release request error: %d", @@ -1151,7 +1349,15 @@ CdmResponseType CdmEngine::Decrypt(const CdmSessionId& session_id, int64_t seconds_remaining = 0; for (CdmSessionMap::iterator iter = sessions_.begin(); iter != sessions_.end(); ++iter) { - if (iter->second->IsKeyLoaded(*parameters.key_id)) { + + bool is_key_loaded; + M_TIME( + is_key_loaded = iter->second->IsKeyLoaded( + *parameters.key_id), + iter->second->GetMetrics(), + cdm_session_is_key_loaded_, + is_key_loaded); + if (is_key_loaded) { int64_t duration = iter->second->GetDurationRemaining(); if (duration > seconds_remaining) { session_iter = iter; @@ -1168,7 +1374,14 @@ CdmResponseType CdmEngine::Decrypt(const CdmSessionId& session_id, return SESSION_NOT_FOUND_FOR_DECRYPT; } - return session_iter->second->Decrypt(parameters); + CdmResponseType decrypt_sts; + M_TIME( + decrypt_sts = session_iter->second->Decrypt( + parameters), + session_iter->second->GetMetrics(), + cdm_session_decrypt_, + decrypt_sts); + return decrypt_sts; } CdmResponseType CdmEngine::GenericEncrypt( @@ -1181,8 +1394,20 @@ CdmResponseType CdmEngine::GenericEncrypt( session_id.c_str()); return SESSION_NOT_FOUND_13; } - return iter->second->GenericEncrypt(in_buffer, key_id, iv, algorithm, - out_buffer); + CdmResponseType sts; + M_TIME( + sts = iter->second->GenericEncrypt( + in_buffer, + key_id, + iv, + algorithm, + out_buffer), + iter->second->GetMetrics(), + cdm_session_generic_encrypt_, + sts, + metrics::Pow2Bucket(in_buffer.size()), + algorithm); + return sts; } CdmResponseType CdmEngine::GenericDecrypt( @@ -1196,8 +1421,20 @@ CdmResponseType CdmEngine::GenericDecrypt( session_id.c_str()); return SESSION_NOT_FOUND_14; } - return iter->second->GenericDecrypt(in_buffer, key_id, iv, algorithm, - out_buffer); + CdmResponseType sts; + M_TIME( + sts = iter->second->GenericDecrypt( + in_buffer, + key_id, + iv, + algorithm, + out_buffer), + iter->second->GetMetrics(), + cdm_session_generic_decrypt_, + sts, + metrics::Pow2Bucket(in_buffer.size()), + algorithm); + return sts; } CdmResponseType CdmEngine::GenericSign( @@ -1210,7 +1447,19 @@ CdmResponseType CdmEngine::GenericSign( session_id.c_str()); return SESSION_NOT_FOUND_15; } - return iter->second->GenericSign(message, key_id, algorithm, signature); + CdmResponseType sts; + M_TIME( + sts = iter->second->GenericSign( + message, + key_id, + algorithm, + signature), + iter->second->GetMetrics(), + cdm_session_generic_sign_, + sts, + metrics::Pow2Bucket(message.size()), + algorithm); + return sts; } CdmResponseType CdmEngine::GenericVerify( @@ -1223,7 +1472,19 @@ CdmResponseType CdmEngine::GenericVerify( session_id.c_str()); return SESSION_NOT_FOUND_16; } - return iter->second->GenericVerify(message, key_id, algorithm, signature); + CdmResponseType sts; + M_TIME( + sts = iter->second->GenericVerify( + message, + key_id, + algorithm, + signature), + iter->second->GetMetrics(), + cdm_session_generic_verify_, + sts, + metrics::Pow2Bucket(message.size()), + algorithm); + return sts; } bool CdmEngine::IsKeyLoaded(const KeyId& key_id) { @@ -1318,7 +1579,12 @@ void CdmEngine::OnTimerEvent() { if (!has_usage_been_updated) { // usage is updated for all sessions so this needs to be // called only once per update usage information period - CdmResponseType status = iter->second->UpdateUsageInformation(); + CdmResponseType status; + M_TIME( + status = iter->second->UpdateUsageInformation(), + iter->second->GetMetrics(), + cdm_session_update_usage_information_, + status); if (NO_ERROR != status) { LOGW("Update usage information failed: %d", status); } else { @@ -1391,11 +1657,21 @@ void CdmEngine::DeleteAllUsageReportsUponFactoryReset() { if (!file_system_->Exists(device_base_path_level1) && !file_system_->Exists(device_base_path_level3)) { - scoped_ptr crypto_session(new CryptoSession()); - CdmResponseType status = crypto_session->Open( + scoped_ptr crypto_session(new CryptoSession(&metrics_)); + CdmResponseType status; + M_TIME( + status = crypto_session->Open( + cert_provisioning_requested_security_level_), + &metrics_, + crypto_session_open_, + status, cert_provisioning_requested_security_level_); if (NO_ERROR == status) { - status = crypto_session->DeleteAllUsageReports(); + M_TIME( + status = crypto_session->DeleteAllUsageReports(), + &metrics_, + crypto_session_delete_all_usage_reports_, + status); if (NO_ERROR != status) { LOGW( "CdmEngine::GetProvisioningRequest: " diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index 3c060115..11e7e700 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -12,6 +12,7 @@ #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,7 +26,6 @@ namespace wvcdm { CdmSession::CdmSession(FileSystem* file_system) : initialized_(false), - crypto_session_(new CryptoSession), file_handle_(new DeviceFiles(file_system)), license_received_(false), is_offline_(false), @@ -38,7 +38,10 @@ CdmSession::CdmSession(FileSystem* file_system) : is_initial_usage_update_(true), is_usage_update_needed_(false), mock_license_parser_in_use_(false), - mock_policy_engine_in_use_(false) {} + mock_policy_engine_in_use_(false), + crypto_session_(new CryptoSession(&metrics_)) { + life_span_.Start(); +} CdmSession::~CdmSession() { if (!key_set_id_.empty()) { @@ -46,6 +49,8 @@ CdmSession::~CdmSession() { file_handle_->UnreserveLicenseId(key_set_id_); } Properties::RemoveSessionPropertySet(session_id_); + + M_RECORD(&metrics_, cdm_session_life_span_, life_span_.AsMs()); } CdmResponseType CdmSession::Init( @@ -67,10 +72,20 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set, requested_security_level_ = kLevel3; security_level_ = kSecurityLevelL3; } - CdmResponseType sts = crypto_session_->Open(requested_security_level_); + CdmResponseType sts; + M_TIME( + sts = crypto_session_->Open( + requested_security_level_), + &metrics_, + crypto_session_open_, + sts, + requested_security_level_); if (NO_ERROR != sts) return sts; - security_level_ = crypto_session_->GetSecurityLevel(); - + M_TIME( + security_level_ = crypto_session_->GetSecurityLevel(), + &metrics_, + crypto_session_get_security_level_, + security_level_); if (!file_handle_->Init(security_level_)) { LOGE("CdmSession::Init: Unable to initialize file handle"); return SESSION_FILE_HANDLE_INIT_ERROR; @@ -90,15 +105,32 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set, // Keybox is client token. LOGW("CdmSession::Init: Properties::use_certificates_as_identification() " "is not set - using Keybox for license requests (not recommended)."); - if (!crypto_session_->GetClientToken(&client_token)) { + + bool get_client_token_sts; + M_TIME( + get_client_token_sts = crypto_session_->GetClientToken( + &client_token), + &metrics_, + crypto_session_get_token_, + get_client_token_sts); + if (!get_client_token_sts) { return SESSION_INIT_ERROR_1; } } else { // License server client ID token is a stored certificate. Stage it or // indicate that provisioning is needed. Get token from stored certificate std::string wrapped_key; - if (!file_handle_->RetrieveCertificate(&client_token, &wrapped_key) || - !crypto_session_->LoadCertificatePrivateKey(wrapped_key)) { + if (!file_handle_->RetrieveCertificate(&client_token, &wrapped_key)) { + return NEED_PROVISIONING; + } + bool load_cert_sts; + M_TIME( + load_cert_sts = crypto_session_->LoadCertificatePrivateKey( + wrapped_key), + &metrics_, + crypto_session_load_certificate_private_key_, + load_cert_sts); + if(!load_cert_sts) { return NEED_PROVISIONING; } client_token_type = kClientTokenDrmCert; @@ -417,7 +449,13 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) { return policy_engine_->IsLicenseForFuture() ? DECRYPT_NOT_READY : NEED_KEY; } - CdmResponseType status = crypto_session_->Decrypt(params); + CdmResponseType status; + + M_TIME( + status = crypto_session_->Decrypt( + params), + &metrics_, crypto_session_decrypt_, + status); if (status == NO_ERROR) { if (is_initial_decryption_) { @@ -526,8 +564,19 @@ bool CdmSession::GenerateKeySetId(CdmKeySetId* key_set_id) { (kKeySetIdLength - sizeof(KEY_SET_ID_PREFIX)) / 2, 0); while (key_set_id->empty()) { - if (!crypto_session_->GetRandom(random_data.size(), &random_data[0])) + bool sts; + M_TIME( + sts = crypto_session_->GetRandom( + random_data.size(), + &random_data[0]), + &metrics_, + crypto_session_get_random_, + sts, + metrics::Pow2Bucket(random_data.size())); + + if (!sts) { return false; + } *key_set_id = KEY_SET_ID_PREFIX + b2a_hex(random_data); @@ -595,7 +644,11 @@ bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) { } CdmResponseType CdmSession::ReleaseCrypto() { - crypto_session_->Close(); + M_TIME( + crypto_session_->Close(), + &metrics_, + crypto_session_close_); + return NO_ERROR; } @@ -642,12 +695,24 @@ void CdmSession::GetApplicationId(std::string* app_id) { CdmResponseType CdmSession::DeleteMultipleUsageInformation( const std::vector& provider_session_tokens) { - return crypto_session_->DeleteMultipleUsageInformation( - provider_session_tokens); + CdmResponseType sts; + M_TIME( + sts = crypto_session_->DeleteMultipleUsageInformation( + provider_session_tokens), + &metrics_, + crypto_session_delete_multiple_usage_information_, + sts); + return sts; } CdmResponseType CdmSession::UpdateUsageInformation() { - return crypto_session_->UpdateUsageInformation(); + CdmResponseType sts; + M_TIME( + sts = crypto_session_->UpdateUsageInformation(), + &metrics_, + crypto_session_update_usage_information_, + sts); + return sts; } CdmResponseType CdmSession::GenericEncrypt(const std::string& in_buffer, @@ -659,8 +724,20 @@ CdmResponseType CdmSession::GenericEncrypt(const std::string& in_buffer, LOGE("CdmSession::GenericEncrypt: No output destination provided"); return INVALID_PARAMETERS_ENG_6; } - return crypto_session_->GenericEncrypt(in_buffer, key_id, iv, algorithm, - out_buffer); + CdmResponseType sts; + M_TIME( + sts = crypto_session_->GenericEncrypt( + in_buffer, + key_id, + iv, + algorithm, + out_buffer), + &metrics_, + crypto_session_generic_encrypt_, + sts, + metrics::Pow2Bucket(in_buffer.size()), + algorithm); + return sts; } CdmResponseType CdmSession::GenericDecrypt(const std::string& in_buffer, @@ -672,8 +749,20 @@ CdmResponseType CdmSession::GenericDecrypt(const std::string& in_buffer, LOGE("CdmSession::GenericDecrypt: No output destination provided"); return INVALID_PARAMETERS_ENG_7; } - return crypto_session_->GenericDecrypt(in_buffer, key_id, iv, algorithm, - out_buffer); + CdmResponseType sts; + M_TIME( + sts = crypto_session_->GenericDecrypt( + in_buffer, + key_id, + iv, + algorithm, + out_buffer), + &metrics_, + crypto_session_generic_decrypt_, + sts, + metrics::Pow2Bucket(in_buffer.size()), + algorithm); + return sts; } CdmResponseType CdmSession::GenericSign(const std::string& message, @@ -684,14 +773,38 @@ CdmResponseType CdmSession::GenericSign(const std::string& message, LOGE("CdmSession::GenericSign: No output destination provided"); return INVALID_PARAMETERS_ENG_8; } - return crypto_session_->GenericSign(message, key_id, algorithm, signature); + CdmResponseType sts; + M_TIME( + sts = crypto_session_->GenericSign( + message, + key_id, + algorithm, + signature), + &metrics_, + crypto_session_generic_sign_, + sts, + metrics::Pow2Bucket(message.size()), + algorithm); + return sts; } CdmResponseType CdmSession::GenericVerify(const std::string& message, const std::string& key_id, CdmSigningAlgorithm algorithm, const std::string& signature) { - return crypto_session_->GenericVerify(message, key_id, algorithm, signature); + CdmResponseType sts; + M_TIME( + sts = crypto_session_->GenericVerify( + message, + key_id, + algorithm, + signature), + &metrics_, + crypto_session_generic_verify_, + sts, + metrics::Pow2Bucket(message.size()), + algorithm); + return sts; } // For testing only - takes ownership of pointers diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 49067495..2ea19f4b 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -12,6 +12,7 @@ #include "crypto_key.h" #include "log.h" +#include "metrics_front_end.h" #include "properties.h" #include "pst_report.h" #include "string_conversions.h" @@ -39,14 +40,16 @@ bool CryptoSession::initialized_ = false; int CryptoSession::session_count_ = 0; uint64_t CryptoSession::request_id_index_ = 0; -CryptoSession::CryptoSession() - : open_(false), +CryptoSession::CryptoSession(metrics::MetricsGroup* metrics) + : metrics_(metrics), + open_(false), update_usage_table_after_close_session_(false), is_destination_buffer_type_valid_(false), requested_security_level_(kLevelDefault), request_id_base_(0), cipher_mode_(kCipherModeCtr) { Init(); + life_span_.Start(); } CryptoSession::~CryptoSession() { @@ -54,6 +57,7 @@ CryptoSession::~CryptoSession() { Close(); } Terminate(); + M_RECORD(metrics_, crypto_session_life_span_, life_span_.AsMs()); } bool CryptoSession::GetProvisioningMethod(CdmClientTokenType* token_type) { @@ -81,7 +85,12 @@ void CryptoSession::Init() { AutoLock auto_lock(crypto_lock_); session_count_ += 1; if (!initialized_) { - OEMCryptoResult sts = OEMCrypto_Initialize(); + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_Initialize(), + metrics_, + oemcrypto_initialize_, + sts); if (OEMCrypto_SUCCESS != sts) { LOGE("OEMCrypto_Initialize failed: %d", sts); return; @@ -116,8 +125,19 @@ bool CryptoSession::GetTokenFromKeybox(std::string* token) { // lock is held by caller size_t buf_size = temp_buffer.size(); uint8_t* buf = reinterpret_cast(&temp_buffer[0]); - status = OEMCrypto_GetKeyData(buf, &buf_size, requested_security_level_); - if (status == OEMCrypto_SUCCESS) { + + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_GetKeyData( + buf, + &buf_size, + requested_security_level_), + metrics_, + oemcrypto_get_key_data_, + sts, + metrics::Pow2Bucket(buf_size), + requested_security_level_); + if (OEMCrypto_SUCCESS == sts) { token->swap(temp_buffer); return true; } @@ -158,7 +178,6 @@ bool CryptoSession::GetClientToken(std::string* token) { if (!initialized_) { return false; } - // Only keybox is used for client token. All other cases use DRM Cert. if (pre_provision_token_type_ != kClientTokenKeybox) { return false; @@ -194,8 +213,14 @@ CdmSecurityLevel CryptoSession::GetSecurityLevel() { return kSecurityLevelUninitialized; } - std::string security_level = - OEMCrypto_SecurityLevel(requested_security_level_); + std::string security_level; + M_TIME( + security_level = OEMCrypto_SecurityLevel( + requested_security_level_), + metrics_, + oemcrypto_security_level_, + security_level, + requested_security_level_); if ((security_level.size() != 2) || (security_level.at(0) != 'L')) { return kSecurityLevelUnknown; @@ -234,8 +259,16 @@ bool CryptoSession::GetDeviceUniqueId(std::string* device_id) { size_t id_length = 32; id.resize(id_length); - OEMCryptoResult sts = - OEMCrypto_GetDeviceID(&id[0], &id_length, requested_security_level_); + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_GetDeviceID( + &id[0], + &id_length, + requested_security_level_), + metrics_, + oemcrypto_get_device_id_, + sts, + requested_security_level_); if (OEMCrypto_SUCCESS != sts) { return false; @@ -255,7 +288,13 @@ bool CryptoSession::GetApiVersion(uint32_t* version) { if (!initialized_) { return false; } - *version = OEMCrypto_APIVersion(requested_security_level_); + M_TIME( + *version = OEMCrypto_APIVersion(requested_security_level_), + metrics_, + oemcrypto_api_version_, + *version, + requested_security_level_); + return true; } @@ -273,8 +312,17 @@ bool CryptoSession::GetSystemId(uint32_t* system_id) { if (!initialized_) { return false; } - OEMCryptoResult sts = - OEMCrypto_GetKeyData(buf, &buf_size, requested_security_level_); + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_GetKeyData( + buf, + &buf_size, + requested_security_level_), + metrics_, + oemcrypto_get_key_data_, + sts, + metrics::Pow2Bucket(buf_size), + requested_security_level_); if (OEMCrypto_SUCCESS != sts) { return false; @@ -302,9 +350,17 @@ bool CryptoSession::GetProvisioningId(std::string* provisioning_id) { if (!initialized_) { return false; } - OEMCryptoResult sts = - OEMCrypto_GetKeyData(buf, &buf_size, requested_security_level_); - + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_GetKeyData( + buf, + &buf_size, + requested_security_level_), + metrics_, + oemcrypto_get_key_data_, + sts, + metrics::Pow2Bucket(buf_size), + requested_security_level_); if (OEMCrypto_SUCCESS != sts) { return false; } @@ -314,7 +370,15 @@ bool CryptoSession::GetProvisioningId(std::string* provisioning_id) { } uint8_t CryptoSession::GetSecurityPatchLevel() { - return OEMCrypto_Security_Patch_Level(requested_security_level_); + uint8_t patch; + M_TIME( + patch = OEMCrypto_Security_Patch_Level( + requested_security_level_), + metrics_, + oemcrypto_security_patch_level_, + patch, + requested_security_level_); + return patch; } CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) { @@ -325,7 +389,15 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) { OEMCrypto_SESSION sid; requested_security_level_ = requested_security_level; - OEMCryptoResult sts = OEMCrypto_OpenSession(&sid, requested_security_level); + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_OpenSession( + &sid, + requested_security_level), + metrics_, + oemcrypto_open_session_, + sts, + requested_security_level); if (OEMCrypto_SUCCESS == sts) { oec_session_id_ = static_cast(sid); LOGV("OpenSession: id= %ld", (uint32_t)oec_session_id_); @@ -340,8 +412,15 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) { sts, session_count_, (int)initialized_); return UNKNOWN_ERROR; } - OEMCrypto_GetRandom(reinterpret_cast(&request_id_base_), - sizeof(request_id_base_)); + OEMCryptoResult random_sts; + M_TIME( + random_sts = OEMCrypto_GetRandom( + reinterpret_cast(&request_id_base_), + sizeof(request_id_base_)), + metrics_, + oemcrypto_get_random_, + random_sts, + metrics::Pow2Bucket(sizeof(request_id_base_))); ++request_id_index_; return NO_ERROR; } @@ -351,12 +430,25 @@ void CryptoSession::Close() { open_ ? "true" : "false"); AutoLock auto_lock(crypto_lock_); if (!open_) return; - if (OEMCrypto_SUCCESS == OEMCrypto_CloseSession(oec_session_id_)) { + + OEMCryptoResult close_sts; + M_TIME( + close_sts = OEMCrypto_CloseSession( + oec_session_id_), + metrics_, + oemcrypto_close_session_, + close_sts); + if (OEMCrypto_SUCCESS == close_sts) { open_ = false; if (update_usage_table_after_close_session_) { - OEMCryptoResult sts = OEMCrypto_UpdateUsageTable(); - if (sts != OEMCrypto_SUCCESS) - LOGW("CryptoSession::Close: OEMCrypto_UpdateUsageTable error=%ld", sts); + OEMCryptoResult update_sts; + M_TIME( + update_sts = OEMCrypto_UpdateUsageTable(), + metrics_, + oemcrypto_update_usage_table_, + update_sts); + if ( update_sts != OEMCrypto_SUCCESS) + LOGW("CryptoSession::Close: OEMCrypto_UpdateUsageTable error=%ld", update_sts); } } } @@ -504,24 +596,39 @@ CdmResponseType CryptoSession::LoadKeys( } uint8_t* pst = NULL; if (!provider_session_token.empty()) { - pst = - const_cast(msg) + GetOffset(message, provider_session_token); + pst = const_cast(msg) + GetOffset(message, provider_session_token); } uint8_t* srm_req = NULL; if (!srm_requirement.empty()) srm_req = const_cast(msg) + GetOffset(message, srm_requirement); LOGV("LoadKeys: id=%ld", (uint32_t)oec_session_id_); - OEMCryptoResult sts = OEMCrypto_LoadKeys( - oec_session_id_, msg, message.size(), - reinterpret_cast(signature.data()), signature.size(), - enc_mac_key_iv, enc_mac_key, keys.size(), &load_keys[0], pst, - provider_session_token.length(), srm_req); - + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_LoadKeys( + oec_session_id_, + msg, + message.size(), + reinterpret_cast(signature.data()), + signature.size(), + enc_mac_key_iv, + enc_mac_key, + keys.size(), + &load_keys[0], + pst, + provider_session_token.length(), + srm_req), + metrics_, + oemcrypto_load_keys_, + sts); if (OEMCrypto_SUCCESS == sts) { if (!provider_session_token.empty()) { update_usage_table_after_close_session_ = true; - sts = OEMCrypto_UpdateUsageTable(); + M_TIME( + sts = OEMCrypto_UpdateUsageTable(), + metrics_, + oemcrypto_update_usage_table_, + sts); if (sts != OEMCrypto_SUCCESS) { LOGW("CryptoSession::LoadKeys: OEMCrypto_UpdateUsageTable error=%ld", sts); @@ -542,10 +649,15 @@ bool CryptoSession::LoadCertificatePrivateKey(std::string& wrapped_key) { AutoLock auto_lock(crypto_lock_); LOGV("LoadDeviceRSAKey: id=%ld", (uint32_t)oec_session_id_); - OEMCryptoResult sts = OEMCrypto_LoadDeviceRSAKey( - oec_session_id_, reinterpret_cast(wrapped_key.data()), - wrapped_key.size()); - + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_LoadDeviceRSAKey( + oec_session_id_, + reinterpret_cast(wrapped_key.data()), + wrapped_key.size()), + metrics_, + oemcrypto_load_device_rsa_key_, + sts); if (OEMCrypto_SUCCESS != sts) { LOGE("LoadCertificatePrivateKey: OEMCrypto_LoadDeviceRSAKey error=%d", sts); return false; @@ -583,11 +695,20 @@ bool CryptoSession::RefreshKeys(const std::string& message, } } LOGV("RefreshKeys: id=%ld", static_cast(oec_session_id_)); - return ( - OEMCrypto_SUCCESS == - OEMCrypto_RefreshKeys(oec_session_id_, msg, message.size(), - reinterpret_cast(signature.data()), - signature.size(), num_keys, &load_key_array[0])); + OEMCryptoResult refresh_sts; + M_TIME( + refresh_sts = OEMCrypto_RefreshKeys( + oec_session_id_, + msg, + message.size(), + reinterpret_cast(signature.data()), + signature.size(), + num_keys, + &load_key_array[0]), + metrics_, + oemcrypto_refresh_keys_, + refresh_sts); + return OEMCrypto_SUCCESS == refresh_sts; } CdmResponseType CryptoSession::SelectKey(const std::string& key_id) { @@ -602,10 +723,21 @@ CdmResponseType CryptoSession::SelectKey(const std::string& key_id) { const uint8_t* key_id_string = reinterpret_cast(cached_key_id_.data()); - OEMCryptoResult sts = - OEMCrypto_SelectKey(oec_session_id_, key_id_string, - cached_key_id_.size()); - if (OEMCrypto_SUCCESS != sts) cached_key_id_.clear(); + OEMCryptoResult sts; + + M_TIME( + sts = OEMCrypto_SelectKey( + oec_session_id_, + key_id_string, + cached_key_id_.size()), + metrics_, + oemcrypto_select_key_, + sts); + + + if (OEMCrypto_SUCCESS != sts) { + cached_key_id_.clear(); + } switch (sts) { case OEMCrypto_SUCCESS: @@ -640,13 +772,17 @@ bool CryptoSession::GenerateDerivedKeys(const std::string& message) { GenerateEncryptContext(message, &enc_deriv_message); LOGV("GenerateDerivedKeys: id=%ld", (uint32_t)oec_session_id_); - OEMCryptoResult sts = OEMCrypto_GenerateDerivedKeys( - oec_session_id_, - reinterpret_cast(mac_deriv_message.data()), - mac_deriv_message.size(), - reinterpret_cast(enc_deriv_message.data()), - enc_deriv_message.size()); - + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_GenerateDerivedKeys( + oec_session_id_, + reinterpret_cast(mac_deriv_message.data()), + mac_deriv_message.size(), + reinterpret_cast(enc_deriv_message.data()), + enc_deriv_message.size()), + metrics_, + oemcrypto_generate_derived_keys_, + sts); if (OEMCrypto_SUCCESS != sts) { LOGE("GenerateDerivedKeys: OEMCrypto_GenerateDerivedKeys error=%d", sts); return false; @@ -663,13 +799,19 @@ bool CryptoSession::GenerateDerivedKeys(const std::string& message, GenerateEncryptContext(message, &enc_deriv_message); LOGV("GenerateDerivedKeys: id=%ld", (uint32_t)oec_session_id_); - OEMCryptoResult sts = OEMCrypto_DeriveKeysFromSessionKey( - oec_session_id_, reinterpret_cast(session_key.data()), - session_key.size(), - reinterpret_cast(mac_deriv_message.data()), - mac_deriv_message.size(), - reinterpret_cast(enc_deriv_message.data()), - enc_deriv_message.size()); + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_DeriveKeysFromSessionKey( + oec_session_id_, + reinterpret_cast(session_key.data()), + session_key.size(), + reinterpret_cast(mac_deriv_message.data()), + mac_deriv_message.size(), + reinterpret_cast(enc_deriv_message.data()), + enc_deriv_message.size()), + metrics_, + oemcrypto_derive_keys_from_session_key_, + sts); if (OEMCrypto_SUCCESS != sts) { LOGE("GenerateDerivedKeys: OEMCrypto_DeriveKeysFromSessionKey err=%d", sts); @@ -693,12 +835,17 @@ bool CryptoSession::GenerateSignature(const std::string& message, // At most two attempts. // The first attempt may fail due to buffer too short for (int i = 0; i < 2; ++i) { - sts = OEMCrypto_GenerateSignature( - oec_session_id_, reinterpret_cast(message.data()), - message.size(), - reinterpret_cast(const_cast(signature->data())), - &length); - + M_TIME( + sts = OEMCrypto_GenerateSignature( + oec_session_id_, + reinterpret_cast(message.data()), + message.size(), + reinterpret_cast(const_cast(signature->data())), + &length), + metrics_, + oemcrypto_generate_signature_, + sts, + metrics::Pow2Bucket(length)); if (OEMCrypto_SUCCESS == sts) { // Trim signature buffer and done signature->resize(length); @@ -731,11 +878,18 @@ bool CryptoSession::GenerateRsaSignature(const std::string& message, // At most two attempts. // The first attempt may fail due to buffer too short for (int i = 0; i < 2; ++i) { - sts = OEMCrypto_GenerateRSASignature( - oec_session_id_, reinterpret_cast(message.data()), - message.size(), - reinterpret_cast(const_cast(signature->data())), - &length, kSign_RSASSA_PSS); + M_TIME( + sts = OEMCrypto_GenerateRSASignature( + oec_session_id_, + reinterpret_cast(message.data()), + message.size(), + reinterpret_cast(const_cast(signature->data())), + &length, + kSign_RSASSA_PSS), + metrics_, + oemcrypto_generate_rsa_signature_, + sts, + metrics::Pow2Bucket(length)); if (OEMCrypto_SUCCESS == sts) { // Trim signature buffer and done @@ -791,9 +945,19 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) { if (!params.is_encrypted && params.subsample_flags == (OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample)) { - sts = OEMCrypto_CopyBuffer(requested_security_level_, - params.encrypt_buffer, params.encrypt_length, - &buffer_descriptor, params.subsample_flags); + + M_TIME( + sts = OEMCrypto_CopyBuffer( + requested_security_level_, + params.encrypt_buffer, + params.encrypt_length, + &buffer_descriptor, + params.subsample_flags), + metrics_, + oemcrypto_copy_buffer_, + sts, + requested_security_level_, + metrics::Pow2Bucket(params.encrypt_length)); if (sts == OEMCrypto_ERROR_BUFFER_TOO_LARGE && params.encrypt_length > kMaximumChunkSize) { @@ -816,11 +980,22 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) { CdmResponseType result = SelectKey(*params.key_id); if (result != NO_ERROR) return result; } - sts = OEMCrypto_DecryptCENC( - oec_session_id_, params.encrypt_buffer, params.encrypt_length, - params.is_encrypted, &(*params.iv).front(), params.block_offset, - &buffer_descriptor, &pattern_descriptor, params.subsample_flags); + M_TIME( + sts = OEMCrypto_DecryptCENC( + oec_session_id_, + params.encrypt_buffer, + params.encrypt_length, + params.is_encrypted, + &(*params.iv).front(), + params.block_offset, + &buffer_descriptor, + &pattern_descriptor, + params.subsample_flags), + metrics_, + oemcrypto_decrypt_cenc_, + sts, + metrics::Pow2Bucket(params.encrypt_length)); if (sts == OEMCrypto_ERROR_BUFFER_TOO_LARGE) { // OEMCrypto_DecryptCENC rejected the buffer as too large, so chunk it up @@ -876,7 +1051,12 @@ CdmResponseType CryptoSession::UpdateUsageInformation() { AutoLock auto_lock(crypto_lock_); if (!initialized_) return UNKNOWN_ERROR; - OEMCryptoResult status = OEMCrypto_UpdateUsageTable(); + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_UpdateUsageTable(), + metrics_, + oemcrypto_update_usage_table_, + status); if (status != OEMCrypto_SUCCESS) { LOGE("CryptoSession::UsageUsageInformation: error=%ld", status); return UNKNOWN_ERROR; @@ -893,9 +1073,15 @@ CdmResponseType CryptoSession::DeactivateUsageInformation( const_cast(provider_session_token.data())); // TODO(fredgc or rfrias): make sure oec_session_id_ is valid. - OEMCryptoResult status = - OEMCrypto_DeactivateUsageEntry((uint32_t)oec_session_id_, - pst, provider_session_token.length()); + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_DeactivateUsageEntry( + (uint32_t)oec_session_id_, + pst, + provider_session_token.length()), + metrics_, + oemcrypto_deactivate_usage_entry_, + status); switch (status) { case OEMCrypto_SUCCESS: @@ -925,9 +1111,17 @@ CdmResponseType CryptoSession::GenerateUsageReport( const_cast(provider_session_token.data())); size_t usage_length = 0; - OEMCryptoResult status = OEMCrypto_ReportUsage( - oec_session_id_, pst, provider_session_token.length(), NULL, - &usage_length); + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_ReportUsage( + oec_session_id_, + pst, + provider_session_token.length(), + NULL, + &usage_length), + metrics_, + oemcrypto_report_usage_, + status); if (OEMCrypto_SUCCESS != status) { if (OEMCrypto_ERROR_SHORT_BUFFER != status) { @@ -938,9 +1132,17 @@ CdmResponseType CryptoSession::GenerateUsageReport( } std::vector buffer(usage_length); - status = OEMCrypto_ReportUsage(oec_session_id_, pst, - provider_session_token.length(), - &buffer[0], &usage_length); + + M_TIME( + status = OEMCrypto_ReportUsage( + oec_session_id_, + pst, + provider_session_token.length(), + &buffer[0], + &usage_length), + metrics_, + oemcrypto_report_usage_, + status); if (OEMCrypto_SUCCESS != status) { LOGE("CryptoSession::GenerateUsageReport: Report Usage error=%ld", status); @@ -1008,16 +1210,30 @@ CdmResponseType CryptoSession::ReleaseUsageInformation( const uint8_t* sig = reinterpret_cast(signature.data()); const uint8_t* pst = msg + GetOffset(message, provider_session_token); - OEMCryptoResult status = OEMCrypto_DeleteUsageEntry( - oec_session_id_, pst, provider_session_token.length(), msg, - message.length(), sig, signature.length()); + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_DeleteUsageEntry( + oec_session_id_, + pst, + provider_session_token.length(), + msg, + message.length(), + sig, + signature.length()), + metrics_, + oemcrypto_delete_usage_entry_, + status); if (OEMCrypto_SUCCESS != status) { LOGE("CryptoSession::ReleaseUsageInformation: Report Usage error=%ld", status); return UNKNOWN_ERROR; } - status = OEMCrypto_UpdateUsageTable(); + M_TIME( + status = OEMCrypto_UpdateUsageTable(), + metrics_, + oemcrypto_update_usage_table_, + status); if (status != OEMCrypto_SUCCESS) { LOGW("CryptoSession::ReleaseUsageInformation: update table error=%ld", status); @@ -1030,15 +1246,24 @@ CdmResponseType CryptoSession::DeleteUsageInformation( const std::string& provider_session_token) { CdmResponseType response = NO_ERROR; LOGV("CryptoSession::DeleteUsageInformation"); - OEMCryptoResult status = OEMCrypto_ForceDeleteUsageEntry( - reinterpret_cast(provider_session_token.c_str()), - provider_session_token.length()); + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_ForceDeleteUsageEntry( + reinterpret_cast(provider_session_token.c_str()), + provider_session_token.length()), + metrics_, + oemcrypto_force_delete_usage_entry_, + status); if (OEMCrypto_SUCCESS != status) { LOGE("CryptoSession::DeleteUsageInformation: Delete Usage Table error =%ld", status); response = UNKNOWN_ERROR; } - status = OEMCrypto_UpdateUsageTable(); + M_TIME( + status = OEMCrypto_UpdateUsageTable(), + metrics_, + oemcrypto_update_usage_table_, + status); if (status != OEMCrypto_SUCCESS) { LOGE("CryptoSession::DeleteUsageInformation: update table error=%ld", status); @@ -1052,16 +1277,26 @@ CdmResponseType CryptoSession::DeleteMultipleUsageInformation( LOGV("CryptoSession::DeleteMultipleUsageInformation"); CdmResponseType response = NO_ERROR; for (size_t i=0; i < provider_session_tokens.size(); ++i) { - OEMCryptoResult status = OEMCrypto_ForceDeleteUsageEntry( - reinterpret_cast(provider_session_tokens[i].c_str()), - provider_session_tokens[i].length()); + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_ForceDeleteUsageEntry( + reinterpret_cast(provider_session_tokens[i].c_str()), + provider_session_tokens[i].length()), + metrics_, + oemcrypto_force_delete_usage_entry_, + status); if (OEMCrypto_SUCCESS != status) { LOGW("CryptoSession::DeleteMultipleUsageInformation: " "Delete Usage Table error =%ld", status); response = UNKNOWN_ERROR; } } - OEMCryptoResult status = OEMCrypto_UpdateUsageTable(); + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_UpdateUsageTable(), + metrics_, + oemcrypto_update_usage_table_, + status); if (status != OEMCrypto_SUCCESS) { LOGE("CryptoSession::DeleteMultipleUsageInformation: update table error=%ld", status); @@ -1072,14 +1307,22 @@ CdmResponseType CryptoSession::DeleteMultipleUsageInformation( CdmResponseType CryptoSession::DeleteAllUsageReports() { LOGV("DeleteAllUsageReports"); - OEMCryptoResult status = OEMCrypto_DeleteOldUsageTable(); - + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_DeleteOldUsageTable(), + metrics_, + oemcrypto_delete_usage_table_, + status); if (OEMCrypto_SUCCESS != status) { LOGE("CryptoSession::DeleteAllUsageReports: Delete Usage Table error =%ld", status); } - status = OEMCrypto_UpdateUsageTable(); + M_TIME( + status = OEMCrypto_UpdateUsageTable(), + metrics_, + oemcrypto_update_usage_table_, + status); if (status != OEMCrypto_SUCCESS) { LOGE("CryptoSession::DeletaAllUsageReports: update table error=%ld", status); @@ -1089,7 +1332,14 @@ CdmResponseType CryptoSession::DeleteAllUsageReports() { } bool CryptoSession::IsAntiRollbackHwPresent() { - return OEMCrypto_IsAntiRollbackHwPresent(requested_security_level_); + bool is_present; + M_TIME( + is_present = OEMCrypto_IsAntiRollbackHwPresent(requested_security_level_), + metrics_, + oemcrypto_is_anti_rollback_hw_present_, + is_present, + requested_security_level_); + return is_present; } bool CryptoSession::GenerateNonce(uint32_t* nonce) { @@ -1101,7 +1351,15 @@ bool CryptoSession::GenerateNonce(uint32_t* nonce) { LOGV("CryptoSession::GenerateNonce: Lock"); AutoLock auto_lock(crypto_lock_); - return (OEMCrypto_SUCCESS == OEMCrypto_GenerateNonce(oec_session_id_, nonce)); + OEMCryptoResult result; + M_TIME( + result = OEMCrypto_GenerateNonce( + oec_session_id_, + nonce), + metrics_, + oemcrypto_generate_nonce_, + result); + return OEMCrypto_SUCCESS == result; } bool CryptoSession::SetDestinationBufferType() { @@ -1146,23 +1404,45 @@ bool CryptoSession::RewrapDeviceRSAKey(const std::string& message, // Gets wrapped_rsa_key_length by passing NULL as uint8_t* wrapped_rsa_key // and 0 as wrapped_rsa_key_length. size_t wrapped_rsa_key_length = 0; - OEMCryptoResult status = OEMCrypto_RewrapDeviceRSAKey( - oec_session_id_, signed_msg, message.size(), - reinterpret_cast(signature.data()), signature.size(), - msg_nonce, msg_rsa_key, enc_rsa_key.size(), msg_rsa_key_iv, NULL, - &wrapped_rsa_key_length); + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_RewrapDeviceRSAKey( + oec_session_id_, + signed_msg, + message.size(), + reinterpret_cast(signature.data()), + signature.size(), + msg_nonce, + msg_rsa_key, + enc_rsa_key.size(), + msg_rsa_key_iv, + NULL, + &wrapped_rsa_key_length), + metrics_, + oemcrypto_rewrap_device_rsa_key_, + status); if (status != OEMCrypto_ERROR_SHORT_BUFFER) { LOGE("OEMCrypto_RewrapDeviceRSAKey fails to get wrapped_rsa_key_length"); return false; } wrapped_rsa_key->resize(wrapped_rsa_key_length); - status = OEMCrypto_RewrapDeviceRSAKey( - oec_session_id_, signed_msg, message.size(), - reinterpret_cast(signature.data()), signature.size(), - msg_nonce, msg_rsa_key, enc_rsa_key.size(), msg_rsa_key_iv, - reinterpret_cast(&(*wrapped_rsa_key)[0]), - &wrapped_rsa_key_length); + M_TIME( + status = OEMCrypto_RewrapDeviceRSAKey( + oec_session_id_, + signed_msg, + message.size(), + reinterpret_cast(signature.data()), + signature.size(), + msg_nonce, + msg_rsa_key, + enc_rsa_key.size(), + msg_rsa_key_iv, + reinterpret_cast(&(*wrapped_rsa_key)[0]), + &wrapped_rsa_key_length), + metrics_, + oemcrypto_rewrap_device_rsa_key_, + status); wrapped_rsa_key->resize(wrapped_rsa_key_length); @@ -1182,8 +1462,16 @@ bool CryptoSession::GetHdcpCapabilities(HdcpCapability* current, LOGE("CryptoSession::GetHdcpCapabilities: |current|, |max| cannot be NULL"); return false; } - OEMCryptoResult status = OEMCrypto_GetHDCPCapability( - requested_security_level_, current, max); + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_GetHDCPCapability( + requested_security_level_, + current, + max), + metrics_, + oemcrypto_get_hdcp_capability_, + status, + requested_security_level_); if (OEMCrypto_SUCCESS != status) { LOGW("OEMCrypto_GetHDCPCapability fails with %d", status); return false; @@ -1214,7 +1502,15 @@ bool CryptoSession::GetRandom(size_t data_length, uint8_t* random_data) { LOGE("CryptoSession::GetRandom: random data destination not provided"); return false; } - OEMCryptoResult sts = OEMCrypto_GetRandom(random_data, data_length); + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_GetRandom( + random_data, + data_length), + metrics_, + oemcrypto_get_random_, + sts, + metrics::Pow2Bucket(data_length)); if (sts != OEMCrypto_SUCCESS) { LOGE("OEMCrypto_GetRandom fails with %d", sts); @@ -1233,8 +1529,15 @@ bool CryptoSession::GetNumberOfOpenSessions(size_t* count) { } size_t sessions_count; - OEMCryptoResult status = OEMCrypto_GetNumberOfOpenSessions( - requested_security_level_, &sessions_count); + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_GetNumberOfOpenSessions( + requested_security_level_, + &sessions_count), + metrics_, + oemcrypto_get_number_of_open_sessions_, + status, + requested_security_level_); if (OEMCrypto_SUCCESS != status) { LOGW("OEMCrypto_GetNumberOfOpenSessions fails with %d", status); return false; @@ -1252,8 +1555,16 @@ bool CryptoSession::GetMaxNumberOfSessions(size_t* max) { } size_t max_sessions; - OEMCryptoResult status = OEMCrypto_GetMaxNumberOfSessions( - requested_security_level_, &max_sessions); + OEMCryptoResult status; + M_TIME( + status = OEMCrypto_GetMaxNumberOfSessions( + requested_security_level_, + &max_sessions), + metrics_, + oemcrypto_get_max_number_of_sessions_, + status, + requested_security_level_); + if (OEMCrypto_SUCCESS != status) { LOGW("OEMCrypto_GetMaxNumberOfSessions fails with %d", status); return false; @@ -1323,11 +1634,20 @@ CdmResponseType CryptoSession::GenericEncrypt(const std::string& in_buffer, CdmResponseType result = SelectKey(key_id); if (result != NO_ERROR) return result; - OEMCryptoResult sts = OEMCrypto_Generic_Encrypt( - oec_session_id_, reinterpret_cast(in_buffer.data()), - in_buffer.size(), reinterpret_cast(iv.data()), - oec_algorithm, - reinterpret_cast(const_cast(out_buffer->data()))); + OEMCryptoResult sts; + + M_TIME( + sts = OEMCrypto_Generic_Encrypt( + oec_session_id_, + reinterpret_cast(in_buffer.data()), + in_buffer.size(), + reinterpret_cast(iv.data()), + oec_algorithm, + reinterpret_cast(const_cast(out_buffer->data()))), + metrics_, + oemcrypto_generic_encrypt_, + sts, + metrics::Pow2Bucket(in_buffer.size())); if (OEMCrypto_SUCCESS != sts) { LOGE("GenericEncrypt: OEMCrypto_Generic_Encrypt err=%d", sts); @@ -1363,11 +1683,20 @@ CdmResponseType CryptoSession::GenericDecrypt(const std::string& in_buffer, CdmResponseType result = SelectKey(key_id); if (result != NO_ERROR) return result; - OEMCryptoResult sts = OEMCrypto_Generic_Decrypt( - oec_session_id_, reinterpret_cast(in_buffer.data()), - in_buffer.size(), reinterpret_cast(iv.data()), - oec_algorithm, - reinterpret_cast(const_cast(out_buffer->data()))); + OEMCryptoResult sts; + + M_TIME( + sts = OEMCrypto_Generic_Decrypt( + oec_session_id_, + reinterpret_cast(in_buffer.data()), + in_buffer.size(), + reinterpret_cast(iv.data()), + oec_algorithm, + reinterpret_cast(const_cast(out_buffer->data()))), + metrics_, + oemcrypto_generic_decrypt_, + sts, + metrics::Pow2Bucket(in_buffer.size())); if (OEMCrypto_SUCCESS != sts) { LOGE("GenericDecrypt: OEMCrypto_Generic_Decrypt err=%d", sts); @@ -1406,11 +1735,18 @@ CdmResponseType CryptoSession::GenericSign(const std::string& message, // At most two attempts. // The first attempt may fail due to buffer too short for (int i = 0; i < 2; ++i) { - sts = OEMCrypto_Generic_Sign( - oec_session_id_, reinterpret_cast(message.data()), - message.size(), oec_algorithm, - reinterpret_cast(const_cast(signature->data())), - &length); + M_TIME( + sts = OEMCrypto_Generic_Sign( + oec_session_id_, + reinterpret_cast(message.data()), + message.size(), + oec_algorithm, + reinterpret_cast(const_cast(signature->data())), + &length), + metrics_, + oemcrypto_generic_sign_, + sts, + metrics::Pow2Bucket(message.size())); if (OEMCrypto_SUCCESS == sts) { // Trim signature buffer and done @@ -1449,10 +1785,19 @@ CdmResponseType CryptoSession::GenericVerify(const std::string& message, CdmResponseType result = SelectKey(key_id); if (result != NO_ERROR) return result; - OEMCryptoResult sts = OEMCrypto_Generic_Verify( - oec_session_id_, reinterpret_cast(message.data()), - message.size(), oec_algorithm, - reinterpret_cast(signature.data()), signature.size()); + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_Generic_Verify( + oec_session_id_, + reinterpret_cast(message.data()), + message.size(), + oec_algorithm, + reinterpret_cast(signature.data()), + signature.size()), + metrics_, + oemcrypto_generic_verify_, + sts, + metrics::Pow2Bucket(signature.size())); if (OEMCrypto_SUCCESS != sts) { LOGE("GenericVerify: OEMCrypto_Generic_Verify err=%d", sts); @@ -1772,9 +2117,20 @@ OEMCryptoResult CryptoSession::CopyBufferInChunks( subsample_flags |= OEMCrypto_LastSubsample; } - OEMCryptoResult sts = OEMCrypto_CopyBuffer( - requested_security_level_, params.encrypt_buffer + additional_offset, - chunk_size, &buffer_descriptor, subsample_flags); + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_CopyBuffer( + requested_security_level_, + params.encrypt_buffer + additional_offset, + chunk_size, + &buffer_descriptor, + subsample_flags), + metrics_, + oemcrypto_copy_buffer_, + sts, + requested_security_level_, + metrics::Pow2Bucket(chunk_size)); + if (sts != OEMCrypto_SUCCESS) { return sts; } @@ -1841,10 +2197,23 @@ OEMCryptoResult CryptoSession::DecryptInChunks( // max_chunk_size is guaranteed to be an even multiple of the // pattern length long, which is also guaranteed to be an exact number // of AES blocks long. - OEMCryptoResult sts = OEMCrypto_DecryptCENC( - oec_session_id_, params.encrypt_buffer + additional_offset, - chunk_size, params.is_encrypted, &iv.front(), params.block_offset, - &buffer_descriptor, &pattern_descriptor, subsample_flags); + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_DecryptCENC( + oec_session_id_, + params.encrypt_buffer + additional_offset, + chunk_size, + params.is_encrypted, + &iv.front(), + params.block_offset, + &buffer_descriptor, + &pattern_descriptor, + subsample_flags), + metrics_, + oemcrypto_decrypt_cenc_, + sts, + metrics::Pow2Bucket(chunk_size)); + if (sts != OEMCrypto_SUCCESS) { return sts; } diff --git a/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp b/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp index a356a070..b4083a14 100644 --- a/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp @@ -98,6 +98,7 @@ class MockDeviceFiles : public DeviceFiles { class MockCryptoSession : public CryptoSession { public: + MockCryptoSession() : CryptoSession(NULL) { } MOCK_METHOD1(GetClientToken, bool(std::string*)); MOCK_METHOD1(GetProvisioningToken, bool(std::string*)); MOCK_METHOD0(GetPreProvisionTokenType, CdmClientTokenType()); diff --git a/libwvdrmengine/cdm/core/test/license_unittest.cpp b/libwvdrmengine/cdm/core/test/license_unittest.cpp index c3790c25..90604a81 100644 --- a/libwvdrmengine/cdm/core/test/license_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/license_unittest.cpp @@ -79,6 +79,7 @@ const std::string kLicenseRequestSignature = a2bs_hex( class MockCryptoSession : public CryptoSession { public: + MockCryptoSession() : CryptoSession(NULL) { } MOCK_METHOD0(IsOpen, bool()); MOCK_METHOD1(GenerateRequestId, bool(std::string*)); MOCK_METHOD1(UsageInformationSupport, bool(bool*)); diff --git a/libwvdrmengine/cdm/core/test/policy_engine_constraints_unittest.cpp b/libwvdrmengine/cdm/core/test/policy_engine_constraints_unittest.cpp index cd0d0e72..79657c50 100644 --- a/libwvdrmengine/cdm/core/test/policy_engine_constraints_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/policy_engine_constraints_unittest.cpp @@ -60,6 +60,8 @@ const int64_t kHdcpInterval = 10; class HdcpOnlyMockCryptoSession : public CryptoSession { public: + HdcpOnlyMockCryptoSession() : CryptoSession(NULL) { } + MOCK_METHOD2(GetHdcpCapabilities, bool(HdcpCapability*, HdcpCapability*)); }; diff --git a/libwvdrmengine/cdm/core/test/service_certificate_unittest.cpp b/libwvdrmengine/cdm/core/test/service_certificate_unittest.cpp index 94549057..75f91e20 100644 --- a/libwvdrmengine/cdm/core/test/service_certificate_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/service_certificate_unittest.cpp @@ -44,6 +44,7 @@ const std::string kTestSignedCertificate = a2bs_hex( class MockCryptoSession : public CryptoSession { public: + MockCryptoSession() : CryptoSession(NULL) { } MOCK_METHOD2(GetRandom, bool(size_t, uint8_t*)); }; diff --git a/libwvdrmengine/cdm/include/ami_adapter.h b/libwvdrmengine/cdm/include/ami_adapter.h new file mode 100644 index 00000000..75999233 --- /dev/null +++ b/libwvdrmengine/cdm/include/ami_adapter.h @@ -0,0 +1,35 @@ +// Copyright 2017 Google Inc. All Rights Reserved. + +#ifndef CDM_AMI_ADAPTER_H_ +#define CDM_AMI_ADAPTER_H_ + +#include + +#include + +#include "report.h" + +namespace wvcdm { + +class AmiAdapter : public metrics::Report { + + 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); + void UpdateDouble(const std::string& metric_id, double value); + + private: + android::MediaAnalyticsItem analytics_item_; + +}; + +} // namespace wvcdm + +#endif diff --git a/libwvdrmengine/cdm/include/wv_content_decryption_module.h b/libwvdrmengine/cdm/include/wv_content_decryption_module.h index 4d53895b..8d0b5d27 100644 --- a/libwvdrmengine/cdm/include/wv_content_decryption_module.h +++ b/libwvdrmengine/cdm/include/wv_content_decryption_module.h @@ -11,6 +11,7 @@ #include "cdm_identifier.h" #include "file_store.h" #include "lock.h" +#include "metrics_front_end.h" #include "timer.h" #include "wv_cdm_types.h" @@ -155,6 +156,9 @@ 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/distribution.h b/libwvdrmengine/cdm/metrics/include/distribution.h new file mode 100644 index 00000000..c9a13d7e --- /dev/null +++ b/libwvdrmengine/cdm/metrics/include/distribution.h @@ -0,0 +1,53 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// This file contains the definition of a Distribution class which computes +// the distribution values of a series of samples. + +#ifndef WVCDM_METRICS_DISTRIBUTION_H_ +#define WVCDM_METRICS_DISTRIBUTION_H_ + +#include + +namespace wvcdm { +namespace metrics { + +// The Distribution class holds statistics about a series of values that the +// client provides via the Record method. A caller will call Record once for +// each of the values in a series. The Distribution instance will calculate the +// mean, count, min, max and variance of the distribution. +// +// Example usage: +// Distribution dist; +// dist.Record(1); +// dist.Record(2); +// dist.Mean(); // Returns 1.5. +// dist.Count(); // Returns 2. +class Distribution { + public: + Distribution(); + + // Uses the provided sample value to update the computed statistics. + void Record(double value); + + // Return the value for each of the stats computed about the series of + // values (min, max, count, etc.). + const double Min() { return min_; } + const double Max() { return max_; } + const double Mean() { return mean_; } + const int64_t Count() { return count_; } + const double Variance() { + return count_ == 0 ? 0.0 : sum_squared_deviation_ / count_; + } + + private: + int64_t count_; + double min_; + double max_; + double mean_; + double sum_squared_deviation_; +}; + +} // namespace metrics +} // namespace wvcdm + +#endif // WVCDM_METRICS_DISTRIBUTION_H_ diff --git a/libwvdrmengine/cdm/metrics/include/event_metric.h b/libwvdrmengine/cdm/metrics/include/event_metric.h new file mode 100644 index 00000000..d0f5341b --- /dev/null +++ b/libwvdrmengine/cdm/metrics/include/event_metric.h @@ -0,0 +1,298 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// This file contains the declarations for the EventMetric class and related +// types. +#ifndef WVCDM_METRICS_EVENT_METRIC_H_ +#define WVCDM_METRICS_EVENT_METRIC_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lock.h" + +#include "distribution.h" +#include "metric_publisher.h" + +namespace wvcdm { +namespace metrics { + +class EventMetricTest; + +// This base class provides the common defintion used by all templated +// instances of EventMetric. +class BaseEventMetric : public MetricPublisher { + public: + // Publish metric values to the MetricNotification. |subscriber| must + // not be null and is owned by the caller. + virtual void Publish(MetricNotification* subscriber); + + protected: + // Instantiates a BaseEventMetric. + BaseEventMetric(const std::string& metric_name) + : metric_name_(metric_name) {} + + virtual ~BaseEventMetric(); + + // Record will look for an existing instance of the Distribution identified + // by the field_names_values string and update it. If the instance does + // not exist, this will create it. + void Record(const std::string& field_names_values, double value); + + private: + friend class EventMetricTest; + const std::string metric_name_; + // value_map_ contains a mapping from the field name/value pairs to the + // distribution instance which holds the metric information (min, max, sum, + // etc.). + std::map value_map_; + + /* + * This locks the internal state of the event metric to ensure safety across + * multiple threads preventing the caller from worrying about locking. + */ + Lock internal_lock_; +}; + +// This is a placeholder type for unused type parameters. +struct Unused { + // Required for compilation. Should never be used. + inline friend std::ostream& operator<< (std::ostream& out, const Unused&) + { return out; } +}; + + +// This class converts the size_t value into the highest power of two +// below the value. E.g. for 7, the value is 4. For 11, the value is 8. +// This class is intended to simplify the use of EventMetric Fields that may +// have many possible values, but we want to bucket them into a small set of +// numbers (32 or 64). +class Pow2Bucket { + public: + explicit Pow2Bucket(size_t value) : value_(GetLowerBucket(value)) {} + + Pow2Bucket(const Pow2Bucket& value) : value_(value.value_) {} + + // Support for converting to string. + friend std::ostream& operator<<(std::ostream& os, const Pow2Bucket& log) + { return os << log.value_; } + + private: + inline size_t GetLowerBucket(size_t value) { + if (!value) { + return 0; + } + + size_t log = 0; + while (value) { + log++; + value >>= 1; + } + + return 1 << (log - 1); + } + + size_t value_; +}; + +// The EventMetric class is used to capture statistics about an event such as +// a method call. EventMetric keeps track of the count, mean, min, max and +// variance for the value being measured. For example, we may want to track the +// latency of a particular operation. Each time the operation is run, the time +// is calculated and provided to the EventMetric by using the +// EventMetric::Record method to capture and maintain statistics about the +// latency (max, min, count, mean, variance). +// +// The EventMetric class supports the ability to breakdown the statistics based +// on certain "field" values. For example, if a particular operation can run in +// one of two modes, it's useful to track the latency of the operation in each +// mode separately. You can use Fields to define how to breakdown the +// statistics. Each Field is a separate dimention. The statistics for each +// combination of field values are tracked independently. +// +// Example usage: +// +// EventMetric my_metric("multiple/fields/metric", +// "request_type", "error_code", // Field names); +// +// my_metric.Record(1, 7, 23); // (latency value, request type, error code). +// +// A MetricNotification may be used to allow the EventMetric instance to +// notify that an update occurred and provide the updated value. +// +// class MyMetricNotification : public MetricNotification { +// // Add implementation here. +// } +// +// MyMetricNotification notification; +// my_metric.Publish(notification); +template +class EventMetric : public BaseEventMetric { + public: + // Create an EventMetric instance with the name |metric_name|. + EventMetric(const std::string& metric_name); + + // Overloaded constructors with variable field name arguments. The number + // of |field_name| arguments must match the number of used Field type + // arguments. + EventMetric(const std::string& metric_name, + const char* field_name); + EventMetric(const std::string& metric_name, + const char* field_name1, + const char* field_name2); + EventMetric(const std::string& metric_name, + const char* field_name1, + const char* field_name2, + const char* field_name3); + EventMetric(const std::string& metric_name, + const char* field_name1, + const char* field_name2, + const char* field_name3, + const char* field_name4); + + // Record will update the statistics of the EventMetric broken down by the + // given field values. + void Record(double value, + F1 field1 = Unused(), + F2 field2 = Unused(), + F3 field3 = Unused(), + F4 field4 = Unused()); + + private: + friend class EventMetricTest; + std::vector field_names_; +}; + +// This is an internal namespace for helper functions only. +namespace impl { + +// This method formats the collection of field name/value pairs. +// The format of the string is: +// +// [{field:value[&field:value]*}] +// +// If there are no pairs, returns a blank string. +// +// TODO(blueeyes): Add a check for the count of field_names and the count +// of field values (check that the fields are not type Unused). +template +std::string MakeFieldNameString(const std::vector& field_names, + const F1 field1, const F2 field2, + const F3 field3, const F4 field4) { + std::stringstream field_name_and_values; + std::vector::const_iterator field_name_iterator = + field_names.begin(); + if (field_name_iterator == field_names.end()) { + return field_name_and_values.str(); + } + // There is at least one name/value pair. prepend open brace. + field_name_and_values << "{"; + field_name_and_values << *field_name_iterator << ':' << field1; + if (++field_name_iterator == field_names.end()) { + field_name_and_values << "}"; + return field_name_and_values.str(); + } + field_name_and_values << '&' << *field_name_iterator << ':' << field2; + if (++field_name_iterator == field_names.end()) { + field_name_and_values << "}"; + return field_name_and_values.str(); + } + field_name_and_values << '&' << *field_name_iterator << ':' << field3; + if (++field_name_iterator == field_names.end()) { + field_name_and_values << "}"; + return field_name_and_values.str(); + } + field_name_and_values << '&' << *field_name_iterator << ':' << field4; + field_name_and_values << "}"; + return field_name_and_values.str(); +} + +// This specialization of the helper method is a shortcut for EventMetric +// instances with no fields. +template<> +inline std::string MakeFieldNameString( + const std::vector& field_names, + const Unused unused1, const Unused unused2, + const Unused unused3, const Unused unused4) { + return ""; +} + +// This helper function appends the field names to a vector of strings. +inline void AppendFieldNames(std::vector* field_name_vector, + int field_count, ...) { + va_list field_names; + + va_start(field_names, field_count); + for (int x = 0; x < field_count; x++) { + field_name_vector->push_back(va_arg(field_names, const char*)); + } + va_end(field_names); +} + +} // namespace impl + +// Overloaded template constructor implementations for EventMetric. +template +EventMetric::EventMetric( + const std::string& metric_name) + : BaseEventMetric(metric_name) {} + +template +EventMetric::EventMetric( + const std::string& metric_name, + const char* field_name) + : BaseEventMetric(metric_name) { + impl::AppendFieldNames(&field_names_, 1, field_name); +} +template +EventMetric::EventMetric( + const std::string& metric_name, + const char* field_name1, + const char* field_name2) + : BaseEventMetric(metric_name) { + impl::AppendFieldNames(&field_names_, 2, field_name1, field_name2); +} +template +EventMetric::EventMetric( + const std::string& metric_name, + const char* field_name1, + const char* field_name2, + const char* field_name3) + : BaseEventMetric(metric_name) { + impl::AppendFieldNames(&field_names_, + 3, field_name1, field_name2, field_name3); +} +template +EventMetric::EventMetric( + const std::string& metric_name, + const char* field_name1, + const char* field_name2, + const char* field_name3, + const char* field_name4) + : BaseEventMetric(metric_name) { + impl::AppendFieldNames(&field_names_, + 4, field_name1, field_name2, + field_name3, field_name4); +} + +template +void EventMetric::Record( + double value, F1 field1, F2 field2, F3 field3, F4 field4) { + std::string field_name_values = + impl::MakeFieldNameString(field_names_, field1, field2, field3, field4); + BaseEventMetric::Record(field_name_values, value); +} + +} // namespace metrics +} // namespace wvcdm + +#endif // WVCDM_METRICS_EVENT_METRIC_H_ diff --git a/libwvdrmengine/cdm/metrics/include/metric_publisher.h b/libwvdrmengine/cdm/metrics/include/metric_publisher.h new file mode 100644 index 00000000..11a1a3ed --- /dev/null +++ b/libwvdrmengine/cdm/metrics/include/metric_publisher.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_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/metrics_front_end.h b/libwvdrmengine/cdm/metrics/include/metrics_front_end.h new file mode 100644 index 00000000..20e8737a --- /dev/null +++ b/libwvdrmengine/cdm/metrics/include/metrics_front_end.h @@ -0,0 +1,56 @@ +// 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 M_RECORD(GROUP, METRIC, ...) \ + if ( GROUP ) { \ + ( GROUP ) -> METRIC . Record( __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/metrics_group.h b/libwvdrmengine/cdm/metrics/include/metrics_group.h new file mode 100644 index 00000000..cb3e40b0 --- /dev/null +++ b/libwvdrmengine/cdm/metrics/include/metrics_group.h @@ -0,0 +1,150 @@ +// Copyright 2016 Google Inc. All Rights Reserved. + +#ifndef WVCDM_METRICS_METRICS_GROUP_H_ +#define WVCDM_METRICS_METRICS_GROUP_H_ + +#include +#include + +#include "OEMCryptoCENC.h" +#include "event_metric.h" +#include "metric_publisher.h" +#include "wv_cdm_types.h" + +namespace wvcdm { +namespace metrics { + +/* + * 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 { + public: + /* CDM ENGINE */ + EventMetric cdm_engine_add_key_; + EventMetric<> cdm_engine_close_key_set_session_; + 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_notify_resolution_; + EventMetric cdm_engine_open_key_set_session_; + EventMetric cdm_engine_open_session_; + EventMetric cdm_engine_query_key_status_; + EventMetric cdm_engine_query_oemcrypto_session_id_; + EventMetric cdm_engine_query_session_status_; + EventMetric cdm_engine_query_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_add_key_; + EventMetric cdm_session_decrypt_; + EventMetric<> cdm_session_delete_license_; + EventMetric cdm_session_generate_key_request_; + EventMetric cdm_session_generate_release_request_; + EventMetric cdm_session_generate_renewal_request_; + EventMetric cdm_session_generic_decrypt_; + EventMetric cdm_session_generic_encrypt_; + EventMetric cdm_session_generic_sign_; + EventMetric cdm_session_generic_verify_; + EventMetric cdm_session_get_requested_security_level_; + EventMetric cdm_session_is_key_loaded_; + EventMetric<> cdm_session_life_span_; + EventMetric cdm_session_query_key_allowed_usage_; + EventMetric cdm_session_query_key_status_; + EventMetric cdm_session_query_oemcrypto_session_id_; + EventMetric cdm_session_query_status_; + EventMetric<> cdm_session_release_crypto_; + EventMetric cdm_session_renew_key_; + EventMetric cdm_session_restore_offline_session_; + EventMetric cdm_session_restore_usage_session_; + EventMetric cdm_session_update_usage_information_; + /* CRYPTO SESSION */ + EventMetric<> crypto_session_close_; + EventMetric crypto_session_decrypt_; + EventMetric crypto_session_delete_all_usage_reports_; + EventMetric crypto_session_delete_multiple_usage_information_; + EventMetric crypto_session_generic_decrypt_; + EventMetric crypto_session_generic_encrypt_; + EventMetric crypto_session_generic_sign_; + EventMetric crypto_session_generic_verify_; + EventMetric crypto_session_get_api_version_; + EventMetric crypto_session_get_device_unique_id_; + EventMetric crypto_session_get_hdcp_capabilities_; + EventMetric crypto_session_get_max_number_of_sessions_; + EventMetric crypto_session_get_number_of_open_sessions_; + EventMetric crypto_session_get_provisioning_id_; + EventMetric crypto_session_get_random_; + EventMetric crypto_session_get_security_level_; + EventMetric crypto_session_get_system_id_; + EventMetric crypto_session_get_token_; + EventMetric<> crypto_session_life_span_; + EventMetric crypto_session_load_certificate_private_key_; + EventMetric crypto_session_open_; + EventMetric crypto_session_query_oemcrypto_session_id_; + EventMetric crypto_session_update_usage_information_; + EventMetric crypto_session_usage_information_support_; + /* OEMCRYPTO */ + EventMetric oemcrypto_api_version_; + EventMetric oemcrypto_close_session_; + EventMetric oemcrypto_copy_buffer_; + EventMetric oemcrypto_deactivate_usage_entry_; + EventMetric oemcrypto_decrypt_cenc_; + EventMetric oemcrypto_delete_usage_entry_; + EventMetric oemcrypto_delete_usage_table_; + EventMetric oemcrypto_derive_keys_from_session_key_; + EventMetric oemcrypto_force_delete_usage_entry_; + EventMetric oemcrypto_generate_derived_keys_; + EventMetric oemcrypto_generate_nonce_; + EventMetric oemcrypto_generate_rsa_signature_; + EventMetric oemcrypto_generate_signature_; + EventMetric oemcrypto_generic_decrypt_; + EventMetric oemcrypto_generic_encrypt_; + EventMetric oemcrypto_generic_sign_; + EventMetric oemcrypto_generic_verify_; + EventMetric oemcrypto_get_device_id_; + EventMetric oemcrypto_get_hdcp_capability_; + EventMetric oemcrypto_get_key_data_; + EventMetric oemcrypto_get_max_number_of_sessions_; + EventMetric oemcrypto_get_number_of_open_sessions_; + EventMetric oemcrypto_get_oem_public_certificate_; + EventMetric oemcrypto_get_provisioning_method_; + EventMetric oemcrypto_get_random_; + EventMetric oemcrypto_initialize_; + EventMetric oemcrypto_install_keybox_; + EventMetric oemcrypto_is_anti_rollback_hw_present_; + EventMetric oemcrypto_is_keybox_valid_; + EventMetric oemcrypto_load_device_rsa_key_; + EventMetric oemcrypto_load_keys_; + EventMetric oemcrypto_load_test_keybox_; + EventMetric oemcrypto_load_test_rsa_key_; + EventMetric oemcrypto_open_session_; + EventMetric oemcrypto_query_key_control_; + EventMetric oemcrypto_refresh_keys_; + EventMetric oemcrypto_report_usage_; + EventMetric oemcrypto_rewrap_device_rsa_key_; + EventMetric oemcrypto_rewrap_device_rsa_key_30_; + EventMetric oemcrypto_security_level_; + EventMetric oemcrypto_security_patch_level_; + EventMetric oemcrypto_select_key_; + EventMetric oemcrypto_supports_usage_table_; + EventMetric oemcrypto_update_usage_table_; + EventMetric oemcrypto_wrap_keybox_; + + MetricsGroup(); + ~MetricsGroup(); + + private: + void Publish(MetricNotification* subscriber); + +}; +} // namespace metrics +} // namespace wvcdm +#endif diff --git a/libwvdrmengine/cdm/metrics/include/report.h b/libwvdrmengine/cdm/metrics/include/report.h new file mode 100644 index 00000000..49216e69 --- /dev/null +++ b/libwvdrmengine/cdm/metrics/include/report.h @@ -0,0 +1,29 @@ +// 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/include/timer_metric.h b/libwvdrmengine/cdm/metrics/include/timer_metric.h new file mode 100644 index 00000000..ce00c2fd --- /dev/null +++ b/libwvdrmengine/cdm/metrics/include/timer_metric.h @@ -0,0 +1,24 @@ +#ifndef WVCDM_METRICS_TIMER_METRIC_H_ +#define WVCDM_METRICS_TIMER_METRIC_H_ + +#include + +namespace wvcdm { +namespace metrics { + +class TimerMetric { + + public: + void Start(); + double AsMs() const; + double AsUs() const; + + private: + double sec_; + double usec_; + +}; + +} // namespace metrics +} // namespace wvcdm +#endif diff --git a/libwvdrmengine/cdm/metrics/src/distribution.cpp b/libwvdrmengine/cdm/metrics/src/distribution.cpp new file mode 100644 index 00000000..378e75ff --- /dev/null +++ b/libwvdrmengine/cdm/metrics/src/distribution.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// This file contains the definitions for the Distribution class members. + +#include "distribution.h" + +#include + +namespace wvcdm { +namespace metrics { + +Distribution::Distribution() : + count_(0LL), + min_(DBL_MAX), + max_(-DBL_MAX), + mean_(0.0), + sum_squared_deviation_(0.0) { +} + +void Distribution::Record(double value) { + // Using method of provisional means. + double deviation = value - mean_; + mean_ = mean_ + (deviation / ++count_); + sum_squared_deviation_ = + sum_squared_deviation_ + (deviation * (value - mean_)); + + min_ = min_ < value ? min_ : value; + max_ = max_ > value ? max_ : value; +} + +} // namespace metrics +} // namespace wvcdm + diff --git a/libwvdrmengine/cdm/metrics/src/event_metric.cpp b/libwvdrmengine/cdm/metrics/src/event_metric.cpp new file mode 100644 index 00000000..1f9bba5d --- /dev/null +++ b/libwvdrmengine/cdm/metrics/src/event_metric.cpp @@ -0,0 +1,60 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// This file contains implementations for the BaseEventMetric. + +#include "event_metric.h" + +namespace wvcdm { +namespace metrics { + +BaseEventMetric::~BaseEventMetric() { + AutoLock lock(internal_lock_); + + for (std::map::iterator it + = value_map_.begin(); it != value_map_.end(); it++) { + delete it->second; + } +} + +void BaseEventMetric::Record(const std::string& field_names_values, + double value) { + AutoLock lock(internal_lock_); + + Distribution* distribution; + + if (value_map_.find(field_names_values) == value_map_.end()) { + distribution = new Distribution(); + value_map_[field_names_values] = distribution; + } else { + distribution = value_map_[field_names_values]; + } + + distribution->Record(value); +} + +void BaseEventMetric::Publish(MetricNotification* notification) { + AutoLock lock(internal_lock_); + + for (std::map::iterator it + = value_map_.begin(); it != value_map_.end(); it++) { + notification->UpdateInt64( + metric_name_ + "/count" + it->first, + it->second->Count()); + notification->UpdateDouble( + 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()); + } +} + +} // namespace metrics +} // namespace wvcdm + diff --git a/libwvdrmengine/cdm/metrics/src/metrics_front_end.cpp b/libwvdrmengine/cdm/metrics/src/metrics_front_end.cpp new file mode 100644 index 00000000..13658cc4 --- /dev/null +++ b/libwvdrmengine/cdm/metrics/src/metrics_front_end.cpp @@ -0,0 +1,31 @@ +// 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/src/metrics_group.cpp b/libwvdrmengine/cdm/metrics/src/metrics_group.cpp new file mode 100644 index 00000000..969688db --- /dev/null +++ b/libwvdrmengine/cdm/metrics/src/metrics_group.cpp @@ -0,0 +1,511 @@ +// Copyright 2016 Google Inc. All Rights Reserved. + +#include "metrics_group.h" + +#include "metrics_front_end.h" + +namespace wvcdm { +namespace metrics { + +MetricsGroup::MetricsGroup() : + cdm_engine_add_key_( + "/drm/widevine/cdm_engine/add_key/time", + "error"), + cdm_engine_close_key_set_session_( + "/drm/widevine/cdm_engine/close_key_set_session"), + 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_notify_resolution_( + "/drm/widevine/cdm_engine/notify_resolution/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_query_oemcrypto_session_id_( + "/drm/widevine/cdm_engine/query_oemcrypto_session_id/time", + "error"), + cdm_engine_query_session_status_( + "/drm/widevine/cdm_engine/query_session_status/time", + "error"), + cdm_engine_query_status_( + "/drm/widevine/cdm_engine/query_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_add_key_( + "/drm/widevine/cdm_session/add_key/time", + "error"), + cdm_session_decrypt_( + "/drm/widevine/cdm_session/decrypt/time", + "error"), + cdm_session_delete_license_( + "/drm/widevine/cdm_session/delete_license/time"), + cdm_session_generate_key_request_( + "/drm/widevine/cdm_session/generate_key_request/time", + "error"), + cdm_session_generate_release_request_( + "/drm/widevine/cdm_session/generate_release_request/time", + "error"), + cdm_session_generate_renewal_request_( + "/drm/widevine/cdm_session/generate_renewal_request/time", + "error"), + cdm_session_generic_decrypt_( + "/drm/widevine/cdm_session/generic_decrypt/time", + "error", + "length", + "algorithm"), + cdm_session_generic_encrypt_( + "/drm/widevine/cdm_session/generic_encrypt/time", + "error", + "length", + "algorithm"), + cdm_session_generic_sign_( + "/drm/widevine/cdm_session/generic_sign/time", + "error", + "length", + "algorithm"), + cdm_session_generic_verify_( + "/drm/widevine/cdm_session/generic_verify/time", + "error", + "length", + "algorithm"), + cdm_session_get_requested_security_level_( + "/drm/widevine/cdm_session/get_requested_security_level/time", + "security_level"), + cdm_session_is_key_loaded_( + "/drm/widevine/cdm_session/is_key_loaded/time", + "success"), + cdm_session_life_span_( + "/drm/widevine/cdm_session/life_span/time"), + cdm_session_query_key_allowed_usage_( + "/drm/widevine/cdm_session/query_key_allowed_usage/time", + "error"), + cdm_session_query_key_status_( + "/drm/widevine/cdm_session/query_key_status/time", + "error"), + cdm_session_query_oemcrypto_session_id_( + "/drm/widevine/cdm_session/query_oemcrypto_session_id/time", + "error"), + cdm_session_query_status_( + "/drm/widevine/cdm_session/query_status/time", + "error"), + cdm_session_release_crypto_( + "/drm/widevine/cdm_session/release_crypto/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"), + cdm_session_update_usage_information_( + "/drm/widevine/cdm_session/update_usage_information/time", + "error"), + crypto_session_close_( + "/drm/widevine/crypto_session/close/time"), + crypto_session_decrypt_( + "/drm/widevine/crypto_session/decrypt/time", + "error"), + crypto_session_delete_all_usage_reports_( + "/drm/widevine/crypto_session/delete_all_usage_reports/time", + "error"), + crypto_session_delete_multiple_usage_information_( + "/drm/widevine/crypto_session/delete_multiple_usage_information/time", + "error"), + crypto_session_generic_decrypt_( + "/drm/widevine/crypto_session/generic_decrypt/time", + "error", + "length", + "algorithm"), + crypto_session_generic_encrypt_( + "/drm/widevine/crypto_session/generic_encrypt/time", + "error", + "length", + "algorithm"), + crypto_session_generic_sign_( + "/drm/widevine/crypto_session/generic_sign/time", + "error", + "length", + "algorithm"), + crypto_session_generic_verify_( + "/drm/widevine/crypto_session/generic_verify/time", + "error", + "length", + "algorithm"), + crypto_session_get_api_version_( + "/drm/widevine/crypto_session/get_api_version/time", + "success"), + crypto_session_get_device_unique_id_( + "/drm/widevine/crypto_session/get_device_unique_id/time", + "success"), + crypto_session_get_hdcp_capabilities_( + "/drm/widevine/crypto_session/get_hdcp_capabilities/time", + "success"), + crypto_session_get_max_number_of_sessions_( + "/drm/widevine/crypto_session/get_max_number_of_sessions/time", + "success"), + crypto_session_get_number_of_open_sessions_( + "/drm/widevine/crypto_session/get_number_of_open_sessions/time", + "success"), + crypto_session_get_provisioning_id_( + "/drm/widevine/crypto_session/get_provisioning_id/time", + "success"), + crypto_session_get_random_( + "/drm/widevine/crypto_session/get_random/time", + "success", + "length"), + crypto_session_get_security_level_( + "/drm/widevine/crypto_session/get_security_level/time", + "security_level"), + crypto_session_get_system_id_( + "/drm/widevine/crypto_session/get_system_id/time", + "success", + "id"), + crypto_session_get_token_( + "/drm/widevine/crypto_session/get_token/time", + "success"), + crypto_session_life_span_( + "/drm/widevine/crypto_session/life_span/time"), + crypto_session_load_certificate_private_key_( + "/drm/widevine/crypto_session/load_certificate_private_key/time", + "success"), + crypto_session_open_( + "/drm/widevine/crypto_session/open/time", + "error", + "security_level"), + crypto_session_query_oemcrypto_session_id_( + "/drm/widevine/crypto_session/query_oemcrypto_session_id/time", + "error"), + crypto_session_update_usage_information_( + "/drm/widevine/crypto_session/update_usage_information/time", + "error"), + crypto_session_usage_information_support_( + "/drm/widevine/crypto_session/usage_information_support/time", + "success"), + oemcrypto_api_version_( + "/drm/widevine/oemcrypto/api_version/time", + "version", + "security_level"), + oemcrypto_close_session_( + "/drm/widevine/oemcrypto/close_session/time", + "error"), + oemcrypto_copy_buffer_( + "/drm/widevine/oemcrypto/copy_buffer/time", + "error", + "security_level", + "length"), + oemcrypto_deactivate_usage_entry_( + "/drm/widevine/oemcrypto/deactivate_usage_entry/time", + "error"), + oemcrypto_decrypt_cenc_( + "/drm/widevine/oemcrypto/decrypt_cenc/time", + "error", + "length"), + oemcrypto_delete_usage_entry_( + "/drm/widevine/oemcrypto/delete_usage_entry/time", + "error"), + oemcrypto_delete_usage_table_( + "/drm/widevine/oemcrypto/delete_usage_table/time", + "error"), + oemcrypto_derive_keys_from_session_key_( + "/drm/widevine/oemcrypto/derive_keys_from_session_key/time", + "error"), + oemcrypto_force_delete_usage_entry_( + "/drm/widevine/oemcrypto/force_delete_usage_entry/time", + "error"), + oemcrypto_generate_derived_keys_( + "/drm/widevine/oemcrypto/generate_derived_keys/time", + "error"), + oemcrypto_generate_nonce_( + "/drm/widevine/oemcrypto/generate_nonce/time", + "error"), + oemcrypto_generate_rsa_signature_( + "/drm/widevine/oemcrypto/generate_rsa_signature/time", + "error", + "length"), + oemcrypto_generate_signature_( + "/drm/widevine/oemcrypto/generate_signature/time", + "error", + "length"), + oemcrypto_generic_decrypt_( + "/drm/widevine/oemcrypto/generic_decrypt/time", + "error", + "length"), + oemcrypto_generic_encrypt_( + "/drm/widevine/oemcrypto/generic_encrypt/time", + "error", + "length"), + oemcrypto_generic_sign_( + "/drm/widevine/oemcrypto/generic_sign/time", + "error", + "length"), + oemcrypto_generic_verify_( + "/drm/widevine/oemcrypto/generic_verify/time", + "error", + "length"), + oemcrypto_get_device_id_( + "/drm/widevine/oemcrypto/get_device_id/time", + "error", + "security_level"), + oemcrypto_get_hdcp_capability_( + "/drm/widevine/oemcrypto/get_hdcp_capability/time", + "error", + "security_level"), + oemcrypto_get_key_data_( + "/drm/widevine/oemcrypto/get_key_data/time", + "error", + "length", + "security_level"), + oemcrypto_get_max_number_of_sessions_( + "/drm/widevine/oemcrypto/get_max_number_of_sessions/time", + "error", + "security_level"), + oemcrypto_get_number_of_open_sessions_( + "/drm/widevine/oemcrypto/get_number_of_open_sessions/time", + "error", + "security_level"), + oemcrypto_get_oem_public_certificate_( + "/drm/widevine/oemcrypto/get_oem_public_certificate/time", + "error"), + oemcrypto_get_provisioning_method_( + "/drm/widevine/oemcrypto/get_provisioning_method/time", + "method", + "security_level"), + oemcrypto_get_random_( + "/drm/widevine/oemcrypto/get_random/time", + "error", + "length"), + oemcrypto_initialize_( + "/drm/widevine/oemcrypto/initialize/time", + "error"), + oemcrypto_install_keybox_( + "/drm/widevine/oemcrypto/install_keybox/time", + "error", + "security_level"), + oemcrypto_is_anti_rollback_hw_present_( + "/drm/widevine/oemcrypto/is_anti_rollback_hw_present/time", + "success", + "security_level"), + oemcrypto_is_keybox_valid_( + "/drm/widevine/oemcrypto/is_keybox_valid/time", + "error", + "security_level"), + oemcrypto_load_device_rsa_key_( + "/drm/widevine/oemcrypto/load_device_rsa_key/time", + "error"), + oemcrypto_load_keys_( + "/drm/widevine/oemcrypto/load_keys/time", + "error"), + oemcrypto_load_test_keybox_( + "/drm/widevine/oemcrypto/load_test_keybox/time", + "error"), + oemcrypto_load_test_rsa_key_( + "/drm/widevine/oemcrypto/load_test_rsa_key/time", + "error"), + oemcrypto_open_session_( + "/drm/widevine/oemcrypto/open_session/time", + "error", + "security_level"), + oemcrypto_query_key_control_( + "/drm/widevine/oemcrypto/query_key_control/time", + "error"), + oemcrypto_refresh_keys_( + "/drm/widevine/oemcrypto/refresh_keys/time", + "error"), + oemcrypto_report_usage_( + "/drm/widevine/oemcrypto/report_usage/time", + "error"), + oemcrypto_rewrap_device_rsa_key_( + "/drm/widevine/oemcrypto/rewrap_device_rsa_key/time", + "error"), + oemcrypto_rewrap_device_rsa_key_30_( + "/drm/widevine/oemcrypto/rewrap_device_rsa_key_30/time", + "error"), + oemcrypto_security_level_( + "/drm/widevine/oemcrypto/security_level/time", + "result", + "security_level"), + oemcrypto_security_patch_level_( + "/drm/widevine/oemcrypto/security_patch_level/time", + "patch", + "security_level"), + oemcrypto_select_key_( + "/drm/widevine/oemcrypto/select_key/time", + "error"), + oemcrypto_supports_usage_table_( + "/drm/widevine/oemcrypto/supports_usage_table/time", + "error", + "security_level"), + oemcrypto_update_usage_table_( + "/drm/widevine/oemcrypto/update_usage_table/time", + "error"), + oemcrypto_wrap_keybox_( + "/drm/widevine/oemcrypto/wrap_keybox/time", + "error") { } + +MetricsGroup::~MetricsGroup() { + MetricNotification* subscriber = MFE.CreateSubscriber(); + if (subscriber) { + Publish(subscriber); + } + delete subscriber; +} + +void MetricsGroup::Publish(MetricNotification* subscriber) { + cdm_engine_add_key_.Publish(subscriber); + cdm_engine_close_key_set_session_.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_notify_resolution_.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_query_oemcrypto_session_id_.Publish(subscriber); + cdm_engine_query_session_status_.Publish(subscriber); + cdm_engine_query_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_add_key_.Publish(subscriber); + cdm_session_decrypt_.Publish(subscriber); + cdm_session_delete_license_.Publish(subscriber); + cdm_session_generate_key_request_.Publish(subscriber); + cdm_session_generate_release_request_.Publish(subscriber); + cdm_session_generate_renewal_request_.Publish(subscriber); + cdm_session_generic_decrypt_.Publish(subscriber); + cdm_session_generic_encrypt_.Publish(subscriber); + cdm_session_generic_sign_.Publish(subscriber); + cdm_session_generic_verify_.Publish(subscriber); + cdm_session_get_requested_security_level_.Publish(subscriber); + cdm_session_is_key_loaded_.Publish(subscriber); + cdm_session_life_span_.Publish(subscriber); + cdm_session_query_key_allowed_usage_.Publish(subscriber); + cdm_session_query_key_status_.Publish(subscriber); + cdm_session_query_oemcrypto_session_id_.Publish(subscriber); + cdm_session_query_status_.Publish(subscriber); + cdm_session_release_crypto_.Publish(subscriber); + cdm_session_renew_key_.Publish(subscriber); + cdm_session_restore_offline_session_.Publish(subscriber); + cdm_session_restore_usage_session_.Publish(subscriber); + cdm_session_update_usage_information_.Publish(subscriber); + crypto_session_close_.Publish(subscriber); + crypto_session_decrypt_.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_encrypt_.Publish(subscriber); + crypto_session_generic_sign_.Publish(subscriber); + crypto_session_generic_verify_.Publish(subscriber); + crypto_session_get_api_version_.Publish(subscriber); + crypto_session_get_device_unique_id_.Publish(subscriber); + crypto_session_get_hdcp_capabilities_.Publish(subscriber); + crypto_session_get_max_number_of_sessions_.Publish(subscriber); + crypto_session_get_number_of_open_sessions_.Publish(subscriber); + crypto_session_get_provisioning_id_.Publish(subscriber); + crypto_session_get_random_.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_query_oemcrypto_session_id_.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_query_key_control_.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); +} +} // metrics +} // wvcdm diff --git a/libwvdrmengine/cdm/metrics/src/timer_metric.cpp b/libwvdrmengine/cdm/metrics/src/timer_metric.cpp new file mode 100644 index 00000000..f1990949 --- /dev/null +++ b/libwvdrmengine/cdm/metrics/src/timer_metric.cpp @@ -0,0 +1,33 @@ +#include "timer_metric.h" + +#include +#include + +namespace wvcdm { +namespace metrics { + +void TimerMetric::Start() { + struct timeval tv; + gettimeofday(&tv, NULL); + sec_ = tv.tv_sec; + usec_ = tv.tv_usec; +} + +double TimerMetric::AsMs() const { + struct timeval tv; + gettimeofday(&tv, NULL); + return usec_ > tv.tv_usec ? + (tv.tv_sec - sec_ - 1) * 1000.0 + (tv.tv_usec - usec_ + 1000000.0) / 1000.0 : + (tv.tv_sec - sec_) * 1000.0 + (tv.tv_usec - usec_) / 1000.0; +} + +double TimerMetric::AsUs() const { + struct timeval tv; + gettimeofday(&tv, NULL); + return usec_ > tv.tv_usec ? + (tv.tv_sec - sec_ - 1) * 1000000.0 + (tv.tv_usec - usec_ + 1000000.0) : + (tv.tv_sec - sec_) * 1000000.0 + (tv.tv_usec - usec_); +} + +} // namespace metrics +} // namespace wvcdm diff --git a/libwvdrmengine/cdm/metrics/test/distribution_test.cpp b/libwvdrmengine/cdm/metrics/test/distribution_test.cpp new file mode 100644 index 00000000..787978c0 --- /dev/null +++ b/libwvdrmengine/cdm/metrics/test/distribution_test.cpp @@ -0,0 +1,47 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Unit tests for Distribution. + +#include + +#include "distribution.h" + +#include "gtest/gtest.h" + +namespace wvcdm { +namespace metrics { + +TEST(DistributionTest, NoValuesRecorded) { + Distribution distribution; + EXPECT_EQ(DBL_MAX, distribution.Min()); + EXPECT_EQ(-DBL_MAX, distribution.Max()); + EXPECT_EQ(0, distribution.Mean()); + EXPECT_EQ(0, distribution.Count()); + EXPECT_EQ(0, distribution.Variance()); +} + +TEST(DistributionTest, OneValueRecorded) { + Distribution distribution; + distribution.Record(5.0); + EXPECT_EQ(5, distribution.Min()); + EXPECT_EQ(5, distribution.Max()); + EXPECT_EQ(5, distribution.Mean()); + EXPECT_EQ(1, distribution.Count()); + EXPECT_EQ(0, distribution.Variance()); +} + +TEST(DistributionTest, MultipleValuesRecorded) { + Distribution distribution; + distribution.Record(5.0); + distribution.Record(10.0); + distribution.Record(15.0); + EXPECT_EQ(5, distribution.Min()); + EXPECT_EQ(15, distribution.Max()); + EXPECT_EQ(10, distribution.Mean()); + EXPECT_EQ(3, distribution.Count()); + EXPECT_NEAR(16.6667, distribution.Variance(), 0.0001); +} + +} // namespace metrics +} // namespace wvcdm + diff --git a/libwvdrmengine/cdm/metrics/test/event_metric_test.cpp b/libwvdrmengine/cdm/metrics/test/event_metric_test.cpp new file mode 100644 index 00000000..21722617 --- /dev/null +++ b/libwvdrmengine/cdm/metrics/test/event_metric_test.cpp @@ -0,0 +1,226 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Unit tests for EventMetric + +#include "event_metric.h" +#include "metric_publisher.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "scoped_ptr.h" + +using testing::IsNull; +using testing::NotNull; + +namespace wvcdm { +namespace metrics { + +class MockEventMetricNotification : public MetricNotification { + public: + MOCK_METHOD2(UpdateString, void(const std::string& metric_id, + const std::string& value)); + MOCK_METHOD2(UpdateInt32, void(const std::string& metric_id, + int32_t value)); + MOCK_METHOD2(UpdateInt64, void(const std::string& metric_id, + int64_t value)); + MOCK_METHOD2(UpdateDouble, void(const std::string& metric_id, + double value)); +}; + +class EventMetricTest : public ::testing::Test { + public: + void SetUp() { + mock_notification_.reset(new MockEventMetricNotification()); + } + protected: + template + const std::map + GetValueMap( + const wvcdm::metrics::EventMetric& + metric) { + return metric.value_map_; + } + + scoped_ptr mock_notification_; +}; + +TEST_F(EventMetricTest, NoFieldsSuccessNullCallback) { + wvcdm::metrics::EventMetric<> metric("no/fields/metric"); + metric.Record(10LL); + metric.Record(10LL); + + std::map value_map = GetValueMap(metric); + ASSERT_EQ(1, GetValueMap(metric).size()); + EXPECT_EQ(2, value_map.begin()->second->Count()); + EXPECT_EQ("", value_map.begin()->first); +} + +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)); + + metric.Record(10); + metric.Publish(mock_notification_.get()); + + std::map value_map = GetValueMap(metric); + ASSERT_EQ(1, GetValueMap(metric).size()); + EXPECT_EQ(1, value_map.begin()->second->Count()); + EXPECT_EQ("", value_map.begin()->first); +} + +TEST_F(EventMetricTest, OneFieldSuccessNoCallback) { + wvcdm::metrics::EventMetric metric( + "single/fields/metric", + "error_code"); + metric.Record(10LL, 7); + metric.Record(11LL, 13); + metric.Record(12LL, 13); + std::map value_map = GetValueMap(metric); + ASSERT_EQ(2, GetValueMap(metric).size()); + + // Verify both instances. + // TODO(blueeyes): Export MakeFieldNameString so it can be used here. + Distribution* distribution_error_7 = value_map["{error_code:7}"]; + Distribution* distribution_error_13 = value_map["{error_code:13}"]; + ASSERT_THAT(distribution_error_7, NotNull()); + ASSERT_THAT(distribution_error_13, NotNull()); + + EXPECT_EQ(1, distribution_error_7->Count()); + EXPECT_EQ(2, distribution_error_13->Count()); +} + +TEST_F(EventMetricTest, TwoFieldsSuccess) { + wvcdm::metrics::EventMetric metric( + "two/fields/metric", + "error_code", + "size"); + metric.Record(1, 7, 23); + metric.Record(2, 7, 29); + metric.Record(3, 11, 23); + metric.Record(4, 11, 29); + metric.Record(5, 7, 23); + + std::map value_map = GetValueMap(metric); + ASSERT_EQ(4, GetValueMap(metric).size()); + + // Verify all instances. + Distribution* distribution_7_23 = value_map["{error_code:7&size:23}"]; + Distribution* distribution_7_29 = value_map["{error_code:7&size:29}"]; + Distribution* distribution_11_23 = value_map["{error_code:11&size:23}"]; + Distribution* distribution_11_29 = value_map["{error_code:11&size:29}"]; + ASSERT_THAT(distribution_7_23, NotNull()); + ASSERT_THAT(distribution_7_29, NotNull()); + ASSERT_THAT(distribution_11_23, NotNull()); + ASSERT_THAT(distribution_11_29, NotNull()); + + EXPECT_EQ(2, distribution_7_23->Count()); + EXPECT_EQ(1, distribution_7_29->Count()); + EXPECT_EQ(1, distribution_11_23->Count()); + EXPECT_EQ(1, distribution_11_29->Count()); + + // Verify that a non-existent distribution returns nullptr. + Distribution* null_distribution = value_map["error_code:1,size:1"]; + ASSERT_THAT(null_distribution, IsNull()); +} + +TEST_F(EventMetricTest, TwoFieldsSuccessWithCallback) { + wvcdm::metrics::EventMetric metric("two/fields/metric", + "error_code", + "pow2_size"); + + // Callbacks from second record operation. + EXPECT_CALL( + *mock_notification_, + UpdateInt64("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)); + EXPECT_CALL( + *mock_notification_, + UpdateDouble("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)); + EXPECT_CALL( + *mock_notification_, + UpdateDouble("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()); +} + +TEST_F(EventMetricTest, ThreeFieldsSuccess) { + wvcdm::metrics::EventMetric metric( + "three/fields/metric", + "error_code", + "size", + "woke up happy"); + metric.Record(10LL, 7, 13, false); + + + std::map value_map = GetValueMap(metric); + ASSERT_EQ(1, GetValueMap(metric).size()); + EXPECT_EQ("{error_code:7&size:13&woke up happy:0}", + value_map.begin()->first); + EXPECT_EQ(1, value_map.begin()->second->Count()); +} + +TEST_F(EventMetricTest, FourFieldsSuccess) { + wvcdm::metrics::EventMetric metric( + "Four/fields/metric", + "error_code", + "size", + "woke up happy", + "horoscope"); + metric.Record(10LL, 7, 13, true, "find your true love"); + + std::map value_map = GetValueMap(metric); + ASSERT_EQ(1, GetValueMap(metric).size()); + EXPECT_EQ( + "{error_code:7&size:13&woke up happy:1&horoscope:find your true love}", + value_map.begin()->first); + EXPECT_EQ(1, value_map.begin()->second->Count()); +} + +TEST_F(EventMetricTest, Pow2BucketTest) { + std::stringstream value; + value << Pow2Bucket(1); + EXPECT_EQ("1", value.str()); + + value.str(""); + value << Pow2Bucket(0); + EXPECT_EQ("0", value.str()); + + value.str(""); + value << Pow2Bucket(2); + EXPECT_EQ("2", value.str()); + + value.str(""); + value << Pow2Bucket(0xFFFFFFFF); + EXPECT_EQ("2147483648", value.str()); + + value.str(""); + value << Pow2Bucket(0x80000000); + EXPECT_EQ("2147483648", value.str()); + + value.str(""); + value << Pow2Bucket(0x7FFFFFFF); + EXPECT_EQ("1073741824", value.str()); +} + +} // namespace metrics +} // namespace wvcdm + diff --git a/libwvdrmengine/cdm/src/ami_adapter.cpp b/libwvdrmengine/cdm/src/ami_adapter.cpp new file mode 100644 index 00000000..ed228370 --- /dev/null +++ b/libwvdrmengine/cdm/src/ami_adapter.cpp @@ -0,0 +1,71 @@ +// Copyright 2017 Google Inc. All Rights Reserved. + +#include "ami_adapter.h" + +#include + +namespace wvcdm { + +AmiAdapter::AmiAdapter() : + analytics_item_("widevine") { + analytics_item_.generateSessionID(); +} + +AmiAdapter::AmiAdapter(int64_t parent) : + analytics_item_("widevine") { + analytics_item_.generateSessionID(); + analytics_item_.setInt64("/drm/widevine/parent/external", parent); +} + +AmiAdapter::~AmiAdapter() { + analytics_item_.setFinalized(true); + 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()); + LOGI( + "AmiAdapter (%lld) %s : %s", + analytics_item_.getSessionID(), + metric_id.c_str(), + value.c_str()); +} + +void AmiAdapter::UpdateInt32(const std::string& metric_id, + int32_t value) { + analytics_item_.setInt32(metric_id.c_str(), value); + LOGI( + "AmiAdapter (%lld) %s : %ld", + analytics_item_.getSessionID(), + metric_id.c_str(), + value); +} + +void AmiAdapter::UpdateInt64(const std::string& metric_id, + int64_t value) { + analytics_item_.setInt64(metric_id.c_str(), value); + LOGI( + "AmiAdapter (%lld) %s : %lld", + analytics_item_.getSessionID(), + metric_id.c_str(), + value); +} + +void AmiAdapter::UpdateDouble(const std::string& metric_id, + double value) { + analytics_item_.setDouble(metric_id.c_str(), value); + LOGI( + "AmiAdapter (%lld) %s : %f", + analytics_item_.getSessionID(), + metric_id.c_str(), + value); +} + +} // namespace wvcdm + + diff --git a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp index 7ee213d3..6ed289db 100644 --- a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp +++ b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp @@ -2,11 +2,13 @@ #include "wv_content_decryption_module.h" +#include "ami_adapter.h" #include "cdm_client_property_set.h" #include "cdm_engine.h" #include "initialization_data.h" #include "license.h" #include "log.h" +#include "metrics_front_end.h" #include "properties.h" #include "service_certificate.h" #include "wv_cdm_constants.h" @@ -20,10 +22,20 @@ namespace wvcdm { Lock WvContentDecryptionModule::session_sharing_id_generation_lock_; -WvContentDecryptionModule::WvContentDecryptionModule() {} +WvContentDecryptionModule::WvContentDecryptionModule() { + report_root_ = new AmiAdapter(); + front_end_ = new metrics::MetricsFrontEnd(report_root_); + metrics::MetricsFrontEnd::OverrideInstance(front_end_); +} 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) { @@ -53,8 +65,16 @@ CdmResponseType WvContentDecryptionModule::OpenSession( } CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier); - CdmResponseType sts = cdm_engine->OpenSession(key_system, property_set, - event_listener, session_id); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->OpenSession( + key_system, + property_set, + event_listener, + session_id), + cdm_engine->GetMetrics(), + cdm_engine_open_session_, + sts); if (sts == NO_ERROR) { cdm_by_session_id_[*session_id] = cdm_engine; } @@ -66,7 +86,13 @@ CdmResponseType WvContentDecryptionModule::CloseSession( CdmEngine* cdm_engine = GetCdmForSessionId(session_id); // TODO(rfrias): Avoid reusing the error codes from CdmEngine. if (!cdm_engine) return SESSION_NOT_FOUND_1; - CdmResponseType sts = cdm_engine->CloseSession(session_id); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->CloseSession( + session_id), + cdm_engine->GetMetrics(), + cdm_engine_close_session_, + sts); if (sts == NO_ERROR) { cdm_by_session_id_.erase(session_id); } @@ -88,19 +114,37 @@ CdmResponseType WvContentDecryptionModule::GenerateKeyRequest( CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier); CdmResponseType sts; if (license_type == kLicenseTypeRelease) { - sts = cdm_engine->OpenKeySetSession(key_set_id, property_set, NULL); + M_TIME( + sts = cdm_engine->OpenKeySetSession( + key_set_id, + property_set, + NULL), + cdm_engine->GetMetrics(), + cdm_engine_open_key_set_session_, + sts); if (sts != NO_ERROR) return sts; cdm_by_session_id_[key_set_id] = cdm_engine; } InitializationData initialization_data(init_data_type, init_data); - sts = cdm_engine->GenerateKeyRequest( - session_id, key_set_id, initialization_data, license_type, app_parameters, - key_request); - + M_TIME( + sts = cdm_engine->GenerateKeyRequest( + session_id, + key_set_id, + initialization_data, + license_type, + app_parameters, + key_request), + cdm_engine->GetMetrics(), + cdm_engine_generate_key_request_, + sts); switch(license_type) { case kLicenseTypeRelease: if (sts != KEY_MESSAGE) { - cdm_engine->CloseKeySetSession(key_set_id); + M_TIME( + cdm_engine->CloseKeySetSession( + key_set_id), + cdm_engine->GetMetrics(), + cdm_engine_close_key_set_session_); cdm_by_session_id_.erase(key_set_id); } break; @@ -119,9 +163,21 @@ CdmResponseType WvContentDecryptionModule::AddKey( CdmEngine* cdm_engine = session_id.empty() ? GetCdmForSessionId(*key_set_id) : GetCdmForSessionId(session_id); if (!cdm_engine) return SESSION_NOT_FOUND_3; - CdmResponseType sts = cdm_engine->AddKey(session_id, key_data, key_set_id); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->AddKey( + session_id, + key_data, + key_set_id), + cdm_engine->GetMetrics(), + cdm_engine_add_key_, + sts); if (sts == KEY_ADDED && session_id.empty()) { // license type release - cdm_engine->CloseKeySetSession(*key_set_id); + M_TIME( + cdm_engine->CloseKeySetSession( + *key_set_id), + cdm_engine->GetMetrics(), + cdm_engine_close_key_set_session_); cdm_by_session_id_.erase(*key_set_id); } return sts; @@ -132,7 +188,14 @@ CdmResponseType WvContentDecryptionModule::RestoreKey( const CdmKeySetId& key_set_id) { CdmEngine* cdm_engine = GetCdmForSessionId(session_id); if (!cdm_engine) return SESSION_NOT_FOUND_4; - CdmResponseType sts = cdm_engine->RestoreKey(session_id, key_set_id); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->RestoreKey( + session_id, + key_set_id), + cdm_engine->GetMetrics(), + cdm_engine_restore_key_, + sts); if (sts == KEY_ADDED) EnablePolicyTimer(); return sts; @@ -142,7 +205,14 @@ CdmResponseType WvContentDecryptionModule::RemoveKeys( const CdmSessionId& session_id) { CdmEngine* cdm_engine = GetCdmForSessionId(session_id); if (!cdm_engine) return SESSION_NOT_FOUND_5; - return cdm_engine->RemoveKeys(session_id); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->RemoveKeys( + session_id), + cdm_engine->GetMetrics(), + cdm_engine_remove_keys_, + sts); + return sts; } CdmResponseType WvContentDecryptionModule::QueryStatus( @@ -150,28 +220,61 @@ CdmResponseType WvContentDecryptionModule::QueryStatus( const std::string& key, std::string* value) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier); - return cdm_engine->QueryStatus(security_level, key, value); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->QueryStatus( + security_level, + key, + value), + cdm_engine->GetMetrics(), + cdm_engine_query_status_, + sts); + return sts; } CdmResponseType WvContentDecryptionModule::QuerySessionStatus( const CdmSessionId& session_id, CdmQueryMap* key_info) { CdmEngine* cdm_engine = GetCdmForSessionId(session_id); if (!cdm_engine) return SESSION_NOT_FOUND_8; - return cdm_engine->QuerySessionStatus(session_id, key_info); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->QuerySessionStatus( + session_id, + key_info), + cdm_engine->GetMetrics(), + cdm_engine_query_session_status_, + sts); + return sts; } CdmResponseType WvContentDecryptionModule::QueryKeyStatus( const CdmSessionId& session_id, CdmQueryMap* key_info) { CdmEngine* cdm_engine = GetCdmForSessionId(session_id); if (!cdm_engine) return SESSION_NOT_FOUND_9; - return cdm_engine->QueryKeyStatus(session_id, key_info); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->QueryKeyStatus( + session_id, + key_info), + cdm_engine->GetMetrics(), + cdm_engine_query_key_status_, + sts); + return sts; } CdmResponseType WvContentDecryptionModule::QueryOemCryptoSessionId( const CdmSessionId& session_id, CdmQueryMap* response) { CdmEngine* cdm_engine = GetCdmForSessionId(session_id); if (!cdm_engine) return SESSION_NOT_FOUND_10; - return cdm_engine->QueryOemCryptoSessionId(session_id, response); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->QueryOemCryptoSessionId( + session_id, + response), + cdm_engine->GetMetrics(), + cdm_engine_query_oemcrypto_session_id_, + sts); + return sts; } CdmResponseType WvContentDecryptionModule::GetProvisioningRequest( @@ -181,8 +284,17 @@ CdmResponseType WvContentDecryptionModule::GetProvisioningRequest( CdmProvisioningRequest* request, std::string* default_url) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier); - return cdm_engine->GetProvisioningRequest(cert_type, cert_authority, request, - default_url); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->GetProvisioningRequest( + cert_type, + cert_authority, + request, + default_url), + cdm_engine->GetMetrics(), + cdm_engine_get_provisioning_request_, + sts); + return sts; } CdmResponseType WvContentDecryptionModule::HandleProvisioningResponse( @@ -191,19 +303,44 @@ CdmResponseType WvContentDecryptionModule::HandleProvisioningResponse( std::string* cert, std::string* wrapped_key) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier); - return cdm_engine->HandleProvisioningResponse(response, cert, wrapped_key); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->HandleProvisioningResponse( + response, + cert, + wrapped_key), + cdm_engine->GetMetrics(), + cdm_engine_handle_provisioning_response_, + sts); + return sts; } CdmResponseType WvContentDecryptionModule::Unprovision( CdmSecurityLevel level, const CdmIdentifier& identifier) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier); - return cdm_engine->Unprovision(level); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->Unprovision( + level), + cdm_engine->GetMetrics(), + cdm_engine_unprovision_, + sts, + level); + return sts; } CdmResponseType WvContentDecryptionModule::GetUsageInfo( const std::string& app_id, CdmUsageInfo* usage_info) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier); - return cdm_engine->GetUsageInfo(app_id, usage_info); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->GetUsageInfo( + app_id, + usage_info), + cdm_engine->GetMetrics(), + cdm_engine_get_usage_info_, + sts); + return sts; } CdmResponseType WvContentDecryptionModule::GetUsageInfo( @@ -211,19 +348,42 @@ CdmResponseType WvContentDecryptionModule::GetUsageInfo( const CdmSecureStopId& ssid, CdmUsageInfo* usage_info) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier); - return cdm_engine->GetUsageInfo(app_id, ssid, usage_info); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->GetUsageInfo( + app_id, + ssid, + usage_info), + cdm_engine->GetMetrics(), + cdm_engine_get_usage_info_, + sts); + return sts; } CdmResponseType WvContentDecryptionModule::ReleaseAllUsageInfo( const std::string& app_id) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier); - return cdm_engine->ReleaseAllUsageInfo(app_id); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->ReleaseAllUsageInfo( + app_id), + cdm_engine->GetMetrics(), + cdm_engine_release_all_usage_info_, + sts); + return sts; } CdmResponseType WvContentDecryptionModule::ReleaseUsageInfo( const CdmUsageInfoReleaseMessage& message) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier); - return cdm_engine->ReleaseUsageInfo(message); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->ReleaseUsageInfo( + message), + cdm_engine->GetMetrics(), + cdm_engine_release_usage_info_, + sts); + return sts; } CdmResponseType WvContentDecryptionModule::Decrypt( @@ -238,14 +398,28 @@ CdmResponseType WvContentDecryptionModule::Decrypt( CdmSessionId local_session_id = session_id; if (validate_key_id && Properties::GetSessionSharingId(session_id) != 0) { - bool status = cdm_engine->FindSessionForKey(*parameters.key_id, - &local_session_id); + bool status; + M_TIME( + status = cdm_engine->FindSessionForKey( + *parameters.key_id, + &local_session_id), + cdm_engine->GetMetrics(), + cdm_engine_find_session_for_key_, + status); if (!status) { LOGE("WvContentDecryptionModule::Decrypt: unable to find session"); return SESSION_NOT_FOUND_FOR_DECRYPT; } } - return cdm_engine->Decrypt(local_session_id, parameters); + CdmResponseType sts; + M_TIME( + sts = cdm_engine->Decrypt( + local_session_id, + parameters), + cdm_engine->GetMetrics(), + cdm_engine_decrypt_, + sts); + return sts; } void WvContentDecryptionModule::NotifyResolution(const CdmSessionId& session_id, @@ -253,7 +427,10 @@ void WvContentDecryptionModule::NotifyResolution(const CdmSessionId& session_id, uint32_t height) { CdmEngine* cdm_engine = GetCdmForSessionId(session_id); if (!cdm_engine) return; - cdm_engine->NotifyResolution(session_id, width, height); + M_TIME( + cdm_engine->NotifyResolution(session_id, width, height), + cdm_engine->GetMetrics(), + cdm_engine_notify_resolution_); } bool WvContentDecryptionModule::IsValidServiceCertificate( diff --git a/libwvdrmengine/cdm/test/unit-test.mk b/libwvdrmengine/cdm/test/unit-test.mk index a7aef767..2eefd04d 100644 --- a/libwvdrmengine/cdm/test/unit-test.mk +++ b/libwvdrmengine/cdm/test/unit-test.mk @@ -22,6 +22,7 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/cdm/core/include \ vendor/widevine/libwvdrmengine/cdm/core/test \ vendor/widevine/libwvdrmengine/cdm/include \ + vendor/widevine/libwvdrmengine/cdm/metrics/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ LOCAL_C_INCLUDES += external/protobuf/src @@ -41,12 +42,15 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libdl \ liblog \ + libmedia \ libprotobuf-cpp-lite \ libssl \ + libstagefright_foundation \ libutils \ LOCAL_CFLAGS += -DUNIT_TEST + LOCAL_MODULE_TARGET_ARCH := arm x86 mips include $(BUILD_EXECUTABLE) diff --git a/libwvdrmengine/mediacrypto/Android.mk b/libwvdrmengine/mediacrypto/Android.mk index 849837ca..621cb121 100644 --- a/libwvdrmengine/mediacrypto/Android.mk +++ b/libwvdrmengine/mediacrypto/Android.mk @@ -9,6 +9,7 @@ LOCAL_C_INCLUDES := \ frameworks/native/include \ vendor/widevine/libwvdrmengine/cdm/core/include \ vendor/widevine/libwvdrmengine/cdm/include \ + vendor/widevine/libwvdrmengine/cdm/metrics/include \ vendor/widevine/libwvdrmengine/include \ vendor/widevine/libwvdrmengine/mediacrypto/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ diff --git a/libwvdrmengine/mediacrypto/test/Android.mk b/libwvdrmengine/mediacrypto/test/Android.mk index abc92e24..927c8601 100644 --- a/libwvdrmengine/mediacrypto/test/Android.mk +++ b/libwvdrmengine/mediacrypto/test/Android.mk @@ -9,6 +9,7 @@ LOCAL_C_INCLUDES := \ frameworks/native/include \ vendor/widevine/libwvdrmengine/cdm/core/include \ vendor/widevine/libwvdrmengine/cdm/include \ + vendor/widevine/libwvdrmengine/cdm/metrics/include \ vendor/widevine/libwvdrmengine/mediacrypto/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ @@ -28,6 +29,7 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libdl \ liblog \ + libmedia \ libprotobuf-cpp-lite \ libstagefright_foundation \ libutils \ diff --git a/libwvdrmengine/mediadrm/Android.mk b/libwvdrmengine/mediadrm/Android.mk index 6038772a..497fe67f 100644 --- a/libwvdrmengine/mediadrm/Android.mk +++ b/libwvdrmengine/mediadrm/Android.mk @@ -10,6 +10,7 @@ LOCAL_C_INCLUDES := \ frameworks/native/include \ vendor/widevine/libwvdrmengine/cdm/core/include \ vendor/widevine/libwvdrmengine/cdm/include \ + vendor/widevine/libwvdrmengine/cdm/metrics/include \ vendor/widevine/libwvdrmengine/include \ vendor/widevine/libwvdrmengine/mediadrm/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ diff --git a/libwvdrmengine/mediadrm/test/Android.mk b/libwvdrmengine/mediadrm/test/Android.mk index 10da1c03..ca56aab4 100644 --- a/libwvdrmengine/mediadrm/test/Android.mk +++ b/libwvdrmengine/mediadrm/test/Android.mk @@ -9,6 +9,7 @@ LOCAL_C_INCLUDES := \ frameworks/native/include \ vendor/widevine/libwvdrmengine/cdm/core/include \ vendor/widevine/libwvdrmengine/cdm/include \ + vendor/widevine/libwvdrmengine/cdm/metrics/include \ vendor/widevine/libwvdrmengine/include \ vendor/widevine/libwvdrmengine/mediadrm/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ @@ -29,7 +30,9 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libdl \ liblog \ + libmedia \ libprotobuf-cpp-lite \ + libstagefright_foundation \ libutils \ LOCAL_C_INCLUDES += \ diff --git a/libwvdrmengine/oemcrypto/mock/Android.mk b/libwvdrmengine/oemcrypto/mock/Android.mk index 2b8f89fe..9e27d6c8 100644 --- a/libwvdrmengine/oemcrypto/mock/Android.mk +++ b/libwvdrmengine/oemcrypto/mock/Android.mk @@ -26,6 +26,8 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libdl \ liblog \ + libmedia \ + libstagefright_foundation \ libutils \ libz \ diff --git a/libwvdrmengine/oemcrypto/test/common.mk b/libwvdrmengine/oemcrypto/test/common.mk index 2b488bbf..efc25c06 100644 --- a/libwvdrmengine/oemcrypto/test/common.mk +++ b/libwvdrmengine/oemcrypto/test/common.mk @@ -31,6 +31,8 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libdl \ liblog \ + libmedia \ + libstagefright_foundation \ libutils \ libz \ diff --git a/libwvdrmengine/test/unit/Android.mk b/libwvdrmengine/test/unit/Android.mk index d032cf40..741c744a 100644 --- a/libwvdrmengine/test/unit/Android.mk +++ b/libwvdrmengine/test/unit/Android.mk @@ -21,6 +21,8 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_SHARED_LIBRARIES := \ libdl \ liblog \ + libmedia \ + libstagefright_foundation \ libutils \ libwvdrmengine \