diff --git a/libwvdrmengine/cdm/core/include/cdm_session.h b/libwvdrmengine/cdm/core/include/cdm_session.h index d5fcb6d3..7cd781cc 100644 --- a/libwvdrmengine/cdm/core/include/cdm_session.h +++ b/libwvdrmengine/cdm/core/include/cdm_session.h @@ -23,6 +23,7 @@ namespace wvcdm { class CdmClientPropertySet; class WvCdmEventListener; +class UsageTableHeader; class CdmSession { public: @@ -37,7 +38,7 @@ class CdmSession { virtual CdmResponseType RestoreOfflineSession( const CdmKeySetId& key_set_id, const CdmLicenseType license_type); virtual CdmResponseType RestoreUsageSession( - const CdmKeyMessage& key_request, const CdmKeyResponse& key_response); + const DeviceFiles::CdmUsageData& usage_data); virtual const CdmSessionId& session_id() { return session_id_; } virtual const CdmKeySetId& key_set_id() { return key_set_id_; } @@ -81,6 +82,9 @@ class CdmSession { // ReleaseKey() - Accept response and release key. virtual CdmResponseType ReleaseKey(const CdmKeyResponse& key_response); + virtual CdmResponseType DeleteUsageEntry( + const DeviceFiles::CdmUsageData& usage_data); + virtual bool IsKeyLoaded(const KeyId& key_id); virtual int64_t GetDurationRemaining(); @@ -99,7 +103,8 @@ class CdmSession { // Delete usage information for the list of tokens, |provider_session_tokens|. virtual CdmResponseType DeleteMultipleUsageInformation( const std::vector& provider_session_tokens); - virtual CdmResponseType UpdateUsageInformation(); + virtual CdmResponseType UpdateUsageTableInformation(); + virtual CdmResponseType UpdateUsageEntryInformation(); virtual bool is_initial_usage_update() { return is_initial_usage_update_; } virtual bool is_usage_update_needed() { return is_usage_update_needed_; } @@ -113,6 +118,9 @@ class CdmSession { virtual bool is_temporary() { return is_temporary_; } virtual bool license_received() { return license_received_; } + virtual CdmUsageSupportType get_usage_support_type() + { return usage_support_type_; } + // ReleaseCrypto() - Closes the underlying crypto session but leaves this // object alive. It is invalid to call any method that requires a crypto // session after calling this. Since calling this renders this object mostly @@ -165,6 +173,8 @@ class CdmSession { CdmResponseType StoreLicense(); bool StoreLicense(DeviceFiles::LicenseState state); + bool UpdateUsageInfo(); + // These setters are for testing only. Takes ownership of the pointers. void set_license_parser(CdmLicense* license_parser); void set_crypto_session(CryptoSession* crypto_session); @@ -197,11 +207,18 @@ class CdmSession { SecurityLevel requested_security_level_; CdmAppParameterMap app_parameters_; - // decryption and usage flags + // decryption flags bool is_initial_decryption_; bool has_decrypted_since_last_report_; // ... last report to policy engine. + + // Usage related flags and data bool is_initial_usage_update_; bool is_usage_update_needed_; + CdmUsageSupportType usage_support_type_; + UsageTableHeader* usage_table_header_; + uint32_t usage_entry_number_; + CdmUsageEntry usage_entry_; + std::string usage_provider_session_token_; // information useful for offline and usage scenarios CdmKeyMessage key_request_; diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index 62be1d78..c996f195 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -290,6 +290,11 @@ enum CdmResponseType { USAGE_STORE_LICENSE_FAILED, USAGE_STORE_USAGE_INFO_FAILED, USAGE_INVALID_LOAD_ENTRY, /* 250 */ + RELEASE_ALL_USAGE_INFO_ERROR_4, + RELEASE_ALL_USAGE_INFO_ERROR_5, + RELEASE_USAGE_INFO_FAILED, + INCORRECT_USAGE_SUPPORT_TYPE_1, + INCORRECT_USAGE_SUPPORT_TYPE_2, /* 255 */ }; enum CdmKeyStatus { diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index 29f52249..f41eee52 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -1043,7 +1043,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, usage_session_.reset(new CdmSession(file_system_)); CdmResponseType status = usage_session_->Init(usage_property_set_.get()); if (NO_ERROR != status) { - LOGE("CdmEngine::GetUsageInfo: session init error"); + LOGE("CdmEngine::GetUsageInfo: session init error: %d", status); return status; } DeviceFiles handle(file_system_); @@ -1055,11 +1055,9 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, CdmKeyMessage license_request; CdmKeyResponse license_response; std::string usage_entry; - uint32_t usage_entry_number = 0; + DeviceFiles::CdmUsageData usage_data; if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id), - ssid, &license_request, - &license_response, &usage_entry, - &usage_entry_number)) { + 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_)); @@ -1073,16 +1071,14 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, return GET_USAGE_INFO_ERROR_2; } if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id), - ssid, &license_request, - &license_response, &usage_entry, - &usage_entry_number)) { + ssid, &usage_data)) { // No entry found for that ssid. return USAGE_INFO_NOT_FOUND; } } status = - usage_session_->RestoreUsageSession(license_request,license_response); + usage_session_->RestoreUsageSession(usage_data); if (KEY_ADDED != status) { LOGE("CdmEngine::GetUsageInfo: restore usage session error %d", status); @@ -1152,9 +1148,9 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, return GET_USAGE_INFO_ERROR_3; } - std::vector > license_info; + std::vector usage_data; if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id), - &license_info)) { + &usage_data)) { LOGE("CdmEngine::GetUsageInfo: unable to read usage information"); return GET_USAGE_INFO_ERROR_4; } @@ -1163,16 +1159,15 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, LOGE("CdmEngine::GetUsageInfo: no usage info destination"); return INVALID_PARAMETERS_ENG_10; } - if (0 == license_info.size()) { + if (0 == usage_data.size()) { usage_info->resize(0); return NO_ERROR; } usage_info->resize(kUsageReportsPerRequest); - uint32_t index = rand() % license_info.size(); - status = usage_session_->RestoreUsageSession(license_info[index].first, - license_info[index].second); + uint32_t index = rand() % usage_data.size(); + status = usage_session_->RestoreUsageSession(usage_data[index]); if (KEY_ADDED != status) { LOGE("CdmEngine::GetUsageInfo: restore usage session (%d) error %ld", index, status); @@ -1212,25 +1207,49 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) { for (int j = kSecurityLevelL1; j < kSecurityLevelUnknown; ++j) { DeviceFiles handle(file_system_); if (handle.Init(static_cast(j))) { - std::vector provider_session_tokens; - if (!handle.DeleteAllUsageInfoForApp( - DeviceFiles::GetUsageInfoFileName(app_id), - &provider_session_tokens)) { - LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete L%d secure" - "stops", j); - status = RELEASE_ALL_USAGE_INFO_ERROR_1; - } else { - SecurityLevel security_level = - static_cast(j) == kSecurityLevelL3 - ? kLevel3 - : kLevelDefault; - usage_property_set_->set_security_level(security_level); - usage_session_.reset(new CdmSession(file_system_)); - usage_session_->Init(usage_property_set_.get()); - CdmResponseType status2 = usage_session_-> - DeleteMultipleUsageInformation(provider_session_tokens); - if (status2 != NO_ERROR) { - status = status2; + SecurityLevel security_level = + static_cast(j) == kSecurityLevelL3 + ? kLevel3 + : kLevelDefault; + usage_property_set_->set_security_level(security_level); + usage_session_.reset(new CdmSession(file_system_)); + usage_session_->Init(usage_property_set_.get()); + + if (usage_session_->get_usage_support_type() == kUsageEntrySupport) { + std::vector usage_data; + if (!handle.RetrieveUsageInfo( + DeviceFiles::GetUsageInfoFileName(app_id), + &usage_data)) { + status = RELEASE_ALL_USAGE_INFO_ERROR_4; + } else { + for (size_t k = 0; k < usage_data.size(); ++k) { + CdmResponseType status2 = + usage_session_->DeleteUsageEntry(usage_data[k]); + if (status == NO_ERROR && status2 != NO_ERROR) + status = status2; + } + } + std::vector provider_session_tokens; + if (!handle.DeleteAllUsageInfoForApp( + DeviceFiles::GetUsageInfoFileName(app_id), + &provider_session_tokens)) { + status = RELEASE_ALL_USAGE_INFO_ERROR_5; + } + } else if (usage_session_->get_usage_support_type() + == kUsageTableSupport) { + std::vector provider_session_tokens; + if (!handle.DeleteAllUsageInfoForApp( + DeviceFiles::GetUsageInfoFileName(app_id), + &provider_session_tokens)) { + LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete L%d secure" + "stops", j); + status = RELEASE_ALL_USAGE_INFO_ERROR_1; + } else { + CdmResponseType status2 = usage_session_-> + DeleteMultipleUsageInformation(provider_session_tokens); + if (status2 != NO_ERROR) { + status = status2; + } } } } else { @@ -1291,24 +1310,20 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id, std::string app_id; iter->second->GetApplicationId(&app_id); - std::string provider_session_token; - CdmKeyMessage key_message; - CdmKeyResponse key_response; - std::string usage_entry; - uint32_t usage_entry_number = 0; + DeviceFiles::CdmUsageData usage_data; if (!handle.RetrieveUsageInfoByKeySetId( DeviceFiles::GetUsageInfoFileName(app_id), key_set_id, - &provider_session_token, &key_message, &key_response, - &usage_entry, &usage_entry_number)) { + &(usage_data.provider_session_token), + &(usage_data.license_request), + &(usage_data.license), &(usage_data.usage_entry), + &(usage_data.usage_entry_number))) { LOGE("CdmEngine::LoadUsageSession: unable to find usage information"); return LOAD_USAGE_INFO_MISSING; } CdmResponseType status; M_TIME( - status = iter->second->RestoreUsageSession( - key_message, - key_response), + status = iter->second->RestoreUsageSession(usage_data), iter->second->GetMetrics(), cdm_session_restore_usage_session_, status); @@ -1605,19 +1620,24 @@ void CdmEngine::OnTimerEvent() { for (CdmSessionMap::iterator iter = sessions_.begin(); iter != sessions_.end(); ++iter) { iter->second->reset_usage_flags(); + if (iter->second->get_usage_support_type() == kUsageEntrySupport) + iter->second->UpdateUsageEntryInformation(); + if (!has_usage_been_updated) { // usage is updated for all sessions so this needs to be // called only once per update usage information period - CdmResponseType status; - M_TIME( - status = iter->second->UpdateUsageInformation(), - iter->second->GetMetrics(), - cdm_session_update_usage_information_, - status); - if (NO_ERROR != status) { - LOGW("Update usage information failed: %d", status); - } else { - has_usage_been_updated = true; + if (iter->second->get_usage_support_type() == kUsageTableSupport) { + CdmResponseType status; + M_TIME( + status = iter->second->UpdateUsageTableInformation(), + iter->second->GetMetrics(), + cdm_session_update_usage_information_, + status); + if (NO_ERROR != status) { + LOGW("Update usage information failed: %d", status); + } else { + has_usage_been_updated = true; + } } } } diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index 5305b90c..fa40fe1d 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -17,6 +17,7 @@ #include "string_conversions.h" #include "wv_cdm_constants.h" #include "wv_cdm_event_listener.h" +#include "usage_table_header.h" namespace { const size_t kKeySetIdLength = 14; @@ -38,8 +39,20 @@ CdmSession::CdmSession(FileSystem* file_system) : has_decrypted_since_last_report_(false), is_initial_usage_update_(true), is_usage_update_needed_(false), + usage_support_type_(kNonSecureUsageSupport), + usage_table_header_(NULL), + usage_entry_number_(0), mock_license_parser_in_use_(false), mock_policy_engine_in_use_(false) { + CdmResponseType sts = + crypto_session_->GetUsageSupportType(&usage_support_type_); + + if (sts != NO_ERROR) { + LOGW("CdmSession::CdmSession: Failed to get usage support type"); + } + if (usage_support_type_ == kUsageEntrySupport) + usage_table_header_ = UsageTableHeader::GetInstance(file_system, + crypto_session_.get()); life_span_.Start(); } @@ -178,28 +191,37 @@ CdmResponseType CdmSession::RestoreOfflineSession( int64_t playback_start_time; int64_t last_playback_time; int64_t grace_period_end_time; - std::string usage_entry; - uint32_t usage_entry_number = 0; if (!file_handle_->RetrieveLicense( key_set_id, &license_state, &offline_init_data_, &key_request_, &key_response_, &offline_key_renewal_request_, &offline_key_renewal_response_, &offline_release_server_url_, &playback_start_time, &last_playback_time, &grace_period_end_time, - &app_parameters_, &usage_entry, &usage_entry_number)) { - LOGE("CdmSession::Init failed to retrieve license. key set id = %s", - key_set_id.c_str()); + &app_parameters_, &usage_entry_, &usage_entry_number_)) { + LOGE("CdmSession::RestoreOfflineSession: failed to retrieve license. " + "key set id = %s", key_set_id.c_str()); return GET_LICENSE_ERROR; } // Do not restore a released offline license, unless a release retry if (!(license_type == kLicenseTypeRelease || license_state == DeviceFiles::kLicenseStateActive)) { - LOGE("CdmSession::Init invalid offline license state = %d, type = %d", - license_state, license_type); + LOGE("CdmSession::RestoreOfflineSession: invalid offline license state = " + "%d, type = %d", license_state, license_type); return GET_RELEASED_LICENSE_ERROR; } + 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_type == kLicenseTypeRelease) { if (!license_parser_->RestoreLicenseForRelease(key_request_, key_response_)) { @@ -213,6 +235,20 @@ CdmResponseType CdmSession::RestoreOfflineSession( } } + if (usage_support_type_ == kUsageEntrySupport) { + CdmResponseType sts = + usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_); + if (sts != NO_ERROR) { + LOGE("CdmSession::RestoreOfflineSession failed to update usage entry = " + "%d", sts); + return sts; + } + if (!StoreLicense(license_state)) { + LOGW("CdmSession::RestoreUsageSession: unable to save updated usage " + "info"); + } + } + license_received_ = true; is_offline_ = true; is_release_ = license_type == kLicenseTypeRelease; @@ -220,14 +256,45 @@ CdmResponseType CdmSession::RestoreOfflineSession( } CdmResponseType CdmSession::RestoreUsageSession( - const CdmKeyMessage& key_request, const CdmKeyResponse& key_response) { - key_request_ = key_request; - key_response_ = key_response; + const DeviceFiles::CdmUsageData& usage_data) { + if (!key_set_id_.empty()) { + file_handle_->UnreserveLicenseId(key_set_id_); + } + key_set_id_ = usage_data.key_set_id; + key_request_ = usage_data.license_request; + key_response_ = usage_data.license; + usage_entry_ = usage_data.usage_entry; + usage_entry_number_ = usage_data.usage_entry_number; + usage_provider_session_token_ = usage_data.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::RestoreUsageSession: failed to load usage entry = %d", + sts); + return sts; + } + } if (!license_parser_->RestoreLicenseForRelease(key_request_, key_response_)) { return RELEASE_LICENSE_ERROR_2; } + if (usage_support_type_ == kUsageEntrySupport) { + CdmResponseType sts = + usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_); + if (sts != NO_ERROR) { + LOGE("CdmSession::RestoreUsageSession: failed to update usage entry: %d", + sts); + return sts; + } + if (!UpdateUsageInfo()) { + LOGW("CdmSession::RestoreUsageSession: unable to save updated usage " + "info"); + } + } + license_received_ = true; is_offline_ = false; is_release_ = true; @@ -353,7 +420,36 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) { } else if (license_received_) { // renewal return RenewKey(key_response); } else { - CdmResponseType sts = license_parser_->HandleKeyResponse(key_response); + // If usage table header+entries are supported, preprocess the license + // to see if it has a provider session token. If so a new entry needs + // to be created. + CdmResponseType sts; + std::string provider_session_token; + if (usage_support_type_ == kUsageEntrySupport) { + if (license_parser_->ExtractProviderSessionToken( + key_response, &provider_session_token) && + !provider_session_token.empty()) { + std::string app_id; + GetApplicationId(&app_id); + sts = usage_table_header_->AddEntry( + crypto_session_.get(), is_offline_, key_set_id_, + DeviceFiles::GetUsageInfoFileName(app_id), &usage_entry_number_); + if (sts != NO_ERROR) return sts; + } + } + sts = license_parser_->HandleKeyResponse(key_response); + + // Update or delete entry if usage table header+entries are supported + if (usage_support_type_ == kUsageEntrySupport && + !provider_session_token.empty()) { + if (sts != KEY_ADDED) { + CdmResponseType sts = + usage_table_header_->DeleteEntry(usage_entry_number_); + if (sts != NO_ERROR) { + LOGW("CdmSession::AddKey: Delete usage entry failed = %d", sts); + } + } + } if (sts != KEY_ADDED) return (sts == KEY_ERROR) ? ADD_KEY_ERROR : sts; @@ -361,6 +457,13 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) { key_response_ = key_response; if (is_offline_ || !license_parser_->provider_session_token().empty()) { + if (usage_support_type_ == kUsageEntrySupport) + usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_); + + if (!is_offline_) + usage_provider_session_token_ = + license_parser_->provider_session_token(); + sts = StoreLicense(); if (sts != NO_ERROR) return sts; } @@ -522,9 +625,24 @@ CdmResponseType CdmSession::GenerateReleaseRequest( if (KEY_MESSAGE != status) return status; + if (usage_support_type_ == kUsageEntrySupport) { + status = usage_table_header_->UpdateEntry(crypto_session_.get(), + &usage_entry_); + if (status != NO_ERROR) { + LOGE("CdmSession::GenerateReleaseRequest: Update usage entry failed = " + "%d", status); + return status; + } + } + if (is_offline_) { // Mark license as being released if (!StoreLicense(DeviceFiles::kLicenseStateReleasing)) return RELEASE_KEY_REQUEST_ERROR; + } else if (!usage_provider_session_token_.empty()) { + if (usage_support_type_ == kUsageEntrySupport) { + if (!UpdateUsageInfo()) + return RELEASE_USAGE_INFO_FAILED; + } } return KEY_MESSAGE; } @@ -537,10 +655,41 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) { if (is_offline_ || !license_parser_->provider_session_token().empty()) { DeleteLicense(); + + // Deletion of usage entry cannot occur while in use by a crypto session. + // So close and reopen after deletion. + if (usage_support_type_ == kUsageEntrySupport) { + M_TIME( + crypto_session_->Close(), + &metrics_, + crypto_session_close_); + + CdmResponseType sts = usage_table_header_->DeleteEntry(usage_entry_number_); + if (sts != NO_ERROR) return sts; + + M_TIME( + sts = crypto_session_->Open(requested_security_level_), + &metrics_, + crypto_session_open_, + sts, + requested_security_level_); + if (NO_ERROR != sts) return sts; + } } return NO_ERROR; } +CdmResponseType CdmSession::DeleteUsageEntry( + const DeviceFiles::CdmUsageData& usage_data) { + if (usage_support_type_ != kUsageEntrySupport) { + LOGE("CdmSession::DeleteUsageEntry: Unexpected usage type supported: %d", + usage_support_type_); + return INCORRECT_USAGE_SUPPORT_TYPE_1; + } + + return usage_table_header_->DeleteEntry(usage_data.usage_entry_number); +} + bool CdmSession::IsKeyLoaded(const KeyId& key_id) { return license_parser_->IsKeyLoaded(key_id); } @@ -624,13 +773,11 @@ CdmResponseType CdmSession::StoreLicense() { std::string app_id; GetApplicationId(&app_id); - std::string usage_entry; - uint32_t usage_entry_number = 0; if (!file_handle_->StoreUsageInfo(provider_session_token, key_request_, key_response_, DeviceFiles::GetUsageInfoFileName(app_id), - key_set_id_, usage_entry, - usage_entry_number)) { + key_set_id_, usage_entry_, + usage_entry_number_)) { LOGE("CdmSession::StoreLicense: Unable to store usage info"); return STORE_USAGE_INFO_ERROR; } @@ -638,15 +785,13 @@ CdmResponseType CdmSession::StoreLicense() { } bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) { - std::string usage_entry; - uint32_t usage_entry_number = 0; return file_handle_->StoreLicense( key_set_id_, state, offline_init_data_, key_request_, key_response_, offline_key_renewal_request_, offline_key_renewal_response_, offline_release_server_url_, policy_engine_->GetPlaybackStartTime(), policy_engine_->GetLastPlaybackTime(), - policy_engine_->GetGracePeriodEndTime(), app_parameters_, usage_entry, - usage_entry_number); + policy_engine_->GetGracePeriodEndTime(), app_parameters_, usage_entry_, + usage_entry_number_); } CdmResponseType CdmSession::ReleaseCrypto() { @@ -712,7 +857,7 @@ CdmResponseType CdmSession::DeleteMultipleUsageInformation( return sts; } -CdmResponseType CdmSession::UpdateUsageInformation() { +CdmResponseType CdmSession::UpdateUsageTableInformation() { CdmResponseType sts; M_TIME( sts = crypto_session_->UpdateUsageInformation(), @@ -722,6 +867,28 @@ CdmResponseType CdmSession::UpdateUsageInformation() { return sts; } +CdmResponseType CdmSession::UpdateUsageEntryInformation() { + if (usage_support_type_ != kUsageEntrySupport) { + LOGE("CdmSession::UpdateUsageEntryInformation: Unexpected usage type " + "supported: %d", usage_support_type_); + return INCORRECT_USAGE_SUPPORT_TYPE_2; + } + + CdmResponseType sts = usage_table_header_->UpdateEntry(crypto_session_.get(), + &usage_entry_); + + if (sts != NO_ERROR) return sts; + + if (is_offline_) + StoreLicense(is_release_ + ? DeviceFiles::kLicenseStateReleasing + : DeviceFiles::kLicenseStateActive); + else if (!usage_provider_session_token_.empty()) + UpdateUsageInfo(); + + return NO_ERROR; +} + CdmResponseType CdmSession::GenericEncrypt(const std::string& in_buffer, const std::string& key_id, const std::string& iv, @@ -814,6 +981,24 @@ CdmResponseType CdmSession::GenericVerify(const std::string& message, return sts; } +bool CdmSession::UpdateUsageInfo() { + std::string app_id; + GetApplicationId(&app_id); + + DeviceFiles::CdmUsageData usage_data; + usage_data.provider_session_token = usage_provider_session_token_; + usage_data.license_request = key_request_; + usage_data.license = key_response_; + usage_data.key_set_id = key_set_id_; + usage_data.usage_entry = usage_entry_; + usage_data.usage_entry_number = usage_entry_number_; + + return file_handle_->UpdateUsageInfo( + DeviceFiles::GetUsageInfoFileName(app_id), + usage_provider_session_token_, + usage_data); +} + // For testing only - takes ownership of pointers void CdmSession::set_license_parser(CdmLicense* license_parser) { diff --git a/libwvdrmengine/cdm/core/test/test_printers.cpp b/libwvdrmengine/cdm/core/test/test_printers.cpp index bed9f72a..b37bae99 100644 --- a/libwvdrmengine/cdm/core/test/test_printers.cpp +++ b/libwvdrmengine/cdm/core/test/test_printers.cpp @@ -554,6 +554,20 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) { break; case USAGE_INVALID_LOAD_ENTRY: *os << "USAGE_INVALID_LOAD_ENTRY"; break; + case RELEASE_ALL_USAGE_INFO_ERROR_4: + *os << "RELEASE_ALL_USAGE_INFO_ERROR_4"; + break; + case RELEASE_ALL_USAGE_INFO_ERROR_5: + *os << "RELEASE_ALL_USAGE_INFO_ERROR_5"; + break; + case RELEASE_USAGE_INFO_FAILED: *os << "RELEASE_USAGE_INFO_FAILED"; + break; + case INCORRECT_USAGE_SUPPORT_TYPE_1: + *os << "INCORRECT_USAGE_SUPPORT_TYPE_1"; + break; + case INCORRECT_USAGE_SUPPORT_TYPE_2: + *os << "INCORRECT_USAGE_SUPPORT_TYPE_2"; + break; default: *os << "Unknown CdmResponseType"; diff --git a/libwvdrmengine/include/WVErrors.h b/libwvdrmengine/include/WVErrors.h index e597525c..5e8833ab 100644 --- a/libwvdrmengine/include/WVErrors.h +++ b/libwvdrmengine/include/WVErrors.h @@ -255,10 +255,15 @@ enum { kUsageStoreLicenseFailed = ERROR_DRM_VENDOR_MIN + 241, kUsageStoreUsageInfoFailed = ERROR_DRM_VENDOR_MIN + 242, kUsageInvalidLoadEntry = ERROR_DRM_VENDOR_MIN + 243, + kReleaseAllUsageInfoError4 = ERROR_DRM_VENDOR_MIN + 244, + kReleaseAllUsageInfoError5 = ERROR_DRM_VENDOR_MIN + 245, + kReleaseUsageInfoFailed = ERROR_DRM_VENDOR_MIN + 246, + kIncorrectUsageSupportType1 = ERROR_DRM_VENDOR_MIN + 247, + kIncorrectUsageSupportType2 = ERROR_DRM_VENDOR_MIN + 248, // This should always follow the last error code. // The offset value should be updated each time a new error code is added. - kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 243, + kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 248, // Used by crypto test mode kErrorTestMode = ERROR_DRM_VENDOR_MAX, diff --git a/libwvdrmengine/include/mapErrors-inl.h b/libwvdrmengine/include/mapErrors-inl.h index f18d13e9..f93c9b48 100644 --- a/libwvdrmengine/include/mapErrors-inl.h +++ b/libwvdrmengine/include/mapErrors-inl.h @@ -501,6 +501,16 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) { return kUsageStoreUsageInfoFailed; case wvcdm::USAGE_INVALID_LOAD_ENTRY: return kUsageInvalidLoadEntry; + case wvcdm::RELEASE_ALL_USAGE_INFO_ERROR_4: + return kReleaseAllUsageInfoError4; + case wvcdm::RELEASE_ALL_USAGE_INFO_ERROR_5: + return kReleaseAllUsageInfoError5; + case wvcdm::RELEASE_USAGE_INFO_FAILED: + return kReleaseUsageInfoFailed; + case wvcdm::INCORRECT_USAGE_SUPPORT_TYPE_1: + return kIncorrectUsageSupportType1; + case wvcdm::INCORRECT_USAGE_SUPPORT_TYPE_2: + return kIncorrectUsageSupportType2; case wvcdm::UNUSED_1: case wvcdm::UNUSED_2: