diff --git a/libwvdrmengine/Android.mk b/libwvdrmengine/Android.mk index 2c61f443..c5279bd6 100644 --- a/libwvdrmengine/Android.mk +++ b/libwvdrmengine/Android.mk @@ -43,6 +43,9 @@ LOCAL_SHARED_LIBRARIES := \ libwvhidl \ libbinder \ +LOCAL_HEADER_LIBRARIES := \ + libstagefright_foundation_headers + LOCAL_MODULE := android.hardware.drm@1.0-service.widevine LOCAL_INIT_RC := src_hidl/android.hardware.drm@1.0-service.widevine.rc LOCAL_REQUIRED_MODULES := move_widevine_data.sh @@ -63,6 +66,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := libcdm_utils LOCAL_MODULE_CLASS := STATIC_LIBRARIES +LOCAL_PROPRIETARY_MODULE := true LOCAL_STATIC_LIBRARIES := libcrypto_static @@ -71,6 +75,12 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/cdm/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ +LOCAL_HEADER_LIBRARIES := \ + libutils_headers \ + +LOCAL_SHARED_LIBRARIES := \ + liblog + SRC_DIR := cdm/src CORE_SRC_DIR := cdm/core/src LOCAL_SRC_FILES := \ @@ -94,8 +104,11 @@ include $(CLEAR_VARS) LOCAL_MODULE := libcdm_protos LOCAL_MODULE_CLASS := STATIC_LIBRARIES +LOCAL_PROPRIETARY_MODULE := true -LOCAL_SRC_FILES := $(call all-proto-files-under, cdm/core/src) +CORE_PROTO_SRC_FILES := $(call all-proto-files-under, cdm/core/src) +METRICS_PROTO_SRC_FILES := $(call all-proto-files-under, cdm/metrics/src) +LOCAL_SRC_FILES := $(CORE_PROTO_SRC_FILES) $(METRICS_PROTO_SRC_FILES) generated_sources_dir := $(call local-generated-sources-dir) @@ -107,16 +120,18 @@ generated_sources_dir := $(call local-generated-sources-dir) # with this path. LOCAL_EXPORT_C_INCLUDE_DIRS := \ $(generated_sources_dir)/proto \ - $(generated_sources_dir)/proto/$(LOCAL_PATH)/cdm/core/src + $(generated_sources_dir)/proto/$(LOCAL_PATH)/cdm/core/src \ + $(generated_sources_dir)/proto/$(LOCAL_PATH)/cdm/metrics/src include $(BUILD_STATIC_LIBRARY) # ----------------------------------------------------------------------------- -# Builds libhidl_utils.a +# Builds libwidevinehidl_utils.a # include $(CLEAR_VARS) -LOCAL_MODULE := libhidl_utils +LOCAL_MODULE := libwidevinehidl_utils +LOCAL_PROPRIETARY_MODULE := true LOCAL_MODULE_CLASS := STATIC_LIBRARIES @@ -126,6 +141,9 @@ LOCAL_C_INCLUDES := \ LOCAL_SRC_FILES := \ src_hidl/TypeConvert.cpp +LOCAL_HEADER_LIBRARIES := \ + libstagefright_headers + LOCAL_SHARED_LIBRARIES := \ android.hardware.drm@1.0 @@ -172,6 +190,10 @@ LOCAL_SHARED_LIBRARIES := \ libstagefright_foundation \ libutils \ +LOCAL_HEADER_LIBRARIES := \ + libutils_headers \ + libstagefright_headers + LOCAL_MODULE := libwvdrmengine LOCAL_MODULE_RELATIVE_PATH := mediadrm diff --git a/libwvdrmengine/cdm/Android.mk b/libwvdrmengine/cdm/Android.mk index c65f13f3..83b7b5f2 100644 --- a/libwvdrmengine/cdm/Android.mk +++ b/libwvdrmengine/cdm/Android.mk @@ -14,6 +14,9 @@ LOCAL_C_INCLUDES += \ external/jsmn \ external/protobuf/src \ +LOCAL_HEADER_LIBRARIES := \ + libutils_headers + LOCAL_STATIC_LIBRARIES := libcdm_protos libcrypto_static SRC_DIR := src @@ -39,12 +42,12 @@ LOCAL_SRC_FILES := \ $(SRC_DIR)/wv_content_decryption_module.cpp \ $(METRICS_SRC_DIR)/distribution.cpp \ $(METRICS_SRC_DIR)/event_metric.cpp \ - $(METRICS_SRC_DIR)/metrics_front_end.cpp \ - $(METRICS_SRC_DIR)/metrics_group.cpp \ + $(METRICS_SRC_DIR)/metrics_collections.cpp \ $(METRICS_SRC_DIR)/timer_metric.cpp \ LOCAL_MODULE := libcdm LOCAL_MODULE_TAGS := optional +LOCAL_PROPRIETARY_MODULE := true include $(BUILD_STATIC_LIBRARY) diff --git a/libwvdrmengine/cdm/core/include/cdm_engine.h b/libwvdrmengine/cdm/core/include/cdm_engine.h index 11236435..b4ce958e 100644 --- a/libwvdrmengine/cdm/core/include/cdm_engine.h +++ b/libwvdrmengine/cdm/core/include/cdm_engine.h @@ -14,6 +14,7 @@ #include "file_store.h" #include "initialization_data.h" #include "lock.h" +#include "metrics_collections.h" #include "oemcrypto_adapter.h" #include "scoped_ptr.h" #include "service_certificate.h" @@ -290,7 +291,7 @@ class CdmEngine { // dead lock. virtual void OnTimerEvent(); - virtual metrics::MetricsGroup* GetMetrics() { return &metrics_; } + virtual metrics::EngineMetrics* GetMetrics() { return &metrics_; } private: // private methods @@ -320,7 +321,7 @@ class CdmEngine { * ensure that all data has been properly recorded in the group before * it is published. */ - metrics::MetricsGroup metrics_; + metrics::EngineMetrics metrics_; metrics::TimerMetric life_span_; CdmSessionMap session_map_; diff --git a/libwvdrmengine/cdm/core/include/cdm_session.h b/libwvdrmengine/cdm/core/include/cdm_session.h index ca269fd8..0456a207 100644 --- a/libwvdrmengine/cdm/core/include/cdm_session.h +++ b/libwvdrmengine/cdm/core/include/cdm_session.h @@ -12,7 +12,7 @@ #include "file_store.h" #include "initialization_data.h" #include "license.h" -#include "metrics_group.h" +#include "metrics_collections.h" #include "oemcrypto_adapter.h" #include "policy_engine.h" #include "scoped_ptr.h" @@ -28,13 +28,30 @@ class UsageTableHeader; class CdmSession { public: - CdmSession(FileSystem* file_system); + // Creates a new instance of the CdmSession with the given |file_system| + // and |metrics| parameters. Both parameters are owned by the caller and + // must remain in scope througout the scope of the new instance. |metrics| + // must not be null. + CdmSession(FileSystem* file_system, metrics::SessionMetrics* metrics); virtual ~CdmSession(); void Close() { closed_ = true; } bool IsClosed() { return closed_; } + // Initializes this instance of CdmSession with the given property set. + // |cdm_client_property_set| MAY be null, is owned by the caller, + // and must remain in scope throughout the scope of this session. virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set); + + // Initializes this instance of CdmSession with the given parmeters. + // All parameters are owned by the caller. + // |service_certificate| is caller owned, cannot be null, and must be in + // scope as long as the session is in scope. + // |cdm_client_property_set| is caller owned, may be null, but must be + // in scope as long as the session is in scope. + // |forced_session_id| is caller owned and may be null. + // |event_listener| is caller owned, may be null, but must be in scope + // as long as the session is in scope. virtual CdmResponseType Init(ServiceCertificate* service_certificate, CdmClientPropertySet* cdm_client_property_set, const CdmSessionId* forced_session_id, @@ -171,7 +188,7 @@ class CdmSession { CdmSigningAlgorithm algorithm, const std::string& signature); - virtual metrics::MetricsGroup* GetMetrics() { return &metrics_; } + virtual metrics::SessionMetrics* GetMetrics() { return metrics_; } private: friend class CdmSessionTest; @@ -190,20 +207,14 @@ class CdmSession { void set_file_handle(DeviceFiles* file_handle); // instance variables - - /* - * The metrics group must be the first variable declared to ensure - * that it is the last member destroyed so that no child members - * try to use a reference to it after it is destroyed. This will - * ensure that all data has been properly recorded in the group before - * it is published. - */ - metrics::MetricsGroup metrics_; + metrics::SessionMetrics* metrics_; + metrics::CryptoMetrics* crypto_metrics_; metrics::TimerMetric life_span_; bool initialized_; bool closed_; // Session closed, but final shared_ptr has not been released. CdmSessionId session_id_; + FileSystem* file_system_; scoped_ptr license_parser_; scoped_ptr crypto_session_; scoped_ptr policy_engine_; diff --git a/libwvdrmengine/cdm/core/include/certificate_provisioning.h b/libwvdrmengine/cdm/core/include/certificate_provisioning.h index 10cb323e..784f8921 100644 --- a/libwvdrmengine/cdm/core/include/certificate_provisioning.h +++ b/libwvdrmengine/cdm/core/include/certificate_provisioning.h @@ -7,7 +7,7 @@ #include "crypto_session.h" #include "license_protocol.pb.h" -#include "metrics_group.h" +#include "metrics_collections.h" #include "oemcrypto_adapter.h" #include "scoped_ptr.h" #include "wv_cdm_types.h" @@ -21,7 +21,7 @@ class ServiceCertificate; class CertificateProvisioning { public: - CertificateProvisioning(metrics::MetricsGroup* metrics, + CertificateProvisioning(metrics::CryptoMetrics* metrics, ServiceCertificate* service_certificate) : crypto_session_(metrics), cert_type_(kCertificateWidevine), diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index 1cae7170..f57132be 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -9,7 +9,7 @@ #include "OEMCryptoCENC.h" #include "lock.h" -#include "metrics_group.h" +#include "metrics_collections.h" #include "oemcrypto_adapter.h" #include "timer_metric.h" #include "wv_cdm_types.h" @@ -36,7 +36,10 @@ class CryptoSession { bool rsa_cast; }; - CryptoSession(metrics::MetricsGroup* metrics); + // Creates an instance of CryptoSession with the given |crypto_metrics|. + // |crypto_metrics| is owned by the caller, must NOT be null, and must + // exist as long as the new CryptoSession exists. + explicit CryptoSession(metrics::CryptoMetrics* crypto_metrics); virtual ~CryptoSession(); virtual bool GetClientToken(std::string* client_token); @@ -220,7 +223,7 @@ class CryptoSession { static bool initialized_; static int session_count_; - metrics::MetricsGroup* metrics_; + metrics::CryptoMetrics* metrics_; metrics::TimerMetric life_span_; bool open_; diff --git a/libwvdrmengine/cdm/core/include/usage_table_header.h b/libwvdrmengine/cdm/core/include/usage_table_header.h index 5fb703e9..0fb8f748 100644 --- a/libwvdrmengine/cdm/core/include/usage_table_header.h +++ b/libwvdrmengine/cdm/core/include/usage_table_header.h @@ -9,9 +9,8 @@ #include "device_files.h" #include "file_store.h" #include "lock.h" -#include "metrics_group.h" +#include "metrics_collections.h" #include "scoped_ptr.h" -#include "timer_metric.h" #include "wv_cdm_types.h" namespace wvcdm { @@ -67,29 +66,29 @@ class UsageTableHeader { // should not be in use by any open CryptoSession objects when calls // to DeleteEntry and MoveEntry are made. CdmResponseType DeleteEntry(uint32_t usage_entry_number, DeviceFiles* handle, - metrics::MetricsGroup* metrics); + metrics::CryptoMetrics* metrics); private: CdmResponseType MoveEntry(uint32_t from /* usage entry number */, const CdmUsageEntry& from_usage_entry, uint32_t to /* usage entry number */, DeviceFiles* handle, - metrics::MetricsGroup* metrics); + metrics::CryptoMetrics* metrics); CdmResponseType GetEntry(uint32_t usage_entry_number, DeviceFiles* handle, CdmUsageEntry* usage_entry); CdmResponseType StoreEntry(uint32_t usage_entry_number, DeviceFiles* handle, const CdmUsageEntry& usage_entry); - CdmResponseType Shrink(metrics::MetricsGroup* metrics, + CdmResponseType Shrink(metrics::CryptoMetrics* metrics, uint32_t number_of_usage_entries_to_delete); CdmResponseType UpgradeFromUsageTable(DeviceFiles* handle, - metrics::MetricsGroup* metrics); + metrics::CryptoMetrics* metrics); bool UpgradeLicensesFromUsageTable(DeviceFiles* handle, - metrics::MetricsGroup* metrics); + metrics::CryptoMetrics* metrics); bool UpgradeUsageInfoFromUsageTable(DeviceFiles* handle, - metrics::MetricsGroup* metrics); + metrics::CryptoMetrics* metrics); virtual bool is_inited() { return is_inited_; } diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h index 25f49bc2..d8198e20 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h @@ -77,6 +77,7 @@ static const std::string QUERY_VALUE_SECURITY_LEVEL_L1 = "L1"; static const std::string QUERY_VALUE_SECURITY_LEVEL_L2 = "L2"; static const std::string QUERY_VALUE_SECURITY_LEVEL_L3 = "L3"; static const std::string QUERY_VALUE_SECURITY_LEVEL_UNKNOWN = "Unknown"; +static const std::string QUERY_VALUE_SECURITY_LEVEL_DEFAULT = "Default"; static const std::string QUERY_VALUE_DISCONNECTED = "Disconnected"; static const std::string QUERY_VALUE_UNPROTECTED = "Unprotected"; static const std::string QUERY_VALUE_HDCP_V1 = "HDCP-1.x"; diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index 9bff5b29..20b7deaa 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -16,7 +16,6 @@ #include "file_store.h" #include "license_protocol.pb.h" #include "log.h" -#include "metrics_front_end.h" #include "properties.h" #include "string_conversions.h" #include "wv_cdm_constants.h" @@ -188,7 +187,8 @@ CdmResponseType CdmEngine::OpenSession( CloseExpiredReleaseSessions(); - scoped_ptr new_session(new CdmSession(file_system_)); + scoped_ptr new_session(new CdmSession(file_system_, + metrics_.AddSession())); CdmResponseType sts = new_session->Init(&service_certificate_, property_set, forced_session_id, event_listener); if (sts != NO_ERROR) { @@ -545,13 +545,13 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, const std::string& query_token, std::string* query_response) { LOGI("CdmEngine::QueryStatus"); - CryptoSession crypto_session(&metrics_); + CryptoSession crypto_session(metrics_.GetCryptoMetrics()); if (security_level == kLevel3) { CdmResponseType status; M_TIME( status = crypto_session.Open( kLevel3), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_open_, status, kLevel3); @@ -567,7 +567,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, CdmSecurityLevel level; M_TIME( level = crypto_session.GetSecurityLevel(), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_get_security_level_, level); switch (level) { @@ -594,7 +594,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, M_TIME( got_id = crypto_session.GetExternalDeviceUniqueId( &deviceId), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_get_device_unique_id_, got_id); if (!got_id) { @@ -609,7 +609,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, M_TIME( got_id = crypto_session.GetSystemId( &system_id), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_get_system_id_, got_id, system_id); @@ -646,7 +646,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, M_TIME( got_info = crypto_session.UsageInformationSupport( &supports_usage_reporting), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_usage_information_support_, got_info); if (!got_info) { @@ -854,7 +854,8 @@ CdmResponseType CdmEngine::GetProvisioningRequest( if (NULL == cert_provisioning_.get()) { cert_provisioning_.reset( - new CertificateProvisioning(&metrics_, &service_certificate_)); + new CertificateProvisioning(metrics_.GetCryptoMetrics(), + &service_certificate_)); } CdmResponseType ret = cert_provisioning_->GetProvisioningRequest( cert_provisioning_requested_security_level_, cert_type, cert_authority, @@ -896,12 +897,12 @@ CdmResponseType CdmEngine::HandleProvisioningResponse( if (NULL == cert_provisioning_.get()) { // Certificate provisioning object has been released. Check if a concurrent // provisioning attempt has succeeded before declaring failure. - CryptoSession crypto_session(&metrics_); + CryptoSession crypto_session(metrics_.GetCryptoMetrics()); CdmResponseType status; M_TIME( status = crypto_session.Open( cert_provisioning_requested_security_level_), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_open_, status, cert_provisioning_requested_security_level_); @@ -914,7 +915,7 @@ CdmResponseType CdmEngine::HandleProvisioningResponse( CdmSecurityLevel security_level; M_TIME( security_level = crypto_session.GetSecurityLevel(), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_get_security_level_, security_level); if (!IsProvisioned(security_level)) { @@ -968,14 +969,15 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) { } CdmResponseType CdmEngine::DeleteUsageTable(CdmSecurityLevel security_level) { - scoped_ptr crypto_session(new CryptoSession(&metrics_)); + scoped_ptr crypto_session( + new CryptoSession(metrics_.GetCryptoMetrics())); CdmResponseType status; M_TIME( status = crypto_session->Open( security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_open_, status, security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault); @@ -986,11 +988,12 @@ CdmResponseType CdmEngine::DeleteUsageTable(CdmSecurityLevel security_level) { } M_TIME( status = crypto_session->DeleteAllUsageReports(), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_delete_all_usage_reports_, status); if (status != NO_ERROR) { - LOGE("CdmEngine::DeleteUsageTable: error deleteing usage reports: %d", status); + LOGE("CdmEngine::DeleteUsageTable: error deleteing usage reports: %d", + status); } return status; } @@ -1049,7 +1052,8 @@ CdmResponseType CdmEngine::DeleteUsageRecord(const std::string& app_id, } // Got provider token. Remove from OEMCrypto. - scoped_ptr crypto_session(new CryptoSession(&metrics_)); + scoped_ptr crypto_session( + new CryptoSession(metrics_.GetCryptoMetrics())); CdmResponseType status = crypto_session->Open( security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault); if (status == NO_ERROR) { @@ -1079,7 +1083,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, } usage_property_set_->set_security_level(kLevelDefault); usage_property_set_->set_app_id(app_id); - usage_session_.reset(new CdmSession(file_system_)); + usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession())); CdmResponseType status = usage_session_->Init(usage_property_set_.get()); if (NO_ERROR != status) { LOGE("CdmEngine::GetUsageInfo: session init error: %d", status); @@ -1099,7 +1103,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, ssid, &usage_data)) { usage_property_set_->set_security_level(kLevel3); usage_property_set_->set_app_id(app_id); - usage_session_.reset(new CdmSession(file_system_)); + usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession())); status = usage_session_->Init(usage_property_set_.get()); if (NO_ERROR != status) { LOGE("CdmEngine::GetUsageInfo: session init error"); @@ -1176,7 +1180,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, usage_property_set_->set_security_level(requested_security_level); usage_property_set_->set_app_id(app_id); - usage_session_.reset(new CdmSession(file_system_)); + usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession())); CdmResponseType status = usage_session_->Init(usage_property_set_.get()); if (NO_ERROR != status) { @@ -1257,7 +1261,8 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo( } // Got at least one provider token. Remove from OEMCrypto. - scoped_ptr crypto_session(new CryptoSession(&metrics_)); + scoped_ptr crypto_session( + new CryptoSession(metrics_.GetCryptoMetrics())); CdmResponseType status = crypto_session->Open( security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault); if (status == NO_ERROR) { @@ -1285,7 +1290,7 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) { ? kLevel3 : kLevelDefault; usage_property_set_->set_security_level(security_level); - usage_session_.reset(new CdmSession(file_system_)); + usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession())); usage_session_->Init(usage_property_set_.get()); switch (usage_session_->get_usage_support_type()) { @@ -1730,19 +1735,20 @@ void CdmEngine::DeleteAllUsageReportsUponFactoryReset() { if (!file_system_->Exists(device_base_path_level1) && !file_system_->Exists(device_base_path_level3)) { - scoped_ptr crypto_session(new CryptoSession(&metrics_)); + scoped_ptr crypto_session( + new CryptoSession(metrics_.GetCryptoMetrics())); CdmResponseType status; M_TIME( status = crypto_session->Open( cert_provisioning_requested_security_level_), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_open_, status, cert_provisioning_requested_security_level_); if (NO_ERROR == status) { M_TIME( status = crypto_session->DeleteAllUsageReports(), - &metrics_, + metrics_.GetCryptoMetrics(), crypto_session_delete_all_usage_reports_, status); if (NO_ERROR != status) { diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index d9a3190f..ad9ea150 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -12,7 +12,6 @@ #include "clock.h" #include "file_store.h" #include "log.h" -#include "metrics_front_end.h" #include "properties.h" #include "string_conversions.h" #include "wv_cdm_constants.h" @@ -25,10 +24,10 @@ const size_t kKeySetIdLength = 14; namespace wvcdm { -CdmSession::CdmSession(FileSystem* file_system) : +CdmSession::CdmSession(FileSystem* file_system, + metrics::SessionMetrics* metrics) : + metrics_(metrics), initialized_(false), - closed_(false), - crypto_session_(new CryptoSession(&metrics_)), file_handle_(new DeviceFiles(file_system)), license_received_(false), is_offline_(false), @@ -45,6 +44,9 @@ CdmSession::CdmSession(FileSystem* file_system) : usage_entry_number_(0), mock_license_parser_in_use_(false), mock_policy_engine_in_use_(false) { + assert(metrics_); // metrics_ must not be null. + crypto_metrics_ = metrics_->GetCryptoMetrics(); + crypto_session_.reset(new CryptoSession(crypto_metrics_)); life_span_.Start(); } @@ -55,7 +57,10 @@ CdmSession::~CdmSession() { } Properties::RemoveSessionPropertySet(session_id_); - M_RECORD(&metrics_, cdm_session_life_span_, life_span_.AsMs()); + if (metrics_) { + M_RECORD(metrics_, cdm_session_life_span_, life_span_.AsMs()); + metrics_->SetCompleted(); + } } CdmResponseType CdmSession::Init( @@ -80,16 +85,15 @@ CdmResponseType CdmSession::Init( } CdmResponseType sts; M_TIME( - sts = crypto_session_->Open( - requested_security_level_), - &metrics_, + sts = crypto_session_->Open(requested_security_level_), + crypto_metrics_, crypto_session_open_, sts, requested_security_level_); if (NO_ERROR != sts) return sts; M_TIME( security_level_ = crypto_session_->GetSecurityLevel(), - &metrics_, + crypto_metrics_, crypto_session_get_security_level_, security_level_); if (!file_handle_->Init(security_level_)) { @@ -126,7 +130,7 @@ CdmResponseType CdmSession::Init( M_TIME( get_client_token_sts = crypto_session_->GetClientToken( &client_token), - &metrics_, + crypto_metrics_, crypto_session_get_token_, get_client_token_sts); if (!get_client_token_sts) { @@ -144,7 +148,7 @@ CdmResponseType CdmSession::Init( M_TIME( load_cert_sts = crypto_session_->LoadCertificatePrivateKey( wrapped_key), - &metrics_, + crypto_metrics_, crypto_session_load_certificate_private_key_, load_cert_sts); if(!load_cert_sts) { @@ -166,6 +170,7 @@ CdmResponseType CdmSession::Init( session_id_ = Properties::AlwaysUseKeySetIds() ? key_set_id_ : GenerateSessionId(); + metrics_->SetSessionId(session_id_); if (session_id_.empty()) { LOGE("CdmSession::Init: empty session ID"); @@ -222,14 +227,20 @@ CdmResponseType CdmSession::RestoreOfflineSession( return GET_RELEASED_LICENSE_ERROR; } + std::string provider_session_token; if (usage_support_type_ == kUsageEntrySupport) { - CdmResponseType sts = usage_table_header_->LoadEntry(crypto_session_.get(), - usage_entry_, - usage_entry_number_); - if (sts != NO_ERROR) { - LOGE("CdmSession::RestoreOfflineSession: failed to load usage entry = %d", - sts); - return sts; + if (!license_parser_->ExtractProviderSessionToken( + key_response_, &provider_session_token)) { + provider_session_token.clear(); + } else { + CdmResponseType sts = + usage_table_header_->LoadEntry(crypto_session_.get(), usage_entry_, + usage_entry_number_); + if (sts != NO_ERROR) { + LOGE("CdmSession::RestoreOfflineSession: failed to load usage entry = " + "%d", sts); + return sts; + } } } @@ -246,7 +257,8 @@ CdmResponseType CdmSession::RestoreOfflineSession( } } - if (usage_support_type_ == kUsageEntrySupport) { + if (usage_support_type_ == kUsageEntrySupport && + !provider_session_token.empty()) { CdmResponseType sts = usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_); if (sts != NO_ERROR) { @@ -432,7 +444,8 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) { if (sts != KEY_ADDED) { CdmResponseType sts = usage_table_header_->DeleteEntry(usage_entry_number_, - file_handle_.get(), &metrics_); + file_handle_.get(), + crypto_metrics_); if (sts != NO_ERROR) { LOGW("CdmSession::AddKey: Delete usage entry failed = %d", sts); } @@ -449,8 +462,10 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) { license_parser_->provider_session_token().c_str()); if (is_offline_ || has_provider_session_token()) { - if (usage_support_type_ == kUsageEntrySupport) + if (has_provider_session_token() && + usage_support_type_ == kUsageEntrySupport) { usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_); + } if (!is_offline_) usage_provider_session_token_ = @@ -614,7 +629,8 @@ CdmResponseType CdmSession::GenerateReleaseRequest( if (KEY_MESSAGE != status) return status; - if (usage_support_type_ == kUsageEntrySupport) { + if (has_provider_session_token() && + usage_support_type_ == kUsageEntrySupport) { status = usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_); if (status != NO_ERROR) { @@ -645,7 +661,8 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) { if (is_offline_ || has_provider_session_token()) { DeleteLicense(); - if (usage_support_type_ == kUsageEntrySupport) { + if (usage_support_type_ == kUsageEntrySupport && + has_provider_session_token()) { sts = DeleteUsageEntry(usage_entry_number_); if (NO_ERROR != sts) return sts; } @@ -654,7 +671,8 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) { } CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) { - if (usage_support_type_ != kUsageEntrySupport) { + if (usage_support_type_ != kUsageEntrySupport || + !has_provider_session_token()) { LOGE("CdmSession::DeleteUsageEntry: Unexpected usage type supported: %d", usage_support_type_); return INCORRECT_USAGE_SUPPORT_TYPE_1; @@ -664,10 +682,10 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) { // it, so close and reopen session. CdmResponseType sts; crypto_session_->Close(); - crypto_session_.reset(new CryptoSession(&metrics_)); + crypto_session_.reset(new CryptoSession(crypto_metrics_)); M_TIME( sts = crypto_session_->Open(requested_security_level_), - &metrics_, + crypto_metrics_, crypto_session_open_, sts, requested_security_level_); @@ -688,7 +706,7 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) { return usage_table_header_->DeleteEntry(usage_entry_number, file_handle_.get(), - &metrics_); + crypto_metrics_); } bool CdmSession::IsKeyLoaded(const KeyId& key_id) { @@ -838,7 +856,7 @@ CdmResponseType CdmSession::DeleteMultipleUsageInformation( M_TIME( sts = crypto_session_->DeleteMultipleUsageInformation( provider_session_tokens), - &metrics_, + crypto_metrics_, crypto_session_delete_multiple_usage_information_, sts); return sts; @@ -852,7 +870,7 @@ CdmResponseType CdmSession::UpdateUsageTableInformation() { if (sts == NO_ERROR && usage_support_type == kUsageTableSupport) { M_TIME( sts = crypto_session_->UpdateUsageInformation(), - &metrics_, + crypto_metrics_, crypto_session_update_usage_information_, sts); return sts; @@ -862,7 +880,8 @@ CdmResponseType CdmSession::UpdateUsageTableInformation() { } CdmResponseType CdmSession::UpdateUsageEntryInformation() { - if (usage_support_type_ != kUsageEntrySupport) { + if (usage_support_type_ != kUsageEntrySupport || + !has_provider_session_token()) { LOGE("CdmSession::UpdateUsageEntryInformation: Unexpected usage type " "supported: %d", usage_support_type_); return INCORRECT_USAGE_SUPPORT_TYPE_2; @@ -900,7 +919,7 @@ CdmResponseType CdmSession::GenericEncrypt(const std::string& in_buffer, iv, algorithm, out_buffer), - &metrics_, + crypto_metrics_, crypto_session_generic_encrypt_, sts, metrics::Pow2Bucket(in_buffer.size()), @@ -925,7 +944,7 @@ CdmResponseType CdmSession::GenericDecrypt(const std::string& in_buffer, iv, algorithm, out_buffer), - &metrics_, + crypto_metrics_, crypto_session_generic_decrypt_, sts, metrics::Pow2Bucket(in_buffer.size()), @@ -948,7 +967,7 @@ CdmResponseType CdmSession::GenericSign(const std::string& message, key_id, algorithm, signature), - &metrics_, + crypto_metrics_, crypto_session_generic_sign_, sts, metrics::Pow2Bucket(message.size()), @@ -967,7 +986,7 @@ CdmResponseType CdmSession::GenericVerify(const std::string& message, key_id, algorithm, signature), - &metrics_, + crypto_metrics_, crypto_session_generic_verify_, sts, metrics::Pow2Bucket(message.size()), diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 0c6f2e7d..a580cb96 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -12,7 +12,6 @@ #include "crypto_key.h" #include "log.h" -#include "metrics_front_end.h" #include "openssl/sha.h" #include "properties.h" #include "pst_report.h" @@ -45,7 +44,7 @@ uint64_t CryptoSession::request_id_index_ = 0; UsageTableHeader* CryptoSession::usage_table_header_l1_ = NULL; UsageTableHeader* CryptoSession::usage_table_header_l3_ = NULL; -CryptoSession::CryptoSession(metrics::MetricsGroup* metrics) +CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics) : metrics_(metrics), open_(false), update_usage_table_after_close_session_(false), @@ -234,34 +233,43 @@ bool CryptoSession::GetProvisioningToken(std::string* token) { CdmSecurityLevel CryptoSession::GetSecurityLevel() { LOGV("CryptoSession::GetSecurityLevel"); if (!initialized_) { + M_RECORD(metrics_, oemcrypto_security_level_, 0, + kSecurityLevelUninitialized, requested_security_level_); return kSecurityLevelUninitialized; } - std::string security_level; - M_TIME( - security_level = OEMCrypto_SecurityLevel( - requested_security_level_), - metrics_, - oemcrypto_security_level_, - security_level, - requested_security_level_); + wvcdm::metrics::TimerMetric timer; + timer.Start(); + + std::string security_level = + OEMCrypto_SecurityLevel(requested_security_level_); + double clock_time = timer.AsUs(); if ((security_level.size() != 2) || (security_level.at(0) != 'L')) { + M_RECORD(metrics_, oemcrypto_security_level_, clock_time, + kSecurityLevelUnknown, requested_security_level_); return kSecurityLevelUnknown; } + CdmSecurityLevel cdm_security_level; switch (security_level.at(1)) { case '1': - return kSecurityLevelL1; + cdm_security_level = kSecurityLevelL1; + break; case '2': - return kSecurityLevelL2; + cdm_security_level = kSecurityLevelL2; + break; case '3': - return kSecurityLevelL3; + cdm_security_level = kSecurityLevelL3; + break; default: - return kSecurityLevelUnknown; + cdm_security_level = kSecurityLevelUnknown; + break; } - return kSecurityLevelUnknown; + M_RECORD(metrics_, oemcrypto_security_level_, clock_time, + cdm_security_level, requested_security_level_); + return cdm_security_level; } bool CryptoSession::GetInternalDeviceUniqueId(std::string* device_id) { @@ -444,8 +452,10 @@ uint8_t CryptoSession::GetSecurityPatchLevel() { } CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) { - LOGV("CryptoSession::Open: Lock: requested_security_level: %d", - requested_security_level); + LOGD("CryptoSession::Open: Lock: requested_security_level: %s", + requested_security_level == kLevel3 + ? QUERY_VALUE_SECURITY_LEVEL_L3.c_str() + : QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str()); AutoLock auto_lock(crypto_lock_); if (!initialized_) return UNKNOWN_ERROR; if (open_) return NO_ERROR; @@ -719,6 +729,10 @@ CdmResponseType CryptoSession::LoadKeys( } else if (OEMCrypto_ERROR_TOO_MANY_KEYS == sts) { LOGE("CryptoSession::LoadKeys: OEMCrypto_LoadKeys error=%d", sts); result = INSUFFICIENT_CRYPTO_RESOURCES; + } else if (OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE == sts) { + // Handle vendor specific error + LOGE("CryptoSession::LoadKeys: OEMCrypto_LoadKeys error=%d", sts); + result = NEED_PROVISIONING; } else { LOGE("CryptoSession::LoadKeys: OEMCrypto_LoadKeys error=%d", sts); result = LOAD_KEY_ERROR; @@ -1750,11 +1764,15 @@ bool CryptoSession::GetSrmVersion(uint16_t* srm_version) { } OEMCryptoResult status = OEMCrypto_GetCurrentSRMVersion(srm_version); - if (OEMCrypto_SUCCESS != status) { - LOGW("OEMCrypto_GetCurrentSRMVersion fails with %d", status); - return false; + switch (status) { + case OEMCrypto_SUCCESS: + return true; + case OEMCrypto_ERROR_NOT_IMPLEMENTED: + return false; + default: + LOGW("OEMCrypto_GetCurrentSRMVersion fails with %d", status); + return false; } - return true; } bool CryptoSession::IsSrmUpdateSupported() { diff --git a/libwvdrmengine/cdm/core/src/device_files.cpp b/libwvdrmengine/cdm/core/src/device_files.cpp index c9dfa1ae..4db8d3de 100644 --- a/libwvdrmengine/cdm/core/src/device_files.cpp +++ b/libwvdrmengine/cdm/core/src/device_files.cpp @@ -163,7 +163,7 @@ bool DeviceFiles::ExtractDeviceInfo(const std::string& device_certificate, uint32_t* system_id) { LOGI("ExtractDeviceInfo Entry"); if (!serial_number && !system_id) { - LOGE("Invalid paramters to DeviceFiles::ExtractDeviceInfo"); + LOGE("DeviceFiles::ExtractDeviceInfo: invalid parameter."); return false; } @@ -1239,7 +1239,7 @@ bool DeviceFiles::FileExists(const std::string& name) { bool DeviceFiles::ListFiles(std::vector* names) { std::string path; if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) { - LOGW("DeviceFiles::RemoveFile: Unable to get base path"); + LOGW("DeviceFiles::ListFiles: Unable to get base path"); return false; } return file_system_->List(path, names); diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index 3143c098..36fcd9c1 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -486,13 +486,11 @@ CdmResponseType CdmLicense::HandleKeyResponse( license.policy().can_persist()) is_offline_ = true; - LOGV("Get Provider_session_token:"); - if (license.id().has_provider_session_token()) { + if (license.id().has_provider_session_token()) provider_session_token_ = license.id().provider_session_token(); - LOGV("Provider_session_token=%s", provider_session_token_.c_str()); - } else { - LOGV("NO Provider_session_token"); - } + + LOGV("provider_session_token: %s", provider_session_token_.empty() ? + "N/A" : provider_session_token_.c_str()); if (license.policy().has_renewal_server_url()) { server_url_ = license.policy().renewal_server_url(); @@ -803,7 +801,8 @@ bool CdmLicense::ExtractProviderSessionToken( return false; } - if (license.id().has_provider_session_token()) { + if (license.id().has_provider_session_token() && + !license.id().provider_session_token().empty()) { *provider_session_token = license.id().provider_session_token(); return true; } diff --git a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp index 50d12393..3ec8429a 100644 --- a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp +++ b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp @@ -29,8 +29,7 @@ #include "level3.h" #include "lock.h" #include "log.h" -#include "metrics_front_end.h" -#include "metrics_group.h" +#include "metrics_collections.h" #include "properties.h" #include "wv_cdm_constants.h" @@ -41,6 +40,8 @@ using wvcdm::kLevel3; namespace { static const size_t kMaxGenericEncryptChunkSize = 100*1024; +const OEMCryptoResult kOemCryptoResultVendorSpecificError1 = + static_cast(10008); typedef struct { const uint8_t* key_id; @@ -375,6 +376,162 @@ void clear_cache_function(void *page, size_t len) { #endif } +// The WatchDog looks after a worker thread that is trying to initialize L3. +// Once in a rare while, the L3 init does not finish and eats up CPU cycles. +// If that happens, the watchdog thread will give up and return an error. +class WatchDog { + public: + // Created by main thread. + WatchDog() { + pthread_mutex_init(&mutex_, NULL); + pthread_cond_init(&condition_, NULL); + status_ = OEMCrypto_SUCCESS; + gave_up_ = false; + } + + // Deleted by either thread. + ~WatchDog() { + pthread_cond_destroy(&condition_); + } + + // Starts worker thread. + void StartThread() { + running_ = true; + if(pthread_create(&thread_, NULL, RunWatchDog, this)) { + LOGE("Could not create watch dog thread."); + status_ = OEMCrypto_ERROR_INIT_FAILED; + running_ = false; + return; + } + } + + // Function called by new worker thread in pthread_create. + static void *RunWatchDog(void *watcher) { + WatchDog* dog = reinterpret_cast(watcher); + dog->DoInit(); + dog->SignalDoneAndCleanUp(); + return NULL; + } + + // Called by worker thread. + void DoInit() { + std::string base_path; + wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3, + &base_path); + status_ = Level3_Initialize(clear_cache_function, + base_path.c_str()); + } + + std::string FailureFilename() { + std::string path; + if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3, + &path)) { + LOGW("WatchDog::FailureFilename: Unable to get base path"); + return "/data/l3_failure_file"; + } + path += "l3_failure_file"; + return path; + } + + // Check to see if the failure file was created before that last abort. + void CheckForPreviousFailure(wvcdm::metrics::CryptoMetrics* metrics) { + wvcdm::FileSystem file_system; + std::string filename = FailureFilename(); + if (!file_system.Exists(filename)) return; + wvcdm::File* file = file_system.Open(filename, file_system.kReadOnly); + if (file) { + uint32_t flag = 0; + ssize_t size = sizeof(flag); + ssize_t size_read = file->Read(reinterpret_cast(&flag), size); + file->Close(); + file_system.Remove(filename); + if (size == size_read && flag) { + LOGE("Previous L3 Init failed."); + if (metrics == nullptr) return; + M_RECORD( + metrics, + oemcrypto_initialization_mode_, + NO_TIME, + wvcdm::metrics::OEMCrypto_INITIALIZED_L3_INITIALIZATION_FAILED); + } + } + } + + // Save the failure file before we abort. + void SaveFailureInformation() { + wvcdm::FileSystem file_system; + std::string filename = FailureFilename(); + LOGD("failure filename = %s", filename.c_str()); + wvcdm::File* file = file_system.Open( + filename, file_system.kCreate | file_system.kTruncate); + if (!file) { + LOGE("Could not create file %s", filename.c_str()); + return; + } + uint32_t flag = 0x6261640a; // bad + ssize_t size = sizeof(flag); + ssize_t size_written = file->Write(reinterpret_cast(&flag), size); + file->Close(); + if (size != size_written) { + LOGE("Wrote %d bytes, not %d, to file %s", size_written, size, + filename.c_str()); + } else { + LOGE("I wrote %d to %s", size_written, filename.c_str()); + } + } + + // Called by worker thread after DoInit has finshed. + void SignalDoneAndCleanUp() { + pthread_mutex_lock(&mutex_); + running_ = false; + pthread_cond_signal(&condition_); + // If the main thread gave up, it won't delete this, so we must. + bool should_delete = gave_up_; + pthread_mutex_unlock(&mutex_); + // https://isocpp.org/wiki/faq/freestore-mgmt#delete-this + if (should_delete) delete this; + } + + // Called by main thread to wait for worker thread. + OEMCryptoResult WaitForStatusAndCleanUp() { + pthread_mutex_lock(&mutex_); + struct timespec time_to_giveup; + clock_gettime(CLOCK_REALTIME, &time_to_giveup); + time_to_giveup.tv_sec += 5; // wait 5 seconds. + if (running_) { + pthread_cond_timedwait(&condition_, &mutex_, &time_to_giveup); + } + if (running_) { + gave_up_ = true; + status_ = OEMCrypto_ERROR_INIT_FAILED; + LOGE("XXX WATCH DOG ERROR XXX"); + SaveFailureInformation(); + // This is controversial. The argument for an abort here is that if we + // do not abort, we will suck all the life out of the user's battery. By + // saving information to the file system, above, we can still track + // metrics. + abort(); + } + // If we gave up waiting for init thread, we should not delete the mutex + // out from under it. + bool should_delete = !gave_up_; + OEMCryptoResult status = status_; + pthread_mutex_unlock(&mutex_); + if (should_delete) delete this; + return status; + } + + OEMCryptoResult status() { return status_; } + + private: + OEMCryptoResult status_; + pthread_t thread_; + pthread_mutex_t mutex_; + pthread_cond_t condition_; + bool running_; + bool gave_up_; +}; + struct LevelSession { FunctionPointers* fcn; OEMCrypto_SESSION session; @@ -423,17 +580,20 @@ class Adapter { * To avoid changing the function signature and function contract - declare * a one-off metrics group to collect detailed information about how * oemcrypto was intialized. + * + * TODO(blueeyes): Refactor this to allow Initialize to provide the + * details to the caller or to use the metrics instance provided by + * the caller. */ - wvcdm::metrics::MetricsGroup metrics; + wvcdm::metrics::CryptoMetrics metrics; level1_ = FunctionPointers(); // start with all null pointers. level3_ = FunctionPointers(); // start with all null pointers. LoadLevel3(); - std::string base_path; - wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3, - &base_path); - OEMCryptoResult result = Level3_Initialize(clear_cache_function, - base_path.c_str()); + WatchDog *watcher = new WatchDog(); + watcher->CheckForPreviousFailure(&metrics); + watcher->StartThread(); + OEMCryptoResult result = watcher->WaitForStatusAndCleanUp(); if (Level3_IsInApp()) { M_RECORD( &metrics, @@ -472,7 +632,7 @@ class Adapter { wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_L1_OPEN_FAILED); return result; } - if (LoadLevel1(metrics)) { + if (LoadLevel1(&metrics)) { LOGD("OEMCrypto_Initialize Level 1 success. I will use level 1."); } else { level1_ = FunctionPointers(); // revert to all null pointers. @@ -483,7 +643,10 @@ class Adapter { return result; } - bool LoadLevel1(wvcdm::metrics::MetricsGroup& metrics) { + bool LoadLevel1(wvcdm::metrics::CryptoMetrics* metrics) { + if (metrics == nullptr) { + return false; + } level1_valid_ = true; const uint32_t kMinimumVersion = 8; const uint32_t kMaximumVersion = 13; @@ -493,7 +656,7 @@ class Adapter { LOOKUP_ALL(8, Terminate, OEMCrypto_Terminate); if (!level1_valid_) { M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_INVALID_L1); @@ -503,7 +666,7 @@ class Adapter { if (st != OEMCrypto_SUCCESS) { LOGW("Could not initialize L1. Falling Back to L3."); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INITIALIZE_L1); @@ -511,7 +674,7 @@ class Adapter { } level1_.version = level1_.APIVersion(); M_RECORD( - &metrics, + metrics, oemcrypto_l1_api_version_, NO_TIME, level1_.version, @@ -520,7 +683,7 @@ class Adapter { LOGW("liboemcrypto.so is version %d, not %d. Falling Back to L3.", level1_.version, kMinimumVersion); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_WRONG_L1_VERSION); @@ -598,7 +761,7 @@ class Adapter { // If we have a valid keybox, initialization is done. We're good. if (OEMCrypto_SUCCESS == level1_.IsKeyboxValid()) { M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_KEYBOX); @@ -610,7 +773,7 @@ class Adapter { if (level1_.version > 11 && (level1_.GetProvisioningMethod() == OEMCrypto_OEMCertificate)) { M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0); @@ -630,13 +793,13 @@ class Adapter { LOGE("OEMCrypto uses cert as identification, but cdm does not!"); LOGE("This will not work on a production device."); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_CERTIFICATE_MIX); } else { M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_CERTIFICATE); @@ -649,7 +812,7 @@ class Adapter { LOGW("Bad Level 1 Keybox. Falling Back to L3."); level1_.Terminate(); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_BAD_KEYBOX); @@ -661,7 +824,7 @@ class Adapter { LOGW("Could not open %s. Falling Back to L3.", filename.c_str()); level1_.Terminate(); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX); @@ -675,7 +838,7 @@ class Adapter { filename.c_str()); level1_.Terminate(); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INSTALL_KEYBOX); @@ -683,7 +846,7 @@ class Adapter { } LOGI("Installed keybox from %s", filename.c_str()); M_RECORD( - &metrics, + metrics, oemcrypto_initialization_mode_, NO_TIME, wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_INSTALLED_KEYBOX); @@ -1156,18 +1319,26 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys( } else { if (pair.fcn->LoadKeys_V9_or_V10 == NULL) return OEMCrypto_ERROR_NOT_IMPLEMENTED; - return pair.fcn->LoadKeys_V9_or_V10(pair.session, message, message_length, - signature, signature_length, - enc_mac_key_iv, enc_mac_key, num_keys, - &key_array_v10[0], pst, pst_length); + OEMCryptoResult result = pair.fcn->LoadKeys_V9_or_V10( + pair.session, message, message_length, signature, signature_length, + enc_mac_key_iv, enc_mac_key, num_keys, &key_array_v10[0], pst, + pst_length); + // Convert a vendor specific error, to make it actionable + if (result == kOemCryptoResultVendorSpecificError1) + result = OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE; + return result; } } else { if (pair.fcn->version < 13) { if (pair.fcn->LoadKeys_V11_or_V12 == NULL) return OEMCrypto_ERROR_NOT_IMPLEMENTED; - return pair.fcn->LoadKeys_V11_or_V12( + OEMCryptoResult result = pair.fcn->LoadKeys_V11_or_V12( pair.session, message, message_length, signature, signature_length, enc_mac_key_iv, enc_mac_key, num_keys, key_array, pst, pst_length); + // Convert a vendor specific error, to make it actionable + if (result == kOemCryptoResultVendorSpecificError1) + result = OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE; + return result; } else { if (pair.fcn->LoadKeys == NULL) return OEMCrypto_ERROR_NOT_IMPLEMENTED; return pair.fcn->LoadKeys(pair.session, message, message_length, diff --git a/libwvdrmengine/cdm/core/src/privacy_crypto_openssl.cpp b/libwvdrmengine/cdm/core/src/privacy_crypto_openssl.cpp index d5d85df5..d68f53aa 100644 --- a/libwvdrmengine/cdm/core/src/privacy_crypto_openssl.cpp +++ b/libwvdrmengine/cdm/core/src/privacy_crypto_openssl.cpp @@ -94,6 +94,7 @@ bool AesCbcKey::Encrypt(const std::string& in, std::string* out, reinterpret_cast(&(*iv)[0])) == 0) { LOGE("AesCbcKey::Encrypt: AES CBC setup failure: %s", ERR_error_string(ERR_get_error(), NULL)); + EVP_CIPHER_CTX_cleanup(&ctx); return false; } @@ -105,6 +106,7 @@ bool AesCbcKey::Encrypt(const std::string& in, std::string* out, in.size()) == 0) { LOGE("AesCbcKey::Encrypt: encryption failure: %s", ERR_error_string(ERR_get_error(), NULL)); + EVP_CIPHER_CTX_cleanup(&ctx); return false; } @@ -113,8 +115,10 @@ bool AesCbcKey::Encrypt(const std::string& in, std::string* out, &padding) == 0) { LOGE("AesCbcKey::Encrypt: PKCS7 padding failure: %s", ERR_error_string(ERR_get_error(), NULL)); + EVP_CIPHER_CTX_cleanup(&ctx); return false; } + EVP_CIPHER_CTX_cleanup(&ctx); out->resize(out_length + padding); return true; @@ -178,6 +182,7 @@ bool RsaPublicKey::Encrypt(const std::string& clear_message, return false; } + FreeKey(key); return true; } @@ -256,10 +261,15 @@ bool RsaPublicKey::VerifySignature(const std::string& message, return false; } EVP_PKEY *pkey = EVP_PKEY_new(); - if (pkey == NULL || - EVP_PKEY_set1_RSA(pkey, rsa_key) != 1) { + if (pkey == NULL) { + LOGE("RsaPublicKey::VerifySignature: EVP_PKEY allocation failed"); FreeKey(rsa_key); + return false; + } + if (EVP_PKEY_set1_RSA(pkey, rsa_key) != 1) { LOGE("RsaPublicKey::VerifySignature: failed to wrap key in an EVP_PKEY"); + FreeKey(rsa_key); + EVP_PKEY_free(pkey); return false; } FreeKey(rsa_key); diff --git a/libwvdrmengine/cdm/core/src/usage_table_header.cpp b/libwvdrmengine/cdm/core/src/usage_table_header.cpp index 8a82244c..2b7d38d1 100644 --- a/libwvdrmengine/cdm/core/src/usage_table_header.cpp +++ b/libwvdrmengine/cdm/core/src/usage_table_header.cpp @@ -5,7 +5,6 @@ #include "crypto_session.h" #include "license.h" #include "log.h" -#include "metrics_group.h" namespace { std::string kEmptyString; @@ -139,7 +138,7 @@ CdmResponseType UsageTableHeader::UpdateEntry(CryptoSession* crypto_session, CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number, DeviceFiles* handle, - metrics::MetricsGroup* metrics) { + metrics::CryptoMetrics* metrics) { LOGV("UsageTableHeader::DeleteEntry: Lock"); AutoLock auto_lock(usage_table_header_lock_); if (usage_entry_number >= usage_entry_info_.size()) @@ -188,14 +187,13 @@ CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number, number_of_entries_to_be_deleted = usage_entry_info_.size() - swap_entry_number; } - return Shrink(metrics, number_of_entries_to_be_deleted); } CdmResponseType UsageTableHeader::MoveEntry( uint32_t from_usage_entry_number, const CdmUsageEntry& from_usage_entry, uint32_t to_usage_entry_number, DeviceFiles* handle, - metrics::MetricsGroup* metrics) { + metrics::CryptoMetrics* metrics) { LOGV("UsageTableHeader::MoveEntry"); // crypto_session points to an object whose scope is this method or a test @@ -372,7 +370,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number, } CdmResponseType UsageTableHeader::Shrink( - metrics::MetricsGroup* metrics, + metrics::CryptoMetrics* metrics, uint32_t number_of_usage_entries_to_delete) { if (usage_entry_info_.empty()) { LOGE("UsageTableHeader::Shrink: usage entry info table unexpectedly empty"); @@ -413,14 +411,14 @@ CdmResponseType UsageTableHeader::Shrink( } CdmResponseType UsageTableHeader::UpgradeFromUsageTable( - DeviceFiles* handle, metrics::MetricsGroup* metrics) { + DeviceFiles* handle, metrics::CryptoMetrics* metrics) { UpgradeLicensesFromUsageTable(handle, metrics); UpgradeUsageInfoFromUsageTable(handle, metrics); return NO_ERROR; } bool UsageTableHeader::UpgradeLicensesFromUsageTable( - DeviceFiles* handle, metrics::MetricsGroup* metrics) { + DeviceFiles* handle, metrics::CryptoMetrics* metrics) { // Fetch the key set IDs for each offline license. For each license // * retrieve the provider session token, // * create a new usage entry @@ -509,7 +507,7 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable( } bool UsageTableHeader::UpgradeUsageInfoFromUsageTable( - DeviceFiles* handle, metrics::MetricsGroup* metrics) { + DeviceFiles* handle, metrics::CryptoMetrics* metrics) { // Fetch all usage files. For each file retrieve all the usage info records // within the file. For each piece of usage information // * create a new usage entry diff --git a/libwvdrmengine/cdm/core/test/cdm_engine_test.cpp b/libwvdrmengine/cdm/core/test/cdm_engine_test.cpp index 3cb5342e..cc1d84c4 100644 --- a/libwvdrmengine/cdm/core/test/cdm_engine_test.cpp +++ b/libwvdrmengine/cdm/core/test/cdm_engine_test.cpp @@ -12,6 +12,7 @@ #include "cdm_engine.h" #include "config_test_env.h" #include "initialization_data.h" +#include "file_store.h" #include "license_request.h" #include "log.h" #include "OEMCryptoCENC.h" @@ -118,6 +119,10 @@ class WvCdmEnginePreProvTest : public testing::Test { virtual ~WvCdmEnginePreProvTest() {} virtual void SetUp() { + session_opened_ = false; + } + + virtual void OpenSession() { CdmResponseType status = cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_); if (status == NEED_PROVISIONING) { @@ -129,6 +134,12 @@ class WvCdmEnginePreProvTest : public testing::Test { } virtual void TearDown() { + if (cdm_engine_.IsProvisioned(kSecurityLevelL1)) { + cdm_engine_.Unprovision(kSecurityLevelL1); + } + if (cdm_engine_.IsProvisioned(kSecurityLevelL3)) { + cdm_engine_.Unprovision(kSecurityLevelL3); + } if (session_opened_) { cdm_engine_.CloseSession(session_id_); session_opened_ = false; diff --git a/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp b/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp index 4bd48ca6..da1e540f 100644 --- a/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp @@ -144,8 +144,7 @@ using ::testing::StrEq; class CdmSessionTest : public ::testing::Test { protected: virtual void SetUp() { - service_cert_ = new ServiceCertificate; - cdm_session_.reset(new CdmSession(NULL)); + cdm_session_.reset(new CdmSession(NULL, &metrics_)); // Inject testing mocks. license_parser_ = new MockCdmLicense(cdm_session_->session_id()); cdm_session_->set_license_parser(license_parser_); @@ -157,12 +156,18 @@ class CdmSessionTest : public ::testing::Test { cdm_session_->set_file_handle(file_handle_); } + virtual void TearDown() { + // Force the cdm_session_ to be deleted. This enforces a requirement that + // the CDM session metrics exist at least as long as the CDM session. + cdm_session_.reset(); + } + + metrics::SessionMetrics metrics_; scoped_ptr cdm_session_; MockCdmLicense* license_parser_; MockCryptoSession* crypto_session_; MockPolicyEngine* policy_engine_; MockDeviceFiles* file_handle_; - ServiceCertificate* service_cert_; }; TEST_F(CdmSessionTest, InitWithBuiltInCertificate) { diff --git a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp index 0957a560..1fe4632b 100644 --- a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp @@ -2780,7 +2780,7 @@ TEST_P(DeviceFilesUsageInfoTest, RetrieveByProviderSessionToken) { std::string path = device_base_path_ + file_name; size_t max_index_by_app_id = 0; - for (size_t i = 0; i <= sizeof(kUsageInfoTestData) / sizeof(UsageInfo); ++i) { + for (size_t i = 0; i < sizeof(kUsageInfoTestData) / sizeof(UsageInfo); ++i) { if (app_id == kUsageInfoTestData[i].app_id) max_index_by_app_id = i; } std::string file_data = @@ -2840,7 +2840,7 @@ TEST_P(DeviceFilesUsageInfoTest, UpdateUsageInfo) { std::vector usage_data_fields; size_t max_index_by_app_id = 0; - for (size_t i = 0; i <= sizeof(kUsageInfoTestData) / sizeof(UsageInfo); ++i) { + for (size_t i = 0; i < sizeof(kUsageInfoTestData) / sizeof(UsageInfo); ++i) { if (app_id == kUsageInfoTestData[i].app_id) { max_index_by_app_id = i; diff --git a/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp b/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp index dad28238..270a5570 100644 --- a/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include "cdm_engine.h" @@ -15,6 +16,7 @@ #include "log.h" #include "oec_session_util.h" #include "../../oemcrypto/mock/src/oemcrypto_key_mock.h" +#include "properties.h" #include "string_conversions.h" #include "url_request.h" #include "wv_cdm_constants.h" @@ -81,22 +83,21 @@ class WvGenericOperationsTest : public testing::Test { virtual void SetUp() { ::testing::Test::SetUp(); - ConfigTestEnv config(kContentProtectionStagingPlusProv30); + ConfigTestEnv config(kContentProtectionStagingLicense); + Properties::set_provisioning_messages_are_binary(false); g_provisioning_service_certificate.assign( config.provisioning_service_certificate()); g_license_service_certificate.assign(config.license_service_certificate()); g_provisioning_server.assign(config.provisioning_server()); - cdm_engine_ = NULL; - // TODO(fredgc or gmorgan): This should be updated for provisioning 3.0 // Load test keybox. This keybox will be used by any CryptoSession // created by the CDM under test. ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestKeybox()); // Perform CdmEngine setup - cdm_engine_ = new CdmEngine(&file_system_); + cdm_engine_.reset(new CdmEngine(&file_system_)); Provision(); @@ -124,7 +125,7 @@ class WvGenericOperationsTest : public testing::Test { virtual void TearDown() { oec_util_session_.close(); - if (cdm_engine_ != NULL) { + if (cdm_engine_.get() != NULL) { cdm_engine_->CloseSession(session_id_); } // OEMCrypto_Terminate() will be performed during the test class's @@ -246,25 +247,12 @@ class WvGenericOperationsTest : public testing::Test { LOGV("WvCdmEnginePreProvTest::Provision: http_message: \n%s\n", http_message.c_str()); - // extract provisioning response from received message - // Extracts signed response from JSON string, decodes base64 signed response - const std::string kMessageStart = "\"signedResponse\": \""; - const std::string kMessageEnd = "\""; - std::string base64_response; - EXPECT_TRUE (ExtractSignedMessage(http_message, kMessageStart, kMessageEnd, - &base64_response)) << - "Failed to extract signed serialized response from JSON response"; - - LOGV("WvCdmEnginePreProvTest::Provision: extracted response " - "message: \n%s\n", base64_response.c_str()); - ASSERT_EQ(NO_ERROR, - cdm_engine_->HandleProvisioningResponse(base64_response, + cdm_engine_->HandleProvisioningResponse(http_message, &cert, &wrapped_key)); ASSERT_EQ(NO_ERROR, - cdm_engine_->SetServiceCertificate( - g_license_service_certificate)); + cdm_engine_->SetServiceCertificate(g_license_service_certificate)); } // This CryptoSession object handles Initialization and Termination @@ -274,7 +262,7 @@ class WvGenericOperationsTest : public testing::Test { CryptoSession crypto_session_; FileSystem file_system_; - CdmEngine* cdm_engine_; + std::unique_ptr cdm_engine_; std::string key_msg_; std::string session_id_; std::string server_url_; diff --git a/libwvdrmengine/cdm/core/test/policy_engine_constraints_unittest.cpp b/libwvdrmengine/cdm/core/test/policy_engine_constraints_unittest.cpp index a3b7dd95..399effda 100644 --- a/libwvdrmengine/cdm/core/test/policy_engine_constraints_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/policy_engine_constraints_unittest.cpp @@ -81,7 +81,6 @@ class MockCdmEventListener : public WvCdmEventListener { class PolicyEngineConstraintsTest : public Test { protected: virtual void SetUp() { - mock_clock_ = new NiceMock(); current_time_ = 0; policy_engine_.reset(new PolicyEngine(kSessionId, &mock_event_listener_, diff --git a/libwvdrmengine/cdm/core/test/service_certificate_unittest.cpp b/libwvdrmengine/cdm/core/test/service_certificate_unittest.cpp index bd83b812..2b1649a9 100644 --- a/libwvdrmengine/cdm/core/test/service_certificate_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/service_certificate_unittest.cpp @@ -4,7 +4,6 @@ #include #include #include -#include "crypto_session.h" #include "properties.h" #include "string_conversions.h" #include "wv_cdm_constants.h" @@ -42,26 +41,9 @@ const std::string kTestSignedCertificate = a2bs_hex( } // unnamed namespace -class MockCryptoSession : public CryptoSession { - public: - MockCryptoSession() : CryptoSession(NULL) { } - MOCK_METHOD2(GetRandom, bool(size_t, uint8_t*)); -}; - class ServiceCertificateTest : public ::testing::Test { protected: - virtual void SetUp() { crypto_session_ = new MockCryptoSession(); } - - virtual void TearDown() { - if (crypto_session_) delete crypto_session_; - } - - void CreateServiceCertificate() { - service_certificate_ = new ServiceCertificate(); - } - - ServiceCertificate* service_certificate_; - MockCryptoSession* crypto_session_; + ServiceCertificate service_certificate_; }; class StubCdmClientPropertySet : public CdmClientPropertySet { @@ -78,11 +60,11 @@ class StubCdmClientPropertySet : public CdmClientPropertySet { virtual bool use_privacy_mode() const { return use_privacy_mode_; } virtual const std::string& service_certificate() const { - return service_certificate_; + return raw_service_certificate_; } virtual void set_service_certificate(const std::string& cert) { - service_certificate_ = cert; + raw_service_certificate_ = cert; } virtual bool is_session_sharing_enabled() const { @@ -99,7 +81,7 @@ class StubCdmClientPropertySet : public CdmClientPropertySet { private: std::string security_level_; - std::string service_certificate_; + std::string raw_service_certificate_; bool use_privacy_mode_; bool is_session_sharing_enabled_; uint32_t session_sharing_id_; @@ -107,11 +89,8 @@ class StubCdmClientPropertySet : public CdmClientPropertySet { }; TEST_F(ServiceCertificateTest, InitSuccess) { - MockCryptoSession crypto_session; - - CreateServiceCertificate(); - service_certificate_->Init(kTestSessionId1); - EXPECT_FALSE(service_certificate_->has_certificate()); + service_certificate_.Init(kTestSessionId1); + EXPECT_FALSE(service_certificate_.has_certificate()); } TEST_F(ServiceCertificateTest, InitPrivacyModeRequired) { @@ -122,9 +101,8 @@ TEST_F(ServiceCertificateTest, InitPrivacyModeRequired) { Properties::Init(); Properties::AddSessionPropertySet(kTestSessionId1, &property_set); - CreateServiceCertificate(); - service_certificate_->Init(kTestSessionId1); - EXPECT_FALSE(service_certificate_->has_certificate()); + service_certificate_.Init(kTestSessionId1); + EXPECT_FALSE(service_certificate_.has_certificate()); } TEST_F(ServiceCertificateTest, InitServiceCertificatePresent) { @@ -136,13 +114,12 @@ TEST_F(ServiceCertificateTest, InitServiceCertificatePresent) { Properties::Init(); Properties::AddSessionPropertySet(kTestSessionId1, &property_set); - CreateServiceCertificate(); - std::string service_certificate; + std::string raw_service_certificate; EXPECT_TRUE(Properties::GetServiceCertificate(kTestSessionId1, - &service_certificate)); + &raw_service_certificate)); EXPECT_EQ(NO_ERROR, - service_certificate_->Init(service_certificate)); - EXPECT_TRUE(service_certificate_->has_certificate()); + service_certificate_.Init(raw_service_certificate)); + EXPECT_TRUE(service_certificate_.has_certificate()); } TEST_F(ServiceCertificateTest, SetServiceCertificate) { @@ -153,9 +130,8 @@ TEST_F(ServiceCertificateTest, SetServiceCertificate) { Properties::Init(); Properties::AddSessionPropertySet(kTestSessionId1, &property_set); - CreateServiceCertificate(); - EXPECT_EQ(NO_ERROR, service_certificate_->Init(kTestSignedCertificate)); - EXPECT_TRUE(service_certificate_->has_certificate()); + EXPECT_EQ(NO_ERROR, service_certificate_.Init(kTestSignedCertificate)); + EXPECT_TRUE(service_certificate_.has_certificate()); } } diff --git a/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp b/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp index 493992d7..6e7a545a 100644 --- a/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp @@ -395,7 +395,7 @@ TEST_F(UsageTableHeaderTest, UpdateEntry) { TEST_F(UsageTableHeaderTest, DeleteEntry_InvalidUsageEntryNumber) { Init(kSecurityLevelL1, kUsageTableHeader, kUsageEntryInfoVector); uint32_t usage_entry_number = kUsageEntryInfoVector.size(); - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_NE(NO_ERROR, usage_table_header_->DeleteEntry( usage_entry_number, device_files_, &metrics)); @@ -426,7 +426,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_CryptoSessionError) { Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -462,7 +462,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastOfflineEntry) { Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -507,7 +507,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntry) { Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop2 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -558,7 +558,7 @@ TEST_F(UsageTableHeaderTest, Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; device_files_->DeleteAllLicenses(); EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); @@ -608,7 +608,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntriesAreMissing) { Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -671,7 +671,7 @@ TEST_F(UsageTableHeaderTest, Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_TRUE(device_files_->StoreLicense( usage_entry_info_vector[usage_entry_info_vector.size() - 1].key_set_id, @@ -739,7 +739,7 @@ TEST_F(UsageTableHeaderTest, usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1 uint32_t usage_entry_number_after_deleted_entry = usage_entry_number_to_be_deleted + 1; - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -812,7 +812,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreStorageTypeUnknown) { Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); uint32_t usage_entry_number_to_be_deleted = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL( @@ -867,7 +867,7 @@ TEST_F(UsageTableHeaderTest, usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1 uint32_t last_usage_entry_number = usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_TRUE(device_files_->StoreLicense( usage_entry_info_vector[last_usage_entry_number].key_set_id, @@ -933,7 +933,7 @@ TEST_F(UsageTableHeaderTest, usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1 uint32_t last_usage_entry_number = usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); EXPECT_CALL(*crypto_session_, @@ -1007,7 +1007,7 @@ TEST_F(UsageTableHeaderTest, usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1 uint32_t last_valid_usage_entry_number = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_TRUE(device_files_->StoreLicense( usage_entry_info_vector[last_valid_usage_entry_number].key_set_id, @@ -1085,7 +1085,7 @@ TEST_F(UsageTableHeaderTest, usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1 uint32_t last_valid_usage_entry_number = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)) .Times(2) @@ -1157,7 +1157,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsOffline) { usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1 uint32_t last_usage_entry_number = usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_TRUE(device_files_->StoreLicense( usage_entry_info_vector[last_usage_entry_number].key_set_id, @@ -1271,7 +1271,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsSecureStop) { usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1 uint32_t last_usage_entry_number = usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)) .Times(2) @@ -1371,7 +1371,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreOfflineAndUnknknown) { usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1 uint32_t last_valid_usage_entry_number = usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_TRUE(device_files_->StoreLicense( usage_entry_info_vector[last_valid_usage_entry_number].key_set_id, @@ -1490,7 +1490,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreSecureStopAndUnknknown) { usage_entry_info_vector.size() - 5; // kUsageEntryInfoSecureStop1 uint32_t last_valid_usage_entry_number = usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop3 - metrics::MetricsGroup metrics; + metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, Open(kLevelDefault)) .Times(2) diff --git a/libwvdrmengine/cdm/include/ami_adapter.h b/libwvdrmengine/cdm/include/ami_adapter.h index 75999233..42bc4b1f 100644 --- a/libwvdrmengine/cdm/include/ami_adapter.h +++ b/libwvdrmengine/cdm/include/ami_adapter.h @@ -4,22 +4,19 @@ #define CDM_AMI_ADAPTER_H_ #include +#include #include -#include "report.h" - namespace wvcdm { -class AmiAdapter : public metrics::Report { +class AmiAdapter { public: AmiAdapter(); AmiAdapter(int64_t parent); ~AmiAdapter(); - metrics::Report* NewReport() const; - void UpdateString(const std::string& metric_id, const std::string& value); void UpdateInt32(const std::string& metric_id, int32_t value); void UpdateInt64(const std::string& metric_id, int64_t value); diff --git a/libwvdrmengine/cdm/include/wv_content_decryption_module.h b/libwvdrmengine/cdm/include/wv_content_decryption_module.h index 35cb0042..dcf8797a 100644 --- a/libwvdrmengine/cdm/include/wv_content_decryption_module.h +++ b/libwvdrmengine/cdm/include/wv_content_decryption_module.h @@ -11,7 +11,6 @@ #include "cdm_identifier.h" #include "file_store.h" #include "lock.h" -#include "metrics_front_end.h" #include "timer.h" #include "wv_cdm_types.h" @@ -126,6 +125,9 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler { // Validate a passed-in service certificate virtual bool IsValidServiceCertificate(const std::string& certificate); + // Retrieve the serialized metrics from the CDM. + virtual void GetSerializedMetrics(std::string* serialized_metrics); + private: struct CdmInfo { CdmInfo(); @@ -160,9 +162,6 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler { // This contains weak pointers to the CDM instances contained in |cdms_|. std::map cdm_by_session_id_; - metrics::Report* report_root_; - metrics::MetricsFrontEnd* front_end_; - CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule); }; diff --git a/libwvdrmengine/cdm/metrics/include/event_metric.h b/libwvdrmengine/cdm/metrics/include/event_metric.h index f9179b64..4e81ad62 100644 --- a/libwvdrmengine/cdm/metrics/include/event_metric.h +++ b/libwvdrmengine/cdm/metrics/include/event_metric.h @@ -18,7 +18,7 @@ #include "lock.h" #include "distribution.h" -#include "metric_publisher.h" +#include "metric_serialization.h" namespace wvcdm { namespace metrics { @@ -27,11 +27,11 @@ class EventMetricTest; // This base class provides the common defintion used by all templated // instances of EventMetric. -class BaseEventMetric : public MetricPublisher { +class BaseEventMetric : public MetricSerializable { public: - // Publish metric values to the MetricNotification. |subscriber| must + // Send metric values to the MetricSerializer. |serializer| must // not be null and is owned by the caller. - virtual void Publish(MetricNotification* subscriber); + virtual void Serialize(MetricSerializer* serializer); protected: // Instantiates a BaseEventMetric. @@ -238,20 +238,57 @@ inline void AppendFieldNames(std::vector* field_name_vector, va_end(field_names); } +// These helper methods and FirstUnusedType assure that there is no mismatch +// between the specified types for EventMetrics and the constructors and +// methods used for the specializations. +template +struct CompileAssert {}; +#define COMPILE_ASSERT(expr, msg) \ + typedef impl::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] + +template struct is_unused { static const bool value = false; }; +template <> struct is_unused { static const bool value = true; }; + +template +class FirstUnusedType { + static const bool a = is_unused::value; + static const bool b = is_unused::value; + static const bool c = is_unused::value; + static const bool d = is_unused::value; + // Check that all types after the first Unused are also Unused. + COMPILE_ASSERT(a <= b, Invalid_Unused_At_Position_2); + COMPILE_ASSERT(b <= c, Invalid_Unused_At_Position_3); + COMPILE_ASSERT(c <= d, Invalid_Unused_At_Position_4); + + public: + static const int value = 5 - (a + b + c + d); +}; + +// Asserts that no Unused types exist before N; after N, are all Unused types. +#define ASSERT_METRIC_UNUSED_START_FROM(N) \ + COMPILE_ASSERT((\ + impl::FirstUnusedType::value) == N, \ + Unused_Start_From_##N) + } // namespace impl // Overloaded template constructor implementations for EventMetric. template EventMetric::EventMetric( const std::string& metric_name) - : BaseEventMetric(metric_name) {} + : BaseEventMetric(metric_name) { + ASSERT_METRIC_UNUSED_START_FROM(1); +} template EventMetric::EventMetric( const std::string& metric_name, const char* field_name) : BaseEventMetric(metric_name) { - impl::AppendFieldNames(&field_names_, 1, field_name); + ASSERT_METRIC_UNUSED_START_FROM(2); + impl::AppendFieldNames(&field_names_, + impl::FirstUnusedType::value - 1, + field_name); } template EventMetric::EventMetric( @@ -259,7 +296,10 @@ EventMetric::EventMetric( const char* field_name1, const char* field_name2) : BaseEventMetric(metric_name) { - impl::AppendFieldNames(&field_names_, 2, field_name1, field_name2); + ASSERT_METRIC_UNUSED_START_FROM(3); + impl::AppendFieldNames(&field_names_, + impl::FirstUnusedType::value - 1, + field_name1, field_name2); } template EventMetric::EventMetric( @@ -268,8 +308,10 @@ EventMetric::EventMetric( const char* field_name2, const char* field_name3) : BaseEventMetric(metric_name) { + ASSERT_METRIC_UNUSED_START_FROM(4); impl::AppendFieldNames(&field_names_, - 3, field_name1, field_name2, field_name3); + impl::FirstUnusedType::value - 1, + field_name1, field_name2, field_name3); } template EventMetric::EventMetric( @@ -279,8 +321,10 @@ EventMetric::EventMetric( const char* field_name3, const char* field_name4) : BaseEventMetric(metric_name) { + ASSERT_METRIC_UNUSED_START_FROM(5); impl::AppendFieldNames(&field_names_, - 4, field_name1, field_name2, + impl::FirstUnusedType::value - 1, + field_name1, field_name2, field_name3, field_name4); } diff --git a/libwvdrmengine/cdm/metrics/include/metrics_collections.h b/libwvdrmengine/cdm/metrics/include/metrics_collections.h index f047c1fa..ae4cdc85 100644 --- a/libwvdrmengine/cdm/metrics/include/metrics_collections.h +++ b/libwvdrmengine/cdm/metrics/include/metrics_collections.h @@ -10,11 +10,9 @@ #include #include -#include "counter_metric.h" #include "event_metric.h" #include "metrics.pb.h" #include "OEMCryptoCENC.h" -#include "value_metric.h" #include "wv_cdm_types.h" // This definition indicates that a given metric does not need timing @@ -88,64 +86,70 @@ class CryptoMetrics { void Serialize(drm_metrics::MetricsGroup* metrics); /* CRYPTO SESSION */ - // TODO(blueeyes): Convert this to crypto_session_default_security_level_. - ValueMetric crypto_session_security_level_; - CounterMetric crypto_session_delete_all_usage_reports_; - CounterMetric crypto_session_delete_multiple_usage_information_; + EventMetric crypto_session_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_; - CounterMetric crypto_session_get_device_unique_id_; - CounterMetric crypto_session_get_token_; - ValueMetric crypto_session_life_span_; + EventMetric crypto_session_get_device_unique_id_; + 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_; // This is the requested security level. - ValueMetric crypto_session_system_id_; + EventMetric crypto_session_open_; EventMetric crypto_session_update_usage_information_; - ValueMetric crypto_session_usage_information_support_; + EventMetric crypto_session_usage_information_support_; /* OEMCRYPTO */ - ValueMetric oemcrypto_api_version_; - CounterMetric oemcrypto_close_session_; - EventMetric oemcrypto_copy_buffer_; - ValueMetric oemcrypto_current_hdcp_capability_; - CounterMetric oemcrypto_deactivate_usage_entry_; + EventMetric oemcrypto_api_version_; + EventMetric oemcrypto_close_session_; + EventMetric oemcrypto_copy_buffer_; + EventMetric oemcrypto_deactivate_usage_entry_; EventMetric oemcrypto_decrypt_cenc_; - CounterMetric oemcrypto_delete_usage_entry_; - CounterMetric oemcrypto_delete_usage_table_; + EventMetric oemcrypto_delete_usage_entry_; + EventMetric oemcrypto_delete_usage_table_; EventMetric oemcrypto_derive_keys_from_session_key_; - CounterMetric oemcrypto_force_delete_usage_entry_; + EventMetric oemcrypto_force_delete_usage_entry_; EventMetric oemcrypto_generate_derived_keys_; - CounterMetric oemcrypto_generate_nonce_; + 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_; - CounterMetric oemcrypto_get_device_id_; - EventMetric oemcrypto_get_key_data_; - CounterMetric oemcrypto_get_oem_public_certificate_; - CounterMetric oemcrypto_get_random_; + 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_; - ValueMetric oemcrypto_is_anti_rollback_hw_present_; - ValueMetric oemcrypto_is_keybox_valid_; + 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_; - ValueMetric oemcrypto_max_hdcp_capability_; - ValueMetric oemcrypto_max_number_of_sessions_; - ValueMetric oemcrypto_number_of_open_sessions_; - ValueMetric oemcrypto_provisioning_method_; + EventMetric oemcrypto_load_test_keybox_; + EventMetric oemcrypto_load_test_rsa_key_; + EventMetric oemcrypto_open_session_; EventMetric oemcrypto_refresh_keys_; - CounterMetric oemcrypto_report_usage_; + EventMetric oemcrypto_report_usage_; EventMetric oemcrypto_rewrap_device_rsa_key_; EventMetric oemcrypto_rewrap_device_rsa_key_30_; - ValueMetric oemcrypto_security_patch_level_; + EventMetric oemcrypto_security_level_; + EventMetric oemcrypto_security_patch_level_; EventMetric oemcrypto_select_key_; - ValueMetric oemcrypto_supports_usage_table_; - CounterMetric oemcrypto_update_usage_table_; + EventMetric oemcrypto_supports_usage_table_; + EventMetric oemcrypto_update_usage_table_; EventMetric oemcrypto_wrap_keybox_; + + /* Internal OEMCrypto Metrics */ + EventMetric oemcrypto_initialization_mode_; + EventMetric oemcrypto_l1_api_version_; }; // This class contains session-scoped metrics. All properties and @@ -175,10 +179,10 @@ class SessionMetrics { CryptoMetrics* GetCryptoMetrics() { return &crypto_metrics_; } // Metrics collected at the session level. - ValueMetric cdm_session_life_span_; // Milliseconds. + EventMetric<> cdm_session_life_span_; EventMetric cdm_session_renew_key_; - CounterMetric cdm_session_restore_offline_session_; - CounterMetric cdm_session_restore_usage_session_; + EventMetric cdm_session_restore_offline_session_; + EventMetric cdm_session_restore_usage_session_; // Serialize the session metrics to the provided |metric_group|. // |metric_group| is owned by the caller and must not be null. @@ -191,45 +195,6 @@ class SessionMetrics { CryptoMetrics crypto_metrics_; }; -// This class contains metrics for the OEMCrypto Dynamic Adapter. They are -// separated from other metrics because they need to be encapsulated in a -// singleton object. This is because the dynamic adapter uses the OEMCrypto -// function signatures and contract and cannot be extended to inject -// dependencies. -// -// Operations for this metrics class are serialized since these particular -// metrics may be accessed by a separate thread during intialize even as -// the metric may be serialized. -class OemCryptoDynamicAdapterMetrics { - public: - explicit OemCryptoDynamicAdapterMetrics(); - - // Set methods for OEMCrypto metrics. - void SetInitializationMode(OEMCryptoInitializationMode mode); - void SetL1ApiVersion(uint32_t version); - void SetL1MinApiVersion(uint32_t version); - - // Serialize the session metrics to the provided |metric_group|. - // |metric_group| is owned by the caller and must not be null. - void Serialize(drm_metrics::MetricsGroup* metric_group); - - // Clears the existing metric values. - void Clear(); - - private: - Lock adapter_lock_; - ValueMetric oemcrypto_initialization_mode_; - ValueMetric oemcrypto_l1_api_version_; - ValueMetric oemcrypto_l1_min_api_version_; -}; - -// This will fetch the singleton instance for dynamic adapter metrics. -// This method is safe only if we use C++ 11. In C++ 11, static function-local -// initialization is guaranteed to be threadsafe. We return the reference to -// avoid non-guaranteed destructor order problems. Effectively, the destructor -// is never run for the created instance. -OemCryptoDynamicAdapterMetrics& GetDynamicAdapterMetricsInstance(); - // This class contains engine-scoped metrics. All properties and // statistics related to operations within the engine, but outside // the scope of a session are recorded here. @@ -263,39 +228,33 @@ class EngineMetrics { void Serialize(drm_metrics::MetricsGroup* metric_group, bool completed_only, bool clear_serialized_sessions); - void SetAppPackageName(const std::string& app_package_name); - // Metrics recorded at the engine level. EventMetric cdm_engine_add_key_; - ValueMetric cdm_engine_cdm_version_; - CounterMetric cdm_engine_close_session_; - ValueMetric cdm_engine_creation_time_millis_; - EventMetric cdm_engine_decrypt_; - CounterMetric cdm_engine_find_session_for_key_; + EventMetric cdm_engine_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_; - ValueMetric cdm_engine_life_span_; // Milliseconds - CounterMetric cdm_engine_open_key_set_session_; - CounterMetric cdm_engine_open_session_; + EventMetric<> cdm_engine_life_span_; + EventMetric cdm_engine_open_key_set_session_; + EventMetric cdm_engine_open_session_; EventMetric cdm_engine_query_key_status_; - CounterMetric cdm_engine_release_all_usage_info_; - CounterMetric cdm_engine_release_usage_info_; - CounterMetric cdm_engine_remove_keys_; + EventMetric cdm_engine_release_all_usage_info_; + EventMetric cdm_engine_release_usage_info_; + EventMetric cdm_engine_remove_keys_; EventMetric cdm_engine_restore_key_; - CounterMetric cdm_engine_unprovision_; + EventMetric cdm_engine_unprovision_; private: Lock session_metrics_lock_; std::vector session_metrics_list_; CryptoMetrics crypto_metrics_; - std::string app_package_name_; void SerializeEngineMetrics(drm_metrics::MetricsGroup* out); }; } // namespace metrics } // namespace wvcdm - -#endif // WVCDM_METRICS_METRICS_GROUP_H_ +#endif diff --git a/libwvdrmengine/cdm/metrics/src/event_metric.cpp b/libwvdrmengine/cdm/metrics/src/event_metric.cpp index 1f9bba5d..06e2ac51 100644 --- a/libwvdrmengine/cdm/metrics/src/event_metric.cpp +++ b/libwvdrmengine/cdm/metrics/src/event_metric.cpp @@ -32,26 +32,29 @@ void BaseEventMetric::Record(const std::string& field_names_values, distribution->Record(value); } -void BaseEventMetric::Publish(MetricNotification* notification) { +void BaseEventMetric::Serialize(MetricSerializer* serializer) { AutoLock lock(internal_lock_); for (std::map::iterator it = value_map_.begin(); it != value_map_.end(); it++) { - notification->UpdateInt64( + serializer->SetInt64( metric_name_ + "/count" + it->first, it->second->Count()); - notification->UpdateDouble( + serializer->SetDouble( metric_name_ + "/mean" + it->first, it->second->Mean()); - notification->UpdateDouble( - metric_name_ + "/variance" + it->first, - it->second->Variance()); - notification->UpdateDouble( - metric_name_ + "/min" + it->first, - it->second->Min()); - notification->UpdateDouble( - metric_name_ + "/max" + it->first, - it->second->Max()); + // Only publish additional information if there was more than one sample. + if (it->second->Count() > 1) { + serializer->SetDouble( + metric_name_ + "/variance" + it->first, + it->second->Variance()); + serializer->SetDouble( + metric_name_ + "/min" + it->first, + it->second->Min()); + serializer->SetDouble( + metric_name_ + "/max" + it->first, + it->second->Max()); + } } } diff --git a/libwvdrmengine/cdm/metrics/src/metrics.proto b/libwvdrmengine/cdm/metrics/src/metrics.proto index 02c5af24..4df1fe53 100644 --- a/libwvdrmengine/cdm/metrics/src/metrics.proto +++ b/libwvdrmengine/cdm/metrics/src/metrics.proto @@ -33,7 +33,4 @@ message MetricsGroup { // Allow multiple sub groups of metrics. repeated MetricsGroup metric_sub_group = 2; - - // Name of the application package associated with the metrics. - optional string app_package_name = 3; } diff --git a/libwvdrmengine/cdm/metrics/src/metrics_collections.cpp b/libwvdrmengine/cdm/metrics/src/metrics_collections.cpp index f7a2a291..93b35e05 100644 --- a/libwvdrmengine/cdm/metrics/src/metrics_collections.cpp +++ b/libwvdrmengine/cdm/metrics/src/metrics_collections.cpp @@ -4,7 +4,6 @@ #include -#include "log.h" #include "metrics.pb.h" using drm_metrics::MetricsGroup; @@ -63,13 +62,11 @@ namespace wvcdm { namespace metrics { CryptoMetrics::CryptoMetrics() : - crypto_session_security_level_( - "/drm/widevine/crypto_session/security_level"), crypto_session_delete_all_usage_reports_( - "/drm/widevine/crypto_session/delete_all_usage_reports", + "/drm/widevine/crypto_session/delete_all_usage_reports/time", "error"), crypto_session_delete_multiple_usage_information_( - "/drm/widevine/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", @@ -92,13 +89,20 @@ CryptoMetrics::CryptoMetrics() : "length", "signing_algorithm"), crypto_session_get_device_unique_id_( - "/drm/widevine/crypto_session/get_device_unique_id", + "/drm/widevine/crypto_session/get_device_unique_id/time", "success"), + 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", + "system_id"), crypto_session_get_token_( - "/drm/widevine/crypto_session/get_token", + "/drm/widevine/crypto_session/get_token/time", "success"), crypto_session_life_span_( - "/drm/widevine/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"), @@ -106,48 +110,48 @@ CryptoMetrics::CryptoMetrics() : "/drm/widevine/crypto_session/open/time", "error", "requested_security_level"), - crypto_session_system_id_( - "/drm/widevine/crypto_session/system_id"), crypto_session_update_usage_information_( "/drm/widevine/crypto_session/update_usage_information/time", "error"), crypto_session_usage_information_support_( - "/drm/widevine/crypto_session/usage_information_support"), + "/drm/widevine/crypto_session/usage_information_support/time", + "success"), oemcrypto_api_version_( - "/drm/widevine/oemcrypto/api_version"), + "/drm/widevine/oemcrypto/api_version/time", + "version", + "requested_security_level"), oemcrypto_close_session_( - "/drm/widevine/oemcrypto/close_session", + "/drm/widevine/oemcrypto/close_session/time", "oemcrypto_error"), oemcrypto_copy_buffer_( "/drm/widevine/oemcrypto/copy_buffer/time", "oemcrypto_error", + "requested_security_level", "length"), - oemcrypto_current_hdcp_capability_( - "/drm/widevine/oemcrypto/current_hdcp_capability"), oemcrypto_deactivate_usage_entry_( - "/drm/widevine/oemcrypto/deactivate_usage_entry", + "/drm/widevine/oemcrypto/deactivate_usage_entry/time", "oemcrypto_error"), oemcrypto_decrypt_cenc_( "/drm/widevine/oemcrypto/decrypt_cenc/time", "oemcrypto_error", "length"), oemcrypto_delete_usage_entry_( - "/drm/widevine/oemcrypto/delete_usage_entry", + "/drm/widevine/oemcrypto/delete_usage_entry/time", "oemcrypto_error"), oemcrypto_delete_usage_table_( - "/drm/widevine/oemcrypto/delete_usage_table", + "/drm/widevine/oemcrypto/delete_usage_table/time", "oemcrypto_error"), oemcrypto_derive_keys_from_session_key_( "/drm/widevine/oemcrypto/derive_keys_from_session_key/time", "oemcrypto_error"), oemcrypto_force_delete_usage_entry_( - "/drm/widevine/oemcrypto/force_delete_usage_entry", + "/drm/widevine/oemcrypto/force_delete_usage_entry/time", "oemcrypto_error"), oemcrypto_generate_derived_keys_( "/drm/widevine/oemcrypto/generate_derived_keys/time", "oemcrypto_error"), oemcrypto_generate_nonce_( - "/drm/widevine/oemcrypto/generate_nonce", + "/drm/widevine/oemcrypto/generate_nonce/time", "oemcrypto_error"), oemcrypto_generate_rsa_signature_( "/drm/widevine/oemcrypto/generate_rsa_signature/time", @@ -174,47 +178,73 @@ CryptoMetrics::CryptoMetrics() : "oemcrypto_error", "length"), oemcrypto_get_device_id_( - "/drm/widevine/oemcrypto/get_device_id", - "oemcrypto_error"), + "/drm/widevine/oemcrypto/get_device_id/time", + "oemcrypto_error", + "requested_security_level"), + oemcrypto_get_hdcp_capability_( + "/drm/widevine/oemcrypto/get_hdcp_capability/time", + "oemcrypto_error", + "requested_security_level"), oemcrypto_get_key_data_( "/drm/widevine/oemcrypto/get_key_data/time", "oemcrypto_error", - "length"), + "length", + "requested_security_level"), + oemcrypto_get_max_number_of_sessions_( + "/drm/widevine/oemcrypto/get_max_number_of_sessions/time", + "oemcrypto_error", + "requested_security_level"), + oemcrypto_get_number_of_open_sessions_( + "/drm/widevine/oemcrypto/get_number_of_open_sessions/time", + "oemcrypto_error", + "requested_security_level"), oemcrypto_get_oem_public_certificate_( - "/drm/widevine/oemcrypto/get_oem_public_certificate", + "/drm/widevine/oemcrypto/get_oem_public_certificate/time", "oemcrypto_error"), + oemcrypto_get_provisioning_method_( + "/drm/widevine/oemcrypto/get_provisioning_method/time", + "method", + "requested_security_level"), oemcrypto_get_random_( - "/drm/widevine/oemcrypto/get_random", - "oemcrypto_error"), + "/drm/widevine/oemcrypto/get_random/time", + "oemcrypto_error", + "length"), oemcrypto_initialize_( "/drm/widevine/oemcrypto/initialize/time", "oemcrypto_error"), oemcrypto_install_keybox_( "/drm/widevine/oemcrypto/install_keybox/time", - "oemcrypto_error"), + "oemcrypto_error", + "requested_security_level"), oemcrypto_is_anti_rollback_hw_present_( - "/drm/widevine/oemcrypto/is_anti_rollback_hw_present"), + "/drm/widevine/oemcrypto/is_anti_rollback_hw_present/time", + "success", + "requested_security_level"), oemcrypto_is_keybox_valid_( - "/drm/widevine/oemcrypto/is_keybox_valid"), + "/drm/widevine/oemcrypto/is_keybox_valid/time", + "oemcrypto_error", + "requested_security_level"), oemcrypto_load_device_rsa_key_( "/drm/widevine/oemcrypto/load_device_rsa_key/time", "oemcrypto_error"), oemcrypto_load_keys_( "/drm/widevine/oemcrypto/load_keys/time", "oemcrypto_error"), - oemcrypto_max_hdcp_capability_( - "/drm/widevine/oemcrypto/max_hdcp_capability"), - oemcrypto_max_number_of_sessions_( - "/drm/widevine/oemcrypto/max_number_of_sessions"), - oemcrypto_number_of_open_sessions_( - "/drm/widevine/oemcrypto/number_of_open_sessions"), - oemcrypto_provisioning_method_( - "/drm/widevine/oemcrypto/provisioning_method"), + oemcrypto_load_test_keybox_( + "/drm/widevine/oemcrypto/load_test_keybox/time", + "oemcrypto_error"), + oemcrypto_load_test_rsa_key_( + "/drm/widevine/oemcrypto/load_test_rsa_key/time", + "oemcrypto_error"), + oemcrypto_open_session_( + "/drm/widevine/oemcrypto/open_session/time", + "oemcrypto_error", + "requested_security_level"), oemcrypto_refresh_keys_( "/drm/widevine/oemcrypto/refresh_keys/time", "oemcrypto_error"), oemcrypto_report_usage_( - "/drm/widevine/oemcrypto/report_usage", + "/drm/widevine/oemcrypto/report_usage/time", "oemcrypto_error"), oemcrypto_rewrap_device_rsa_key_( "/drm/widevine/oemcrypto/rewrap_device_rsa_key/time", @@ -222,25 +252,38 @@ CryptoMetrics::CryptoMetrics() : oemcrypto_rewrap_device_rsa_key_30_( "/drm/widevine/oemcrypto/rewrap_device_rsa_key_30/time", "oemcrypto_error"), + oemcrypto_security_level_( + "/drm/widevine/oemcrypto/security_level/time", + "security_level", + "requested_security_level"), oemcrypto_security_patch_level_( - "/drm/widevine/oemcrypto/security_patch_level"), + "/drm/widevine/oemcrypto/security_patch_level/time", + "patch", + "requested_security_level"), oemcrypto_select_key_( "/drm/widevine/oemcrypto/select_key/time", "oemcrypto_error"), oemcrypto_supports_usage_table_( - "/drm/widevine/oemcrypto/supports_usage_table"), + "/drm/widevine/oemcrypto/supports_usage_table/time", + "oemcrypto_error", + "requested_security_level"), oemcrypto_update_usage_table_( - "/drm/widevine/oemcrypto/update_usage_table", + "/drm/widevine/oemcrypto/update_usage_table/time", "oemcrypto_error"), oemcrypto_wrap_keybox_( "/drm/widevine/oemcrypto/wrap_keybox/time", - "oemcrypto_error") { -} + "oemcrypto_error"), + oemcrypto_initialization_mode_( + "/drm/widevine/oemcrypto/initialization_mode", + "initialization_mode"), + oemcrypto_l1_api_version_( + "/drm/widevine/oemcrypto/l1_api_version", + "version", + "min_version") {} void CryptoMetrics::Serialize(MetricsGroup* metrics) { ProtoMetricSerializer serializer(metrics); /* CRYPTO SESSION */ - crypto_session_security_level_.Serialize(&serializer); crypto_session_delete_all_usage_reports_.Serialize(&serializer); crypto_session_delete_multiple_usage_information_.Serialize(&serializer); crypto_session_generic_decrypt_.Serialize(&serializer); @@ -248,11 +291,12 @@ void CryptoMetrics::Serialize(MetricsGroup* metrics) { crypto_session_generic_sign_.Serialize(&serializer); crypto_session_generic_verify_.Serialize(&serializer); crypto_session_get_device_unique_id_.Serialize(&serializer); + crypto_session_get_security_level_.Serialize(&serializer); + crypto_session_get_system_id_.Serialize(&serializer); crypto_session_get_token_.Serialize(&serializer); crypto_session_life_span_.Serialize(&serializer); crypto_session_load_certificate_private_key_.Serialize(&serializer); crypto_session_open_.Serialize(&serializer); - crypto_session_system_id_.Serialize(&serializer); crypto_session_update_usage_information_.Serialize(&serializer); crypto_session_usage_information_support_.Serialize(&serializer); @@ -260,7 +304,6 @@ void CryptoMetrics::Serialize(MetricsGroup* metrics) { oemcrypto_api_version_.Serialize(&serializer); oemcrypto_close_session_.Serialize(&serializer); oemcrypto_copy_buffer_.Serialize(&serializer); - oemcrypto_current_hdcp_capability_.Serialize(&serializer); oemcrypto_deactivate_usage_entry_.Serialize(&serializer); oemcrypto_decrypt_cenc_.Serialize(&serializer); oemcrypto_delete_usage_entry_.Serialize(&serializer); @@ -276,8 +319,12 @@ void CryptoMetrics::Serialize(MetricsGroup* metrics) { oemcrypto_generic_sign_.Serialize(&serializer); oemcrypto_generic_verify_.Serialize(&serializer); oemcrypto_get_device_id_.Serialize(&serializer); + oemcrypto_get_hdcp_capability_.Serialize(&serializer); oemcrypto_get_key_data_.Serialize(&serializer); + oemcrypto_get_max_number_of_sessions_.Serialize(&serializer); + oemcrypto_get_number_of_open_sessions_.Serialize(&serializer); oemcrypto_get_oem_public_certificate_.Serialize(&serializer); + oemcrypto_get_provisioning_method_.Serialize(&serializer); oemcrypto_get_random_.Serialize(&serializer); oemcrypto_initialize_.Serialize(&serializer); oemcrypto_install_keybox_.Serialize(&serializer); @@ -285,32 +332,36 @@ void CryptoMetrics::Serialize(MetricsGroup* metrics) { oemcrypto_is_keybox_valid_.Serialize(&serializer); oemcrypto_load_device_rsa_key_.Serialize(&serializer); oemcrypto_load_keys_.Serialize(&serializer); - oemcrypto_max_hdcp_capability_.Serialize(&serializer); - oemcrypto_max_number_of_sessions_.Serialize(&serializer); - oemcrypto_number_of_open_sessions_.Serialize(&serializer); - oemcrypto_provisioning_method_.Serialize(&serializer); + oemcrypto_load_test_keybox_.Serialize(&serializer); + oemcrypto_load_test_rsa_key_.Serialize(&serializer); + oemcrypto_open_session_.Serialize(&serializer); oemcrypto_refresh_keys_.Serialize(&serializer); oemcrypto_report_usage_.Serialize(&serializer); oemcrypto_rewrap_device_rsa_key_.Serialize(&serializer); oemcrypto_rewrap_device_rsa_key_30_.Serialize(&serializer); + oemcrypto_security_level_.Serialize(&serializer); oemcrypto_security_patch_level_.Serialize(&serializer); oemcrypto_select_key_.Serialize(&serializer); oemcrypto_supports_usage_table_.Serialize(&serializer); oemcrypto_update_usage_table_.Serialize(&serializer); oemcrypto_wrap_keybox_.Serialize(&serializer); + + /* Internal OEMCrypto Metrics */ + oemcrypto_initialization_mode_.Serialize(&serializer); + oemcrypto_l1_api_version_.Serialize(&serializer); } SessionMetrics::SessionMetrics() : cdm_session_life_span_( - "/drm/widevine/cdm_session/life_span"), + "/drm/widevine/cdm_session/life_span/time"), cdm_session_renew_key_( "/drm/widevine/cdm_session/renew_key/time", "error"), cdm_session_restore_offline_session_( - "/drm/widevine/cdm_session/restore_offline_session", + "/drm/widevine/cdm_session/restore_offline_session/time", "error"), cdm_session_restore_usage_session_( - "/drm/widevine/cdm_session/restore_usage_session", + "/drm/widevine/cdm_session/restore_usage_session/time", "error"), completed_(false) { } @@ -330,76 +381,18 @@ void SessionMetrics::SerializeSessionMetrics(MetricsGroup* metric_group) { cdm_session_restore_usage_session_.Serialize(&serializer); } -OemCryptoDynamicAdapterMetrics::OemCryptoDynamicAdapterMetrics() : - oemcrypto_initialization_mode_( - "/drm/widevine/oemcrypto/initialization_mode"), - oemcrypto_l1_api_version_( - "/drm/widevine/oemcrypto/l1_api_version"), - oemcrypto_l1_min_api_version_( - "/drm/widevine/oemcrypto/l1_min_api_version") { -} - -void OemCryptoDynamicAdapterMetrics::SetInitializationMode( - OEMCryptoInitializationMode mode) { - AutoLock lock(adapter_lock_); - oemcrypto_initialization_mode_.Record(mode); -} - -void OemCryptoDynamicAdapterMetrics::SetL1ApiVersion(uint32_t version) { - AutoLock lock(adapter_lock_); - oemcrypto_l1_api_version_.Record(version); -} - -void OemCryptoDynamicAdapterMetrics::SetL1MinApiVersion(uint32_t version) { - AutoLock lock(adapter_lock_); - oemcrypto_l1_min_api_version_.Record(version); -} - -void OemCryptoDynamicAdapterMetrics::Serialize( - drm_metrics::MetricsGroup* metric_group) { - AutoLock lock(adapter_lock_); - ProtoMetricSerializer serializer(metric_group); - - oemcrypto_initialization_mode_.Serialize(&serializer); - oemcrypto_l1_api_version_.Serialize(&serializer); - oemcrypto_l1_min_api_version_.Serialize(&serializer); -} - -void OemCryptoDynamicAdapterMetrics::Clear() { - AutoLock lock(adapter_lock_); - - oemcrypto_initialization_mode_.Clear(); - oemcrypto_l1_api_version_.Clear(); - oemcrypto_l1_min_api_version_.Clear(); -} - -// This method returns a reference. This means that the destructor is never -// executed for the returned object. -OemCryptoDynamicAdapterMetrics& GetDynamicAdapterMetricsInstance() { - // This is safe in C++ 11 since the initialization is guaranteed to run - // only once regardless of multi-threaded access. - static OemCryptoDynamicAdapterMetrics* adapter_metrics = - new OemCryptoDynamicAdapterMetrics(); - return *adapter_metrics; -} - EngineMetrics::EngineMetrics() : cdm_engine_add_key_( "/drm/widevine/cdm_engine/add_key/time", "error"), - cdm_engine_cdm_version_( - "/drm/widevine/cdm_engine/version"), cdm_engine_close_session_( - "/drm/widevine/cdm_engine/close_session", + "/drm/widevine/cdm_engine/close_session/time", "error"), - cdm_engine_creation_time_millis_( - "/drm/widevine/cdm_engine/creation_time_millis"), cdm_engine_decrypt_( "/drm/widevine/cdm_engine/decrypt/time", - "error", - "length"), + "error"), cdm_engine_find_session_for_key_( - "/drm/widevine/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", @@ -414,42 +407,37 @@ EngineMetrics::EngineMetrics() : "/drm/widevine/cdm_engine/handle_provisioning_response/time", "error"), cdm_engine_life_span_( - "/drm/widevine/cdm_engine/life_span"), + "/drm/widevine/cdm_engine/life_span/time"), cdm_engine_open_key_set_session_( - "/drm/widevine/cdm_engine/open_key_set_session", + "/drm/widevine/cdm_engine/open_key_set_session/time", "error"), cdm_engine_open_session_( - "/drm/widevine/cdm_engine/open_session", + "/drm/widevine/cdm_engine/open_session/time", "error"), cdm_engine_query_key_status_( "/drm/widevine/cdm_engine/query_key_status/time", "error"), cdm_engine_release_all_usage_info_( - "/drm/widevine/cdm_engine/release_all_usage_info", + "/drm/widevine/cdm_engine/release_all_usage_info/time", "error"), cdm_engine_release_usage_info_( - "/drm/widevine/cdm_engine/release_usage_info", + "/drm/widevine/cdm_engine/release_usage_info/time", "error"), cdm_engine_remove_keys_( - "/drm/widevine/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", + "/drm/widevine/cdm_engine/unprovision/time", "error", - "security_level"), - app_package_name_("") { + "security_level") { } EngineMetrics::~EngineMetrics() { - AutoLock lock(session_metrics_lock_); + AutoLock kock(session_metrics_lock_); std::vector::iterator i; - if (!session_metrics_list_.empty()) { - LOGV("EngineMetrics::~EngineMetrics. Session count: %d", - session_metrics_list_.size()); - } for (i = session_metrics_list_.begin(); i != session_metrics_list_.end(); i++) { delete *i; @@ -478,24 +466,13 @@ void EngineMetrics::Serialize(drm_metrics::MetricsGroup* metric_group, bool clear_serialized_sessions) { AutoLock lock(session_metrics_lock_); - // Serialize the most recent metrics from the OemCyrpto dynamic adapter. - OemCryptoDynamicAdapterMetrics& adapter_metrics = - GetDynamicAdapterMetricsInstance(); - adapter_metrics.Serialize(metric_group); - if (!app_package_name_.empty()) { - metric_group->set_app_package_name(app_package_name_); - } SerializeEngineMetrics(metric_group); std::vector::iterator i; for (i = session_metrics_list_.begin(); i != session_metrics_list_.end(); /* no increment */) { bool serialized = false; if (!completed_only || (*i)->IsCompleted()) { - MetricsGroup* metric_sub_group = metric_group->add_metric_sub_group(); - if (!app_package_name_.empty()) { - metric_sub_group->set_app_package_name(app_package_name_); - } - (*i)->Serialize(metric_sub_group); + (*i)->Serialize(metric_group->add_metric_sub_group()); serialized = true; } @@ -508,16 +485,10 @@ void EngineMetrics::Serialize(drm_metrics::MetricsGroup* metric_group, } } -void EngineMetrics::SetAppPackageName(const std::string& app_package_name) { - app_package_name_ = app_package_name; -} - void EngineMetrics::SerializeEngineMetrics(MetricsGroup* metric_group) { ProtoMetricSerializer serializer(metric_group); cdm_engine_add_key_.Serialize(&serializer); - cdm_engine_cdm_version_.Serialize(&serializer); cdm_engine_close_session_.Serialize(&serializer); - cdm_engine_creation_time_millis_.Serialize(&serializer); cdm_engine_decrypt_.Serialize(&serializer); cdm_engine_find_session_for_key_.Serialize(&serializer); cdm_engine_generate_key_request_.Serialize(&serializer); diff --git a/libwvdrmengine/cdm/src/ami_adapter.cpp b/libwvdrmengine/cdm/src/ami_adapter.cpp index 73dd4ee9..4c7cfc29 100644 --- a/libwvdrmengine/cdm/src/ami_adapter.cpp +++ b/libwvdrmengine/cdm/src/ami_adapter.cpp @@ -22,10 +22,6 @@ AmiAdapter::~AmiAdapter() { analytics_item_.selfrecord(); } -metrics::Report* AmiAdapter::NewReport() const { - return new AmiAdapter(analytics_item_.getSessionID()); -} - void AmiAdapter::UpdateString(const std::string& metric_id, const std::string& value) { analytics_item_.setCString(metric_id.c_str(), value.c_str()); diff --git a/libwvdrmengine/cdm/src/log.cpp b/libwvdrmengine/cdm/src/log.cpp index 8c012036..e1a930b5 100644 --- a/libwvdrmengine/cdm/src/log.cpp +++ b/libwvdrmengine/cdm/src/log.cpp @@ -22,6 +22,9 @@ #include "log.h" #include +#include +#include + /* * Uncomment the line below if you want to have the LOGV messages to print * IMPORTANT : this will affect all of CDM diff --git a/libwvdrmengine/cdm/src/properties_android.cpp b/libwvdrmengine/cdm/src/properties_android.cpp index 8975883a..4ca2cdf5 100644 --- a/libwvdrmengine/cdm/src/properties_android.cpp +++ b/libwvdrmengine/cdm/src/properties_android.cpp @@ -19,7 +19,7 @@ const char kL2Dir[] = "/L2/"; const char kL3Dir[] = "/L3/"; const char kFactoryKeyboxPath[] = "/factory/wv.keys"; -const char kWVCdmVersion[] = "v5.0.0-android"; +const char kWVCdmVersion[] = "v5.1.0-android"; bool GetAndroidProperty(const char* key, std::string* value) { char val[PROPERTY_VALUE_MAX]; diff --git a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp index 47a15087..11b70625 100644 --- a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp +++ b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp @@ -7,7 +7,7 @@ #include "initialization_data.h" #include "license.h" #include "log.h" -#include "metrics_front_end.h" +#include "metrics.pb.h" #include "properties.h" #include "service_certificate.h" #include "wv_cdm_constants.h" @@ -21,22 +21,10 @@ namespace wvcdm { Lock WvContentDecryptionModule::session_sharing_id_generation_lock_; -WvContentDecryptionModule::WvContentDecryptionModule() { - // TODO (b/36497276) - // replace call to new AmiAdapter() and remove ami_apdater.* - report_root_ = NULL; // new AmiAdapter(); - front_end_ = new metrics::MetricsFrontEnd(report_root_); - metrics::MetricsFrontEnd::OverrideInstance(front_end_); -} +WvContentDecryptionModule::WvContentDecryptionModule() {} WvContentDecryptionModule::~WvContentDecryptionModule() { DisablePolicyTimer(true); - - metrics::MetricsFrontEnd::OverrideInstance(NULL); - delete front_end_; - delete report_root_; - front_end_ = NULL; - report_root_ = NULL; } bool WvContentDecryptionModule::IsSupported(const std::string& init_data_type) { @@ -414,6 +402,25 @@ bool WvContentDecryptionModule::IsValidServiceCertificate( return cert.has_certificate(); } +void WvContentDecryptionModule::GetSerializedMetrics( + std::string* serialized_metrics) { + drm_metrics::MetricsGroup metric_group; + { + AutoLock auto_lock(cdms_lock_); + for (auto it = cdms_.begin(); it != cdms_.end(); it++) { + metrics::EngineMetrics* engine_metrics = + it->second.cdm_engine->GetMetrics(); + if (engine_metrics) { + // Serialize the metrics from the engine and any completed sessions. + // Clear the metrics from any completed sessions. + engine_metrics->Serialize( + metric_group.add_metric_sub_group(), true, true); + } + } + } + metric_group.SerializeToString(serialized_metrics); +} + WvContentDecryptionModule::CdmInfo::CdmInfo() : cdm_engine(new CdmEngine(&file_system)) {} diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index d771e803..a5880336 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -1369,8 +1369,12 @@ TEST_F(WvCdmRequestLicenseTest, PerOriginProvisioningSupportsOldPaths) { // Make sure that the cert exists. std::vector files; ASSERT_TRUE(FileUtils::List(base_path, &files)); - ASSERT_EQ(1u, files.size()); - EXPECT_EQ(kOldFileName, files[0]); + ASSERT_LE(1u, files.size()); + bool found_it = false; + for(std::string file: files) { + if (file == std::string(kOldFileName)) found_it = true; + } + EXPECT_TRUE(found_it); // Reprovision the default identifier. Provision(kDefaultCdmIdentifier, kLevel3); @@ -1942,6 +1946,81 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) { VerifyKeyRequestResponse(g_license_server, client_auth); } +TEST_F(WvCdmRequestLicenseTest, + ReleaseRetryL3OfflineKeySessionUsageDisabledTest) { + Unprovision(); + + TestWvCdmClientPropertySet property_set; + property_set.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3); + + // The default offline asset "offline_clip2" has the session usage table + // entry enabled in the replay control portion of the key control block. + // To have it disabled we must use "offline_clip1", so replace the last + // char in init data with '1' + std::string key_id; + std::string client_auth; + GetOfflineConfiguration(&key_id, &client_auth); + key_id[key_id.size()-1] = '1'; + + CdmResponseType sts = decryptor_.OpenSession( + g_key_system, &property_set, kDefaultCdmIdentifier, NULL, &session_id_); + + if (NEED_PROVISIONING == sts) { + std::string provisioning_server_url; + CdmCertificateType cert_type = kCertificateWidevine; + std::string cert_authority, cert, wrapped_key; + EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest( + cert_type, cert_authority, kDefaultCdmIdentifier, + &key_msg_, &provisioning_server_url)); + EXPECT_EQ(provisioning_server_url, g_config->provisioning_server()); + std::string response = + GetCertRequestResponse(g_config->provisioning_server()); + EXPECT_NE(0, static_cast(response.size())); + EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse( + kDefaultCdmIdentifier, response, &cert, + &wrapped_key)); + EXPECT_EQ(NO_ERROR, + decryptor_.OpenSession(g_key_system, &property_set, + kDefaultCdmIdentifier, NULL, + &session_id_)); + } else { + EXPECT_EQ(NO_ERROR, sts); + } + + decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier, + NULL, &session_id_); + GenerateKeyRequest(key_id, kLicenseTypeOffline, &property_set); + VerifyKeyRequestResponse(g_license_server, client_auth); + + CdmKeySetId key_set_id = key_set_id_; + EXPECT_FALSE(key_set_id_.empty()); + decryptor_.CloseSession(session_id_); + + session_id_.clear(); + key_set_id_.clear(); + decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier, + NULL, &session_id_); + EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id)); + decryptor_.CloseSession(session_id_); + + session_id_.clear(); + key_set_id_.clear(); + GenerateKeyRelease(key_set_id, &property_set, NULL); + + session_id_.clear(); + decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier, + NULL, &session_id_); + EXPECT_EQ(wvcdm::GET_RELEASED_LICENSE_ERROR, + decryptor_.RestoreKey(session_id_, key_set_id)); + decryptor_.CloseSession(session_id_); + + session_id_.clear(); + key_set_id_.clear(); + GenerateKeyRelease(key_set_id, &property_set, NULL); + key_set_id_ = key_set_id; + VerifyKeyRequestResponse(g_license_server, client_auth); +} + TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) { Unprovision(); Provision(kLevelDefault); @@ -3652,14 +3731,14 @@ TEST(VersionNumberTest, VersionNumberChangeCanary) { char release_number[PROPERTY_VALUE_MAX]; ASSERT_GT(property_get("ro.build.version.release", release_number, "Unknown"), 0); - EXPECT_STREQ("8.0.0", release_number) + EXPECT_STREQ("8.1.0", release_number) << "The Android version number has changed. You need to update this test " "and also possibly update the Widevine version number in " "properties_android.cpp."; std::string widevine_version; ASSERT_TRUE(Properties::GetWVCdmVersion(&widevine_version)); - EXPECT_EQ("v5.0.0-android", widevine_version) + EXPECT_EQ("v5.1.0-android", widevine_version) << "The Widevine CDM version number has changed. Did you forget to " "update this test after changing it?"; } diff --git a/libwvdrmengine/cdm/test/unit-test.mk b/libwvdrmengine/cdm/test/unit-test.mk index 78ce40f2..33c6007d 100644 --- a/libwvdrmengine/cdm/test/unit-test.mk +++ b/libwvdrmengine/cdm/test/unit-test.mk @@ -42,7 +42,7 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libdl \ liblog \ - libmedia \ + libmedia_omx \ libprotobuf-cpp-lite \ libssl \ libstagefright_foundation \ @@ -51,10 +51,13 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_CFLAGS += -DUNIT_TEST LOCAL_MODULE_OWNER := widevine +LOCAL_PROPRIETARY_MODULE := true # When built, explicitly put it in the DATA/bin directory. LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/bin +LOCAL_PROPRIETARY_MODULE := true + ifneq ($(TARGET_ENABLE_MEDIADRM_64), true) LOCAL_MODULE_TARGET_ARCH := arm x86 mips endif diff --git a/libwvdrmengine/mediacrypto/Android.mk b/libwvdrmengine/mediacrypto/Android.mk index cc7a4c16..31490297 100644 --- a/libwvdrmengine/mediacrypto/Android.mk +++ b/libwvdrmengine/mediacrypto/Android.mk @@ -18,10 +18,17 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/mediacrypto/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ +LOCAL_HEADER_LIBRARIES := \ + libutils_headers + LOCAL_STATIC_LIBRARIES := \ libcrypto_static \ +LOCAL_SHARED_LIBRARIES := \ + liblog + LOCAL_MODULE := libwvdrmcryptoplugin +LOCAL_PROPRIETARY_MODULE := true LOCAL_MODULE_TAGS := optional @@ -47,6 +54,9 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/mediacrypto/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ +LOCAL_HEADER_LIBRARIES := \ + libutils_headers + LOCAL_STATIC_LIBRARIES := \ libcrypto_static \ libhidl_utils \ @@ -55,8 +65,10 @@ LOCAL_SHARED_LIBRARIES := \ android.hardware.drm@1.0 \ android.hidl.memory@1.0 \ libhidlmemory \ + liblog LOCAL_MODULE := libwvdrmcryptoplugin_hidl +LOCAL_PROPRIETARY_MODULE := true LOCAL_MODULE_TAGS := optional diff --git a/libwvdrmengine/mediacrypto/test/Android.mk b/libwvdrmengine/mediacrypto/test/Android.mk index b617e7ac..7cd6a1c5 100644 --- a/libwvdrmengine/mediacrypto/test/Android.mk +++ b/libwvdrmengine/mediacrypto/test/Android.mk @@ -45,6 +45,7 @@ LOCAL_MODULE := libwvdrmmediacrypto_test LOCAL_MODULE_TAGS := tests LOCAL_MODULE_OWNER := widevine +LOCAL_PROPRIETARY_MODULE := true # When built, explicitly put it in the DATA/bin directory. LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/bin @@ -111,6 +112,7 @@ LOCAL_MODULE := libwvdrmmediacrypto_hidl_test LOCAL_MODULE_TAGS := tests LOCAL_MODULE_OWNER := widevine +LOCAL_PROPRIETARY_MODULE := true # When built, explicitly put it in the DATA/bin directory. LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/bin diff --git a/libwvdrmengine/mediadrm/Android.mk b/libwvdrmengine/mediadrm/Android.mk index 32372c5e..05583428 100644 --- a/libwvdrmengine/mediadrm/Android.mk +++ b/libwvdrmengine/mediadrm/Android.mk @@ -19,7 +19,14 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/mediadrm/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ +LOCAL_HEADER_LIBRARIES := \ + libutils_headers + +LOCAL_SHARED_LIBRARIES := \ + liblog + LOCAL_MODULE := libwvdrmdrmplugin +LOCAL_PROPRIETARY_MODULE := true LOCAL_MODULE_TAGS := optional @@ -46,13 +53,18 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/mediadrm/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ +LOCAL_HEADER_LIBRARIES := \ + libutils_headers \ + LOCAL_STATIC_LIBRARIES := libcrypto_static LOCAL_SHARED_LIBRARIES := \ android.hardware.drm@1.0 \ android.hidl.memory@1.0 \ + liblog LOCAL_MODULE := libwvdrmdrmplugin_hidl +LOCAL_PROPRIETARY_MODULE := true LOCAL_MODULE_TAGS := optional diff --git a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp index 41958dba..aea51dcf 100644 --- a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp @@ -533,13 +533,16 @@ status_t WVDrmPlugin::getPropertyString(const String8& name, status_t WVDrmPlugin::getPropertyByteArray(const String8& name, Vector& value) const { - if (name == "deviceUniqueId") { return queryProperty(QUERY_KEY_DEVICE_ID, value); } else if (name == "provisioningUniqueId") { return queryProperty(QUERY_KEY_PROVISIONING_ID, value); } else if (name == "serviceCertificate") { value = ToVector(mPropertySet.service_certificate()); + } else if (name == "metrics") { + std::string metrics_value; + mCDM->GetSerializedMetrics(&metrics_value); + value = ToVector(metrics_value); } else { ALOGE("App requested unknown byte array property %s", name.string()); return android::ERROR_DRM_CANNOT_HANDLE; diff --git a/libwvdrmengine/mediadrm/test/Android.mk b/libwvdrmengine/mediadrm/test/Android.mk index 2e73ef70..746c6dc7 100644 --- a/libwvdrmengine/mediadrm/test/Android.mk +++ b/libwvdrmengine/mediadrm/test/Android.mk @@ -45,6 +45,7 @@ LOCAL_MODULE := libwvdrmdrmplugin_test LOCAL_MODULE_TAGS := tests LOCAL_MODULE_OWNER := widevine +LOCAL_PROPRIETARY_MODULE := true # When built, explicitly put it in the DATA/bin directory. LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/bin @@ -112,6 +113,7 @@ LOCAL_MODULE := libwvdrmdrmplugin_hidl_test LOCAL_MODULE_TAGS := tests LOCAL_MODULE_OWNER := widevine +LOCAL_PROPRIETARY_MODULE := true # When built, explicitly put it in the DATA/bin directory. LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/bin diff --git a/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp b/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp index 23fd4a08..a5d0465d 100644 --- a/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp +++ b/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp @@ -117,7 +117,17 @@ const std::string kAppId("com.unittest.mock.app.id"); const uint8_t* const kUnprovisionResponse = reinterpret_cast("unprovision"); const size_t kUnprovisionResponseSize = 11; -} +const std::string kDeviceId = "0123456789ABCDEF"; + +// This is a serialized MetricsGroup message containing a small amount of +// sample data. This ensures we're able to extract it via a property. +const char kSerializedMetrics[] = { + 0x0a, 0x0a, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x02, 0x08, 0x00, + 0x0a, 0x12, 0x0a, 0x05, 0x74, 0x65, 0x73, 0x74, 0x32, 0x12, 0x09, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x15, 0x0a, 0x05, + 0x74, 0x65, 0x73, 0x74, 0x33, 0x12, 0x0c, 0x1a, 0x0a, 0x74, 0x65, 0x73, + 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65}; +} // anonymous namespace class MockCDM : public WvContentDecryptionModule { public: @@ -183,6 +193,8 @@ class MockCDM : public WvContentDecryptionModule { CdmResponseType(const CdmUsageInfoReleaseMessage&, const CdmIdentifier&)); MOCK_METHOD1(IsValidServiceCertificate, bool(const std::string&)); + + MOCK_METHOD1(GetSerializedMetrics, void(std::string*)); }; class MockCrypto : public WVGenericCryptoInterface { @@ -1047,6 +1059,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { static const std::string openSessions = "42"; static const std::string maxSessions = "54"; static const std::string oemCryptoApiVersion = "13"; + std::string serializedMetrics( + kSerializedMetrics, kSerializedMetrics + sizeof(kSerializedMetrics)); static const std::string currentSRMVersion = "1"; static const std::string cdmVersion = "Infinity Minus 1"; @@ -1198,6 +1212,15 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { ASSERT_EQ(Status::OK, status); EXPECT_STREQ(currentSRMVersion.c_str(), stringResult.c_str()); }); + + plugin.getPropertyByteArray( + hidl_string("metrics"), + [&](Status status, hidl_vec vectorResult) { + ASSERT_EQ(Status::OK, status); + std::vector id(vectorResult); + EXPECT_THAT(id, ElementsAreArray(serializedMetrics.data(), + serializedMetrics.size())); + }); } TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) { diff --git a/libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp b/libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp index 47510501..cc368547 100644 --- a/libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp +++ b/libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp @@ -32,7 +32,16 @@ const String8 kAppId("com.unittest.mock.app.id"); const uint8_t* const kUnprovisionResponse = reinterpret_cast("unprovision"); const size_t kUnprovisionResponseSize = 11; -} + +// This is a serialized MetricsGroup message containing a small amount of +// sample data. This ensures we're able to extract it via a property. +const char kSerializedMetrics[] = { + 0x0a, 0x0a, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x02, 0x08, 0x00, + 0x0a, 0x12, 0x0a, 0x05, 0x74, 0x65, 0x73, 0x74, 0x32, 0x12, 0x09, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x15, 0x0a, 0x05, + 0x74, 0x65, 0x73, 0x74, 0x33, 0x12, 0x0c, 0x1a, 0x0a, 0x74, 0x65, 0x73, + 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65}; +} // anonymous namespace class MockCDM : public WvContentDecryptionModule { public: @@ -98,6 +107,8 @@ class MockCDM : public WvContentDecryptionModule { CdmResponseType(const CdmUsageInfoReleaseMessage&, const CdmIdentifier&)); MOCK_METHOD1(IsValidServiceCertificate, bool(const std::string&)); + + MOCK_METHOD1(GetSerializedMetrics, void(std::string*)); }; class MockCrypto : public WVGenericCryptoInterface { @@ -837,6 +848,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { static const string openSessions = "15"; static const string maxSessions = "18"; static const string oemCryptoApiVersion = "10"; + string serializedMetrics(kSerializedMetrics, + kSerializedMetrics + sizeof(kSerializedMetrics)); static const string currentSRMVersion = "1"; static const string cdmVersion = "Infinity Minus 1"; diff --git a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h index 79fc2e0d..8fca7c9b 100644 --- a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h +++ b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h @@ -78,6 +78,7 @@ typedef enum OEMCryptoResult { OEMCrypto_ERROR_LICENSE_INACTIVE = 47, OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE = 48, OEMCrypto_ERROR_ENTRY_IN_USE = 49, + OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE = 50, // Reserved. Do not use. } OEMCryptoResult; /* diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp index 30935af9..44322d88 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp @@ -7,8 +7,9 @@ namespace wvoec_mock { -CryptoEngine* CryptoEngine::MakeCryptoEngine(wvcdm::FileSystem* file_system) { - return new CryptoEngine(file_system); +CryptoEngine* CryptoEngine::MakeCryptoEngine( + std::unique_ptr file_system) { + return new CryptoEngine(std::move(file_system)); } } // namespace wvoec_mock diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_L1.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_L1.cpp index 448f7ff4..5c4ee1ef 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_L1.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_L1.cpp @@ -10,8 +10,8 @@ namespace wvoec_mock { class L1CryptoEngine : public CryptoEngine { public: - explicit L1CryptoEngine(wvcdm::FileSystem* file_system) - : CryptoEngine(file_system) {} + explicit L1CryptoEngine(std::unique_ptr file_system) + : CryptoEngine(std::move(file_system)) {} bool config_local_display_only() { return true; } @@ -28,8 +28,9 @@ class L1CryptoEngine : public CryptoEngine { uint8_t config_security_patch_level() { return 3; } }; -CryptoEngine* CryptoEngine::MakeCryptoEngine(wvcdm::FileSystem* file_system) { - return new L1CryptoEngine(file_system); +CryptoEngine* CryptoEngine::MakeCryptoEngine( + std::unique_ptr file_system) { + return new L1CryptoEngine(std::move(file_system)); } } // namespace wvoec_mock diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_cert.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_cert.cpp index ec5d8c53..ddb702e3 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_cert.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_cert.cpp @@ -13,8 +13,8 @@ namespace wvoec_mock { class CertOnlyCryptoEngine : public CryptoEngine { public: - explicit CertOnlyCryptoEngine(wvcdm::FileSystem* file_system) - : CryptoEngine(file_system) {} + explicit CertOnlyCryptoEngine(std::unique_ptr file_system) + : CryptoEngine(std::move(file_system)) {} bool config_local_display_only() { return true; } @@ -27,8 +27,9 @@ class CertOnlyCryptoEngine : public CryptoEngine { const char* config_security_level() { return "L2"; } }; -CryptoEngine* CryptoEngine::MakeCryptoEngine(wvcdm::FileSystem* file_system) { - return new CertOnlyCryptoEngine(file_system); +CryptoEngine* CryptoEngine::MakeCryptoEngine( + std::unique_ptr file_system) { + return new CertOnlyCryptoEngine(std::move(file_system)); } } // namespace wvoec_mock diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_mod.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_mod.cpp index a31e455b..a40083bb 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_mod.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_mod.cpp @@ -92,8 +92,8 @@ const std::string kDefaultOptionsFile = "/data/mediadrm/oemcrypto/options.txt"; class AndroidModifiableCryptoEngine : public CryptoEngine { public: - AndroidModifiableCryptoEngine(wvcdm::FileSystem *file_system) - : CryptoEngine(file_system), + AndroidModifiableCryptoEngine(std::unique_ptr file_system) + : CryptoEngine(std::move(file_system)), options_file_(kDefaultOptionsFile), srm_loaded_(false), srm_version_(0), @@ -587,8 +587,9 @@ class AndroidModifiableCryptoEngine : public CryptoEngine { size_t temp_buffer_length_; // Length of temp buffer currently in use. }; -CryptoEngine* CryptoEngine::MakeCryptoEngine(wvcdm::FileSystem *file_system) { - return new AndroidModifiableCryptoEngine(file_system); +CryptoEngine* CryptoEngine::MakeCryptoEngine( + std::unique_ptr file_system) { + return new AndroidModifiableCryptoEngine(std::move(file_system)); } } // namespace wvoec_mock diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_prov30.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_prov30.cpp index 7bd541db..eb2b7ff2 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_prov30.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_prov30.cpp @@ -17,8 +17,8 @@ namespace wvoec_mock { class Prov30CryptoEngine : public CryptoEngine { public: - explicit Prov30CryptoEngine(wvcdm::FileSystem* file_system) - : CryptoEngine(file_system) {} + explicit Prov30CryptoEngine(std::unique_ptr file_system) + : CryptoEngine(std::move(file_system)) {} bool config_local_display_only() { return true; } @@ -74,8 +74,9 @@ class Prov30CryptoEngine : public CryptoEngine { const char* config_security_level() { return "L2"; } }; -CryptoEngine* CryptoEngine::MakeCryptoEngine(wvcdm::FileSystem* file_system) { - return new Prov30CryptoEngine(file_system); +CryptoEngine* CryptoEngine::MakeCryptoEngine( + std::unique_ptr file_system) { + return new Prov30CryptoEngine(std::move(file_system)); } } // namespace wvoec_mock diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp index a3cfdaa5..062a613d 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp @@ -27,9 +27,9 @@ namespace wvoec_mock { // all configurations. See the files oemcrypto_engine_device_properties*.cpp // for methods that are configured for specific configurations. -CryptoEngine::CryptoEngine(wvcdm::FileSystem* file_system) +CryptoEngine::CryptoEngine(std::unique_ptr file_system) : root_of_trust_(config_provisioning_method()), - file_system_(file_system), + file_system_(std::move(file_system)), usage_table_(this) { ERR_load_crypto_strings(); } @@ -41,6 +41,7 @@ CryptoEngine::~CryptoEngine() { delete it->second; } sessions_.clear(); + ERR_free_strings(); } SessionId CryptoEngine::CreateSession() { diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h index 6d6502ea..dfe72a96 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -29,9 +30,12 @@ typedef std::map ActiveSessions; class CryptoEngine { public: // This is like a factory method, except we choose which version to use at - // compile time. It is defined in several source files. The build system + // compile time. It is defined in several source files. The build system // should choose which one to use by only linking in the correct one. - static CryptoEngine* MakeCryptoEngine(wvcdm::FileSystem* file_system); + // NOTE: The caller must instantiate a FileSystem object - ownership + // will be transferred to the new CryptoEngine object. + static CryptoEngine* MakeCryptoEngine( + std::unique_ptr file_system); virtual ~CryptoEngine(); @@ -86,7 +90,7 @@ class CryptoEngine { virtual OEMCrypto_HDCP_Capability config_maximum_hdcp_capability(); UsageTable& usage_table() { return usage_table_; } - wvcdm::FileSystem* file_system() { return file_system_; } + wvcdm::FileSystem* file_system() { return file_system_.get(); } // If config_local_display_only() returns true, we pretend we are using a // built-in display, instead of HDMI or WiFi output. @@ -159,14 +163,14 @@ class CryptoEngine { } protected: - explicit CryptoEngine(wvcdm::FileSystem* file_system); + explicit CryptoEngine(std::unique_ptr file_system); uint8_t* destination_; private: ActiveSessions sessions_; AuthenticationRoot root_of_trust_; wvcdm::Lock session_table_lock_; - wvcdm::FileSystem* file_system_; + std::unique_ptr file_system_; UsageTable usage_table_; CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine); diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp index b1f099dc..b46f49e7 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp @@ -51,8 +51,9 @@ extern "C" OEMCryptoResult OEMCrypto_Initialize(void) { crypto_engine = NULL; } // NOTE: This requires a compatible Filesystem implementation. - wvcdm::FileSystem* fs = new wvcdm::FileSystem(); - crypto_engine = CryptoEngine::MakeCryptoEngine(fs); + // NOTE: Ownership of the FileSystem object is transferred to CryptoEngine + std::unique_ptr fs(new wvcdm::FileSystem()); + crypto_engine = CryptoEngine::MakeCryptoEngine(std::move(fs)); if (!crypto_engine || !crypto_engine->Initialize()) { LOGE("[OEMCrypto_Initialize(): failed]"); diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_old_usage_table_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_old_usage_table_mock.cpp index cbeb7501..033747de 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_old_usage_table_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_old_usage_table_mock.cpp @@ -56,7 +56,7 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) { table_.clear(); // Load saved table. - wvcdm::FileSystem *file_system = ce->file_system(); + wvcdm::FileSystem* file_system = ce->file_system(); wvcdm::File *file; std::string path; // Note: this path is OK for a real implementation, but using security level 1 @@ -208,7 +208,7 @@ void OldUsageTable::Clear() { } void OldUsageTable::DeleteFile(CryptoEngine *ce) { - wvcdm::FileSystem *file_system = ce->file_system(); + wvcdm::FileSystem* file_system = ce->file_system(); std::string path; // Note: this path is OK for a real implementation, but using security level 1 // would be better. diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_session.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_session.cpp index cb26be27..fc8c1aba 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_session.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_session.cpp @@ -74,8 +74,14 @@ bool SessionContext::DeriveKey(const std::vector& key, const EVP_CIPHER* cipher = EVP_aes_128_cbc(); CMAC_CTX* cmac_ctx = CMAC_CTX_new(); + if (!cmac_ctx) { + LOGE("[DeriveKey(): OEMCrypto_ERROR_CMAC_FAILURE]"); + return false; + } + if (!CMAC_Init(cmac_ctx, &key[0], key.size(), cipher, 0)) { LOGE("[DeriveKey(): OEMCrypto_ERROR_CMAC_FAILURE]"); + CMAC_CTX_free(cmac_ctx); return false; } @@ -85,6 +91,7 @@ bool SessionContext::DeriveKey(const std::vector& key, if (!CMAC_Update(cmac_ctx, &message[0], message.size())) { LOGE("[DeriveKey(): OEMCrypto_ERROR_CMAC_FAILURE]"); + CMAC_CTX_free(cmac_ctx); return false; } @@ -92,6 +99,7 @@ bool SessionContext::DeriveKey(const std::vector& key, uint8_t res[128]; if (!CMAC_Final(cmac_ctx, res, &reslen)) { LOGE("[DeriveKey(): OEMCrypto_ERROR_CMAC_FAILURE]"); + CMAC_CTX_free(cmac_ctx); return false; } @@ -1291,6 +1299,7 @@ OEMCryptoResult SessionContext::DecryptCTR(const uint8_t* key_u8, EVP_CIPHER_CTX_set_padding(&ctx, 0); if (!EVP_DecryptInit_ex(&ctx, EVP_aes_128_ctr(), NULL, key_u8, aes_iv_u8)) { LOGE("[DecryptCTR(): EVP_INIT ERROR]"); + EVP_CIPHER_CTX_cleanup(&ctx); return OEMCrypto_ERROR_DECRYPT_FAILED; } @@ -1310,6 +1319,7 @@ OEMCryptoResult SessionContext::DecryptCTR(const uint8_t* key_u8, if (!EVP_DecryptUpdate(&ctx, &clear_data[l], &out_len, &cipher_data[l], decrypt_length)) { LOGE("[DecryptCTR(): EVP_UPDATE_ERROR]"); + EVP_CIPHER_CTX_cleanup(&ctx); return OEMCrypto_ERROR_DECRYPT_FAILED; } l += decrypt_length; @@ -1319,6 +1329,7 @@ OEMCryptoResult SessionContext::DecryptCTR(const uint8_t* key_u8, if (!EVP_DecryptFinal_ex( &ctx, &clear_data[cipher_data_length - remaining], & final)) { LOGE("[DecryptCTR(): EVP_FINAL_ERROR]"); + EVP_CIPHER_CTX_cleanup(&ctx); return OEMCrypto_ERROR_DECRYPT_FAILED; } EVP_CIPHER_CTX_cleanup(&ctx); diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.cpp index 485df98d..d0e549b3 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.cpp @@ -314,7 +314,8 @@ OEMCryptoResult UsageTableEntry::CopyOldUsageEntry( } else { data_.pst_length = pst.size(); } - memcpy(data_.pst, &pst[0], wvcdm::MAC_KEY_SIZE); + memcpy(data_.pst, &pst[0], data_.pst_length); + data_.pst[data_.pst_length] = '\0'; return OEMCrypto_SUCCESS; } @@ -656,7 +657,8 @@ bool UsageTable::LoadGenerationNumber(bool or_make_new_one) { // On a real implementation, you should NOT put the generation number in // a file in user space. It should be stored in secure memory. std::string filename = path + "GenerationNumber.dat"; - wvcdm::File* file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly); + wvcdm::File* file = file_system->Open(filename, + wvcdm::FileSystem::kReadOnly); if (!file) { if (or_make_new_one) { RAND_bytes(reinterpret_cast(&master_generation_number_), diff --git a/libwvdrmengine/oemcrypto/test/Android.mk b/libwvdrmengine/oemcrypto/test/Android.mk index 4ac91c71..5b9a1d1b 100644 --- a/libwvdrmengine/oemcrypto/test/Android.mk +++ b/libwvdrmengine/oemcrypto/test/Android.mk @@ -6,6 +6,7 @@ LOCAL_MODULE:=oemcrypto_test LOCAL_MODULE_TAGS := tests LOCAL_MODULE_OWNER := widevine +LOCAL_PROPRIETARY_MODULE := true # When built, explicitly put it in the DATA/bin directory. LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/bin diff --git a/libwvdrmengine/oemcrypto/test/common.mk b/libwvdrmengine/oemcrypto/test/common.mk index 162b9b04..9415cba6 100644 --- a/libwvdrmengine/oemcrypto/test/common.mk +++ b/libwvdrmengine/oemcrypto/test/common.mk @@ -30,7 +30,7 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libdl \ liblog \ - libmedia \ + libmedia_omx \ libstagefright_foundation \ libutils \ libz \ diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 2e09667c..13ad3818 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -2600,6 +2600,7 @@ TEST_F(OEMCryptoLoadsCertificate, RSAPerformance) { sts = OEMCrypto_GenerateRSASignature(s.session_id(), &licenseRequest[0], licenseRequest.size(), signature, &signature_length, kSign_RSASSA_PSS); + delete[] signature; ASSERT_EQ(OEMCrypto_SUCCESS, sts); count++; gettimeofday(&end_time, NULL); diff --git a/libwvdrmengine/test/unit/Android.mk b/libwvdrmengine/test/unit/Android.mk index ef0fed0f..a4f3e0b8 100644 --- a/libwvdrmengine/test/unit/Android.mk +++ b/libwvdrmengine/test/unit/Android.mk @@ -33,6 +33,7 @@ LOCAL_MODULE := libwvdrmengine_test LOCAL_MODULE_TAGS := tests LOCAL_MODULE_OWNER := widevine +LOCAL_PROPRIETARY_MODULE := true # When built, explicitly put it in the DATA/bin directory. LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/bin @@ -82,6 +83,7 @@ LOCAL_MODULE := libwvdrmengine_hidl_test LOCAL_MODULE_TAGS := tests LOCAL_MODULE_OWNER := widevine +LOCAL_PROPRIETARY_MODULE := true # When built, explicitly put it in the DATA/bin directory. LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/bin diff --git a/libwvdrmengine/test/unit/legacy_src/WVCreatePluginFactories_test.cpp b/libwvdrmengine/test/unit/legacy_src/WVCreatePluginFactories_test.cpp index 391e119f..7b9fec2a 100644 --- a/libwvdrmengine/test/unit/legacy_src/WVCreatePluginFactories_test.cpp +++ b/libwvdrmengine/test/unit/legacy_src/WVCreatePluginFactories_test.cpp @@ -3,20 +3,21 @@ // #include "gtest/gtest.h" -#include #include "WVCreatePluginFactories.h" +#include + using namespace android; TEST(CreatePluginFactoriesTest, CreatesDrmFactory) { - UniquePtr factory(createDrmFactory()); + std::unique_ptr factory(createDrmFactory()); EXPECT_NE((DrmFactory*)NULL, factory.get()) << "createDrmFactory() returned null"; } TEST(CreatePluginFactoriesTest, CreatesCryptoFactory) { - UniquePtr factory(createCryptoFactory()); + std::unique_ptr factory(createCryptoFactory()); EXPECT_NE((CryptoFactory*)NULL, factory.get()) << "createCryptoFactory() returned null"; diff --git a/libwvdrmengine/test/unit/legacy_src/WVCryptoFactory_test.cpp b/libwvdrmengine/test/unit/legacy_src/WVCryptoFactory_test.cpp index 987a7586..bee0b7f6 100644 --- a/libwvdrmengine/test/unit/legacy_src/WVCryptoFactory_test.cpp +++ b/libwvdrmengine/test/unit/legacy_src/WVCryptoFactory_test.cpp @@ -2,11 +2,11 @@ * Copyright 2012 Google Inc. All Rights Reserved. */ -#include - #include "gtest/gtest.h" #include "WVCryptoFactory.h" +#include + using namespace wvdrm; const uint8_t kWidevineUUID[16] = { @@ -25,7 +25,7 @@ const uint8_t kUnknownUUID[16] = { }; TEST(WVCryptoFactoryTest, SupportsSupportedCryptoSchemes) { - UniquePtr factory(new WVCryptoFactory()); + std::unique_ptr factory(new WVCryptoFactory()); EXPECT_TRUE(factory->isCryptoSchemeSupported(kWidevineUUID)) << "WVPluginFactory does not support Widevine's UUID"; @@ -35,7 +35,7 @@ TEST(WVCryptoFactoryTest, SupportsSupportedCryptoSchemes) { } TEST(WVCryptoFactoryTest, DoesNotSupportUnsupportedCryptoSchemes) { - UniquePtr factory(new WVCryptoFactory()); + std::unique_ptr factory(new WVCryptoFactory()); EXPECT_FALSE(factory->isCryptoSchemeSupported(kUnknownUUID)) << "WVPluginFactory incorrectly claims to support an unknown UUID"; diff --git a/libwvdrmengine/test/unit/legacy_src/WVDrmFactory_test.cpp b/libwvdrmengine/test/unit/legacy_src/WVDrmFactory_test.cpp index a920358f..711960a5 100644 --- a/libwvdrmengine/test/unit/legacy_src/WVDrmFactory_test.cpp +++ b/libwvdrmengine/test/unit/legacy_src/WVDrmFactory_test.cpp @@ -3,7 +3,6 @@ */ #include "gtest/gtest.h" -#include #include "WVDrmFactory.h" using namespace wvdrm; diff --git a/libwvdrmengine/vts/vendor_module/Android.mk b/libwvdrmengine/vts/vendor_module/Android.mk index f34413f0..782ca00a 100644 --- a/libwvdrmengine/vts/vendor_module/Android.mk +++ b/libwvdrmengine/vts/vendor_module/Android.mk @@ -35,6 +35,7 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE := libvtswidevine LOCAL_MODULE_RELATIVE_PATH := drm-vts-test-libs LOCAL_MODULE_TAGS := optional +LOCAL_PROPRIETARY_MODULE := true include $(BUILD_SHARED_LIBRARY)