diff --git a/libwvdrmengine/cdm/core/include/cdm_engine.h b/libwvdrmengine/cdm/core/include/cdm_engine.h index e516f7c3..5de39cba 100644 --- a/libwvdrmengine/cdm/core/include/cdm_engine.h +++ b/libwvdrmengine/cdm/core/include/cdm_engine.h @@ -225,14 +225,19 @@ class CdmEngine { // Usage related methods for streaming licenses // Retrieve a random usage info from the list of all usage infos for this app - // id. + // id. If |error_detail| is not null, an additional error code may be provided + // in the event of an error. virtual CdmResponseType GetUsageInfo(const std::string& app_id, + CdmResponseType* error_detail, CdmUsageInfo* usage_info); // Retrieve the usage info for the specified pst. // Returns UNKNOWN_ERROR if no usage info was found. + // id. If |error_detail| is not null, an additional error code may be provided + // in the event of an error. virtual CdmResponseType GetUsageInfo(const std::string& app_id, const CdmSecureStopId& ssid, + CdmResponseType* error_detail, CdmUsageInfo* usage_info); // Remove all usage records for the current origin. @@ -358,6 +363,7 @@ class CdmEngine { bool ValidateKeySystem(const CdmKeySystem& key_system); CdmResponseType GetUsageInfo(const std::string& app_id, SecurityLevel requested_security_level, + CdmResponseType* error_detail, CdmUsageInfo* usage_info); void OnKeyReleaseEvent(const CdmKeySetId& key_set_id); diff --git a/libwvdrmengine/cdm/core/include/cdm_engine_metrics_decorator.h b/libwvdrmengine/cdm/core/include/cdm_engine_metrics_decorator.h index 04027b48..3b514af0 100644 --- a/libwvdrmengine/cdm/core/include/cdm_engine_metrics_decorator.h +++ b/libwvdrmengine/cdm/core/include/cdm_engine_metrics_decorator.h @@ -181,20 +181,30 @@ class CdmEngineMetricsImpl : public T { } CdmResponseType GetUsageInfo(const std::string& app_id, + CdmResponseType* error_detail, CdmUsageInfo* usage_info) override { CdmResponseType sts; - M_TIME(sts = T::GetUsageInfo(app_id, usage_info), - metrics_, cdm_engine_get_usage_info_, sts); + CdmResponseType error_detail_alt; + M_TIME(sts = T::GetUsageInfo(app_id, &error_detail_alt, usage_info), + metrics_, cdm_engine_get_usage_info_, sts, error_detail_alt); + if (error_detail != nullptr) { + *error_detail = error_detail_alt; + } return sts; } CdmResponseType GetUsageInfo(const std::string& app_id, const CdmSecureStopId& ssid, + CdmResponseType* error_detail, CdmUsageInfo* usage_info) override { CdmResponseType sts; - M_TIME(sts = T::GetUsageInfo(app_id, ssid, usage_info), - metrics_, cdm_engine_get_usage_info_, sts); + CdmResponseType error_detail_alt; + M_TIME(sts = T::GetUsageInfo(app_id, ssid, &error_detail_alt, usage_info), + metrics_, cdm_engine_get_usage_info_, sts, error_detail_alt); + if (error_detail != nullptr) { + *error_detail = error_detail_alt; + } return sts; } diff --git a/libwvdrmengine/cdm/core/include/cdm_session.h b/libwvdrmengine/cdm/core/include/cdm_session.h index c518c582..6fd290c3 100644 --- a/libwvdrmengine/cdm/core/include/cdm_session.h +++ b/libwvdrmengine/cdm/core/include/cdm_session.h @@ -61,9 +61,11 @@ class CdmSession { WvCdmEventListener* event_listener); virtual CdmResponseType RestoreOfflineSession( - const CdmKeySetId& key_set_id, CdmLicenseType license_type); + const CdmKeySetId& key_set_id, CdmLicenseType license_type, + CdmResponseType* error_detail); virtual CdmResponseType RestoreUsageSession( - const DeviceFiles::CdmUsageData& usage_data); + const DeviceFiles::CdmUsageData& usage_data, + CdmResponseType* error_detail); virtual const CdmSessionId& session_id() { return session_id_; } virtual const CdmKeySetId& key_set_id() { return key_set_id_; } diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index feff5702..69c5f190 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -285,8 +285,11 @@ CdmResponseType CdmEngine::GenerateKeyRequest( if (license_type == kLicenseTypeRelease && !session->license_received()) { - sts = session->RestoreOfflineSession(key_set_id, kLicenseTypeRelease); - session->GetMetrics()->cdm_session_restore_offline_session_.Increment(sts); + CdmResponseType error_detail = NO_ERROR; + sts = session->RestoreOfflineSession(key_set_id, kLicenseTypeRelease, + &error_detail); + session->GetMetrics()->cdm_session_restore_offline_session_.Increment( + sts, error_detail); if (sts != KEY_ADDED) { LOGE("CdmEngine::GenerateKeyRequest: key release restoration failed," "sts = %d", static_cast(sts)); @@ -418,8 +421,11 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id, } CdmResponseType sts; - sts = session->RestoreOfflineSession(key_set_id, kLicenseTypeOffline); - session->GetMetrics()->cdm_session_restore_offline_session_.Increment(sts); + CdmResponseType error_detail = NO_ERROR; + sts = session->RestoreOfflineSession(key_set_id, kLicenseTypeOffline, + &error_detail); + session->GetMetrics()->cdm_session_restore_offline_session_.Increment( + sts, error_detail); if (sts == NEED_PROVISIONING) { cert_provisioning_requested_security_level_ = session->GetRequestedSecurityLevel(); @@ -1206,6 +1212,7 @@ CdmResponseType CdmEngine::RemoveOfflineLicense( CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, const CdmSecureStopId& ssid, + CdmResponseType* error_detail, CdmUsageInfo* usage_info) { LOGI("CdmEngine::GetUsageInfo: %s", ssid.c_str()); if (NULL == usage_property_set_.get()) { @@ -1254,8 +1261,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, } } - status = - usage_session_->RestoreUsageSession(usage_data); + status = usage_session_->RestoreUsageSession(usage_data, error_detail); if (KEY_ADDED != status) { LOGE("CdmEngine::GetUsageInfo: restore usage session error %d", status); @@ -1279,6 +1285,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, } CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, + CdmResponseType* error_detail, CdmUsageInfo* usage_info) { LOGI("CdmEngine::GetUsageInfo: %s", app_id.c_str()); // Return a random usage report from a random security level @@ -1289,7 +1296,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, return PARAMETER_NULL; } do { - status = GetUsageInfo(app_id, security_level, usage_info); + status = GetUsageInfo(app_id, security_level, error_detail, usage_info); if (KEY_MESSAGE == status && !usage_info->empty()) { return status; @@ -1298,7 +1305,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, security_level = (kLevel3 == security_level) ? kLevelDefault : kLevel3; do { - status = GetUsageInfo(app_id, security_level, usage_info); + status = GetUsageInfo(app_id, security_level, error_detail, usage_info); if (NEED_PROVISIONING == status) return NO_ERROR; // Valid scenario that one of the security // levels has not been provisioned @@ -1308,6 +1315,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, SecurityLevel requested_security_level, + CdmResponseType* error_detail, CdmUsageInfo* usage_info) { LOGI("CdmEngine::GetUsageInfo: %s, security level: %d", app_id.c_str(), requested_security_level); @@ -1350,7 +1358,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, usage_info->resize(kUsageReportsPerRequest); uint32_t index = rand() % usage_data.size(); - status = usage_session_->RestoreUsageSession(usage_data[index]); + status = usage_session_->RestoreUsageSession(usage_data[index], error_detail); if (KEY_ADDED != status) { LOGE("CdmEngine::GetUsageInfo: restore usage session (%d) error %ld", index, status); @@ -1644,8 +1652,11 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id, return LOAD_USAGE_INFO_MISSING; } - CdmResponseType status = session->RestoreUsageSession(usage_data); - session->GetMetrics()->cdm_session_restore_usage_session_.Increment(status); + CdmResponseType error_detail = NO_ERROR; + CdmResponseType status = session->RestoreUsageSession(usage_data, + &error_detail); + session->GetMetrics()->cdm_session_restore_usage_session_.Increment( + status, error_detail); if (KEY_ADDED != status) { LOGE("CdmEngine::LoadUsageSession: usage session error %ld", status); return status; diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index 90260800..650db6d1 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -22,6 +22,15 @@ namespace { const size_t kKeySetIdLength = 14; + +// Helper function for setting the error detail value. +void SetErrorDetail(wvcdm::CdmResponseType* error_detail, + wvcdm::CdmResponseType error_code) { + if (error_detail != nullptr) { + *error_detail = error_code; + } +} + } // namespace namespace wvcdm { @@ -200,7 +209,8 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set, } CdmResponseType CdmSession::RestoreOfflineSession( - const CdmKeySetId& key_set_id, CdmLicenseType license_type) { + const CdmKeySetId& key_set_id, CdmLicenseType license_type, + CdmResponseType* error_detail) { if (!initialized_) { LOGE("CdmSession::RestoreOfflineSession: not initialized"); return NOT_INITIALIZED_ERROR; @@ -272,6 +282,7 @@ CdmResponseType CdmSession::RestoreOfflineSession( license_parser_->RestoreLicenseForRelease(key_request_, key_response_); if (result != NO_ERROR) { + SetErrorDetail(error_detail, result); return RELEASE_LICENSE_ERROR_1; } } else { @@ -279,6 +290,7 @@ CdmResponseType CdmSession::RestoreOfflineSession( key_request_, key_response_, offline_key_renewal_response_, playback_start_time, last_playback_time, grace_period_end_time, this); if (result != NO_ERROR) { + SetErrorDetail(error_detail, result); return RESTORE_OFFLINE_LICENSE_ERROR_2; } } @@ -308,7 +320,8 @@ CdmResponseType CdmSession::RestoreOfflineSession( } CdmResponseType CdmSession::RestoreUsageSession( - const DeviceFiles::CdmUsageData& usage_data) { + const DeviceFiles::CdmUsageData& usage_data, + CdmResponseType* error_detail) { if (!initialized_) { LOGE("CdmSession::RestoreUsageSession: not initialized"); return NOT_INITIALIZED_ERROR; @@ -338,6 +351,7 @@ CdmResponseType CdmSession::RestoreUsageSession( sts = license_parser_->RestoreLicenseForRelease(key_request_, key_response_); if (sts != NO_ERROR) { + SetErrorDetail(error_detail, sts); return RELEASE_LICENSE_ERROR_2; } diff --git a/libwvdrmengine/cdm/metrics/include/metrics_collections.h b/libwvdrmengine/cdm/metrics/include/metrics_collections.h index 122320d6..03876e93 100644 --- a/libwvdrmengine/cdm/metrics/include/metrics_collections.h +++ b/libwvdrmengine/cdm/metrics/include/metrics_collections.h @@ -67,6 +67,8 @@ const int kErrorCodeFieldNumber = ::drm_metrics::Attributes::kErrorCodeFieldNumber; const int kErrorCodeBoolFieldNumber = ::drm_metrics::Attributes::kErrorCodeBoolFieldNumber; +const int kErrorDetailFieldNumber = + ::drm_metrics::Attributes::kErrorDetailFieldNumber; const int kCdmSecurityLevelFieldNumber = ::drm_metrics::Attributes::kCdmSecurityLevelFieldNumber; const int kSecurityLevelFieldNumber = @@ -276,9 +278,11 @@ class SessionMetrics { // Metrics collected at the session level. ValueMetric cdm_session_life_span_; // Milliseconds. EventMetric cdm_session_renew_key_; - CounterMetric + CounterMetric cdm_session_restore_offline_session_; - CounterMetric + CounterMetric cdm_session_restore_usage_session_; EventMetric @@ -401,7 +405,8 @@ class EngineMetrics { cdm_engine_get_provisioning_request_; CounterMetric cdm_engine_get_secure_stop_ids_; - EventMetric + EventMetric cdm_engine_get_usage_info_; EventMetric cdm_engine_handle_provisioning_response_; diff --git a/libwvdrmengine/cdm/metrics/src/attribute_handler.cpp b/libwvdrmengine/cdm/metrics/src/attribute_handler.cpp index 70d00aa8..f8ccdac5 100644 --- a/libwvdrmengine/cdm/metrics/src/attribute_handler.cpp +++ b/libwvdrmengine/cdm/metrics/src/attribute_handler.cpp @@ -88,6 +88,14 @@ void SetAttributeFieldset_license_type(license_type); } +template <> +void SetAttributeField( + const CdmResponseType &error_detail, + drm_metrics::Attributes *attributes) { + attributes->set_error_detail(error_detail); +} + template <> void SetAttributeField<0, util::Unused>(const util::Unused &, drm_metrics::Attributes *) { diff --git a/libwvdrmengine/cdm/metrics/src/metrics.proto b/libwvdrmengine/cdm/metrics/src/metrics.proto index c4f13a27..f1aa60aa 100644 --- a/libwvdrmengine/cdm/metrics/src/metrics.proto +++ b/libwvdrmengine/cdm/metrics/src/metrics.proto @@ -48,6 +48,8 @@ message Attributes { optional uint32 key_request_type = 16; // Contains the CdmLicenseType defined in wv_cdm_types.h. optional uint32 license_type = 17; + // Error detail supplemental to the error_code field. + optional int32 error_detail = 18; } // The Counter message is used to store a count value with an associated diff --git a/libwvdrmengine/cdm/metrics/test/metrics_collections_unittest.cpp b/libwvdrmengine/cdm/metrics/test/metrics_collections_unittest.cpp index 2c29907e..60bba090 100644 --- a/libwvdrmengine/cdm/metrics/test/metrics_collections_unittest.cpp +++ b/libwvdrmengine/cdm/metrics/test/metrics_collections_unittest.cpp @@ -41,7 +41,8 @@ TEST_F(EngineMetricsTest, AllEngineMetrics) { engine_metrics.cdm_engine_find_session_for_key_.Increment(false); engine_metrics.cdm_engine_generate_key_request_.Record(1.0, NO_ERROR, kLicenseTypeRelease); engine_metrics.cdm_engine_get_provisioning_request_.Record(1.0, NO_ERROR); - engine_metrics.cdm_engine_get_usage_info_.Record(1.0, NO_ERROR); + engine_metrics.cdm_engine_get_usage_info_.Record(1.0, NO_ERROR, + UNKNOWN_ERROR); engine_metrics.cdm_engine_handle_provisioning_response_.Record(1.0, NO_ERROR); engine_metrics.cdm_engine_open_key_set_session_.Increment(NO_ERROR); engine_metrics.cdm_engine_open_session_.Increment(NO_ERROR); @@ -87,6 +88,12 @@ TEST_F(EngineMetricsTest, AllEngineMetrics) { EXPECT_EQ(OEMCrypto_INITIALIZED_FORCING_L3, actual_metrics.engine_metrics().oemcrypto_initialization_mode() .int_value()); + ASSERT_EQ( + 1, actual_metrics.engine_metrics() + .cdm_engine_get_usage_info_time_us_size()); + + EXPECT_EQ(UNKNOWN_ERROR, actual_metrics.engine_metrics() + .cdm_engine_get_usage_info_time_us(0).attributes().error_detail()); } TEST_F(EngineMetricsTest, EngineAndCryptoMetrics) { @@ -244,8 +251,10 @@ TEST_F(SessionMetricsTest, AllSessionMetrics) { session_metrics.SetSessionId(kSessionId1); session_metrics.cdm_session_life_span_.Record(1.0); session_metrics.cdm_session_renew_key_.Record(1.0, NO_ERROR); - session_metrics.cdm_session_restore_offline_session_.Increment(NO_ERROR); - session_metrics.cdm_session_restore_usage_session_.Increment(NO_ERROR); + session_metrics.cdm_session_restore_offline_session_.Increment(NO_ERROR, + UNKNOWN_ERROR); + session_metrics.cdm_session_restore_usage_session_.Increment(NO_ERROR, + UNKNOWN_ERROR); session_metrics.cdm_session_license_request_latency_ms_.Record( 2.0, kKeyRequestTypeInitial); diff --git a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp index cba2bf50..260ee29e 100644 --- a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp +++ b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp @@ -239,14 +239,16 @@ CdmResponseType WvContentDecryptionModule::GetUsageInfo( const std::string& app_id, const CdmIdentifier& identifier, CdmUsageInfo* usage_info) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier); - return cdm_engine->GetUsageInfo(app_id, usage_info); + CdmResponseType error_detail = NO_ERROR; + return cdm_engine->GetUsageInfo(app_id, &error_detail, usage_info); } CdmResponseType WvContentDecryptionModule::GetUsageInfo( const std::string& app_id, const CdmSecureStopId& ssid, const CdmIdentifier& identifier, CdmUsageInfo* usage_info) { CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier); - return cdm_engine->GetUsageInfo(app_id, ssid, usage_info); + CdmResponseType error_detail = NO_ERROR; + return cdm_engine->GetUsageInfo(app_id, ssid, &error_detail, usage_info); } CdmResponseType WvContentDecryptionModule::RemoveAllUsageInfo(