From 7a933ee48e2c45987b408563a9f076073c00bd3d Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Wed, 2 Jul 2014 13:03:09 -0700 Subject: [PATCH] Merge of usage reporting and license changes from WV CDM repo * CdmSession unittest and license request time changes b/15914199 Merge of https://widevine-internal-review.googlesource.com/#/c/10597/ * Specify OEMCrypto API version in client capabilities b/15388863 Merge of https://widevine-internal-review.googlesource.com/#/c/10616/ * Report start and last play time in license request b/15995227 Merge of https://widevine-internal-review.googlesource.com/#/c/10617/ * Respect can_play flag b/15330338 Merge of https://widevine-internal-review.googlesource.com/#/c/10619/ * Restore offline session information b/16009274 Merge of https://widevine-internal-review.googlesource.com/#/c/10641/ Change-Id: I17fdc309efbc1d44385a86a368df11b1349b29c2 --- .../build_and_run_all_unit_tests.sh | 1 + libwvdrmengine/cdm/core/include/cdm_session.h | 33 +- .../cdm/core/include/crypto_session.h | 29 +- .../cdm/core/include/device_files.h | 17 +- libwvdrmengine/cdm/core/include/license.h | 18 +- .../cdm/core/include/policy_engine.h | 26 +- libwvdrmengine/cdm/core/include/properties.h | 8 + libwvdrmengine/cdm/core/src/cdm_engine.cpp | 2 +- libwvdrmengine/cdm/core/src/cdm_session.cpp | 205 ++-- .../cdm/core/src/crypto_session.cpp | 130 ++- libwvdrmengine/cdm/core/src/device_files.cpp | 28 +- .../cdm/core/src/device_files.proto | 2 + libwvdrmengine/cdm/core/src/license.cpp | 156 ++- .../cdm/core/src/license_protocol.proto | 9 +- .../core/src/oemcrypto_adapter_static_v8.cpp | 2 +- libwvdrmengine/cdm/core/src/policy_engine.cpp | 80 +- .../cdm/core/test/device_files_unittest.cpp | 913 +++++++++--------- .../cdm/core/test/policy_engine_unittest.cpp | 341 ++++++- 18 files changed, 1308 insertions(+), 692 deletions(-) diff --git a/libwvdrmengine/build_and_run_all_unit_tests.sh b/libwvdrmengine/build_and_run_all_unit_tests.sh index b6ed9369..0ee23c09 100755 --- a/libwvdrmengine/build_and_run_all_unit_tests.sh +++ b/libwvdrmengine/build_and_run_all_unit_tests.sh @@ -53,6 +53,7 @@ adb push $OUT/system/bin/policy_engine_unittest /system/bin adb push $OUT/system/bin/libwvdrmmediacrypto_test /system/bin adb push $OUT/system/bin/libwvdrmdrmplugin_test /system/bin adb push $OUT/system/bin/cdm_engine_test /system/bin +adb push $OUT/system/bin/cdm_session_unittest /system/bin adb push $OUT/system/bin/file_store_unittest /system/bin adb push $OUT/system/bin/device_files_unittest /system/bin adb push $OUT/system/bin/timer_unittest /system/bin diff --git a/libwvdrmengine/cdm/core/include/cdm_session.h b/libwvdrmengine/cdm/core/include/cdm_session.h index a675b5cb..9aee1060 100644 --- a/libwvdrmengine/cdm/core/include/cdm_session.h +++ b/libwvdrmengine/cdm/core/include/cdm_session.h @@ -31,11 +31,6 @@ class CdmSession { virtual CdmResponseType RestoreUsageSession( const CdmKeyMessage& key_request, const CdmKeyResponse& key_response); - virtual void set_key_system(const CdmKeySystem& ksystem) { - key_system_ = ksystem; - } - virtual const CdmKeySystem& key_system() { return key_system_; } - virtual const CdmSessionId& session_id() { return session_id_; } virtual CdmResponseType GenerateKeyRequest( @@ -85,7 +80,7 @@ class CdmSession { virtual bool AttachEventListener(WvCdmEventListener* listener); virtual bool DetachEventListener(WvCdmEventListener* listener); - virtual void OnTimerEvent(); + virtual void OnTimerEvent(bool update_usage); virtual void OnKeyReleaseEvent(const CdmKeySetId& key_set_id); virtual SecurityLevel GetRequestedSecurityLevel(); @@ -99,6 +94,11 @@ class CdmSession { } private: + // Internal constructor + void Create(CdmLicense* license_parser, CryptoSession* crypto_session, + PolicyEngine* policy_engine, DeviceFiles* file_handle, + const CdmClientPropertySet* cdm_client_property_set); + // Generate unique ID for each new session. CdmSessionId GenerateSessionId(); bool GenerateKeySetId(CdmKeySetId* key_set_id); @@ -108,16 +108,19 @@ class CdmSession { bool DeleteLicense(); // instance variables - const CdmSessionId session_id_; - CdmKeySystem key_system_; - CdmLicense license_parser_; + bool initialized_; + CdmSessionId session_id_; + scoped_ptr license_parser_; scoped_ptr crypto_session_; - PolicyEngine policy_engine_; + scoped_ptr policy_engine_; + scoped_ptr file_handle_; bool license_received_; bool is_offline_; bool is_release_; bool is_usage_update_needed_; bool is_initial_decryption_; + bool has_decrypted_recently_; + CdmSecurityLevel security_level_; // information useful for offline and usage scenarios CdmKeyMessage key_request_; @@ -134,6 +137,16 @@ class CdmSession { std::set listeners_; + // For testing only + // Takes ownership of license_parser, crypto_session, policy_engine + // and device_files + CdmSession(CdmLicense* license_parser, CryptoSession* crypto_session, + PolicyEngine* policy_engine, DeviceFiles* file_handle, + const CdmClientPropertySet* cdm_client_property_set); +#if defined(UNIT_TEST) + friend class CdmSessionTest; +#endif + CORE_DISALLOW_COPY_AND_ASSIGN(CdmSession); }; diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index d19b20d3..e2f674d1 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -18,6 +18,24 @@ typedef std::map CryptoKeyMap; class CryptoSession { public: + // This enum should be kept in sync with the values specified for + // HDCP capabilities in OEMCryptoCENC.h. (See comments for + // OEMCrypto_GetHDCPCapability) + typedef enum { + kOemCryptoHdcpNotSupported = 0, + kOemCryptoHdcpVersion1 = 1, + kOemCryptoHdcpVersion2 = 2, + kOemCryptoHdcpVersion2_1 = 3, + kOemCryptoHdcpVersion2_2 = 4, + kOemCryptoNoHdcpDeviceAttached = 0xff, + } OemCryptoHdcpVersion; + + typedef enum { + kUsageDurationsInvalid = 0, + kUsageDurationPlaybackNotBegun = 1, + kUsageDurationsValid = 2, + } UsageDurationStatus; + CryptoSession(); virtual ~CryptoSession(); @@ -37,7 +55,7 @@ class CryptoSession { virtual CryptoSessionId oec_session_id() { return oec_session_id_; } // Key request/response - virtual void GenerateRequestId(std::string& req_id_str); + virtual bool GenerateRequestId(std::string* req_id_str); virtual bool PrepareRequest(const std::string& key_deriv_message, bool is_provisioning, std::string* signature); virtual bool PrepareRenewalRequest(const std::string& message, @@ -66,13 +84,20 @@ class CryptoSession { // Media data path virtual CdmResponseType Decrypt(const CdmDecryptionParameters& parameters); + virtual bool UsageInformationSupport(bool* has_support); virtual CdmResponseType UpdateUsageInformation(); + virtual CdmResponseType DeactivateUsageInformation( + const std::string& provider_session_token); virtual CdmResponseType GenerateUsageReport( - const std::string& provider_session_token, std::string* usage_report); + const std::string& provider_session_token, std::string* usage_report, + UsageDurationStatus* usage_duration_status, + int64_t* seconds_since_started, int64_t* seconds_since_last_played); virtual CdmResponseType ReleaseUsageInformation( const std::string& message, const std::string& signature, const std::string& provider_session_token); + virtual bool GetHdcpCapabilities(OemCryptoHdcpVersion* current, + OemCryptoHdcpVersion* max); virtual bool GetRandom(size_t data_length, uint8_t* random_data); private: diff --git a/libwvdrmengine/cdm/core/include/device_files.h b/libwvdrmengine/cdm/core/include/device_files.h index fe03a32e..898cdbd6 100644 --- a/libwvdrmengine/cdm/core/include/device_files.h +++ b/libwvdrmengine/cdm/core/include/device_files.h @@ -3,6 +3,7 @@ #ifndef WVCDM_CORE_DEVICE_FILES_H_ #define WVCDM_CORE_DEVICE_FILES_H_ +#include "scoped_ptr.h" #include "wv_cdm_types.h" #if defined(UNIT_TEST) @@ -21,11 +22,13 @@ class DeviceFiles { kLicenseStateUnknown, } LicenseState; - DeviceFiles(): file_(NULL), security_level_(kSecurityLevelUninitialized), - initialized_(false), test_file_(false) {} + DeviceFiles(); virtual ~DeviceFiles(); virtual bool Init(CdmSecurityLevel security_level); + virtual bool Reset(CdmSecurityLevel security_level) { + return Init(security_level); + } virtual bool StoreCertificate(const std::string& certificate, const std::string& wrapped_private_key); @@ -39,7 +42,9 @@ class DeviceFiles { const CdmKeyResponse& key_response, const CdmKeyMessage& key_renewal_request, const CdmKeyResponse& key_renewal_response, - const std::string& release_server_url); + const std::string& release_server_url, + int64_t playback_start_time, + int64_t last_playback_time); virtual bool RetrieveLicense(const std::string& key_set_id, LicenseState* state, CdmInitData* pssh_data, @@ -47,7 +52,9 @@ class DeviceFiles { CdmKeyResponse* key_response, CdmKeyMessage* key_renewal_request, CdmKeyResponse* key_renewal_response, - std::string* release_server_url); + std::string* release_server_url, + int64_t* playback_start_time, + int64_t* last_playback_time); virtual bool DeleteLicense(const std::string& key_set_id); virtual bool DeleteAllFiles(); virtual bool DeleteAllLicenses(); @@ -93,7 +100,7 @@ class DeviceFiles { FRIEND_TEST(WvCdmUsageInfoTest, DISABLED_UsageInfo); #endif - File* file_; + scoped_ptr file_; CdmSecurityLevel security_level_; bool initialized_; diff --git a/libwvdrmengine/cdm/core/include/license.h b/libwvdrmengine/cdm/core/include/license.h index 54fc8286..01013a64 100644 --- a/libwvdrmengine/cdm/core/include/license.h +++ b/libwvdrmengine/cdm/core/include/license.h @@ -6,6 +6,7 @@ #include #include "initialization_data.h" +#include "scoped_ptr.h" #include "wv_cdm_types.h" namespace video_widevine_server { @@ -16,14 +17,15 @@ class SignedMessage; namespace wvcdm { +class Clock; class CryptoSession; class PolicyEngine; class CdmLicense { public: - CdmLicense() : session_(NULL), initialized_(false) {} - virtual ~CdmLicense() {} + CdmLicense(); + virtual ~CdmLicense(); virtual bool Init(const std::string& token, CryptoSession* session, PolicyEngine* policy_engine); @@ -42,7 +44,9 @@ class CdmLicense { virtual bool RestoreOfflineLicense(const CdmKeyMessage& license_request, const CdmKeyResponse& license_response, - const CdmKeyResponse& license_renewal_response); + const CdmKeyResponse& license_renewal_response, + int64_t playback_start_time, + int64_t last_playback_time); virtual bool RestoreUsageLicense(const CdmKeyMessage& license_request, const CdmKeyResponse& license_response); virtual bool HasInitData() { return !stored_init_data_.empty(); } @@ -76,6 +80,14 @@ class CdmLicense { // Used for certificate based licensing CdmKeyMessage key_request_; + scoped_ptr clock_; + + // For testing + CdmLicense(Clock* clock); +#if defined(UNIT_TEST) + friend class CdmLicenseTest; +#endif + CORE_DISALLOW_COPY_AND_ASSIGN(CdmLicense); }; diff --git a/libwvdrmengine/cdm/core/include/policy_engine.h b/libwvdrmengine/cdm/core/include/policy_engine.h index 43555cd4..088e6577 100644 --- a/libwvdrmengine/cdm/core/include/policy_engine.h +++ b/libwvdrmengine/cdm/core/include/policy_engine.h @@ -44,6 +44,7 @@ class PolicyEngine { // Call this on first decrypt to set the start of playback. virtual void BeginDecryption(void); + virtual void DecryptionEvent(void); // UpdateLicense is used in handling a license response for a renewal request. // The response may only contain any policy fields that have changed. In this @@ -60,9 +61,21 @@ class PolicyEngine { bool IsLicenseDurationExpired(int64_t current_time); bool IsPlaybackDurationExpired(int64_t current_time); + bool GetSecondsSinceStarted(int64_t* seconds_since_started); + bool GetSecondsSinceLastPlayed(int64_t* seconds_since_started); + + // for offline save and restore + int64_t GetPlaybackStartTime() { return playback_start_time_; } + int64_t GetLastPlaybackTime() { return last_playback_time_; } + void RestorePlaybackTimes(int64_t playback_start_time, + int64_t last_playback_time); + + bool IsLicenseForFuture() { return license_state_ == kLicenseStatePending; } + private: typedef enum { kLicenseStateInitial, + kLicenseStatePending, // if license is issued for sometime in the future kLicenseStateCanPlay, kLicenseStateNeedRenewal, kLicenseStateWaitingLicenseUpdate, @@ -92,18 +105,15 @@ class PolicyEngine { // from the license server we will get an updated id field. video_widevine_server::sdk::LicenseIdentification license_id_; - // This is the license start time that gets sent from the server in each - // license request or renewal. + // The server returns the license start time in the license/license renewal + // response based off the request time sent by the client in the + // license request/renewal int64_t license_start_time_; - - // This is the time at which the license was received and playback was - // started. These times are based off the local clock in case there is a - // discrepency between local and server time. - int64_t license_received_time_; int64_t playback_start_time_; + int64_t last_playback_time_; // This is used as a reference point for policy management. This value - // represents an offset from license_received_time_. This is used to + // represents an offset from license_start_time_. This is used to // calculate the time where renewal retries should occur. int64_t next_renewal_time_; int64_t policy_max_duration_seconds_; diff --git a/libwvdrmengine/cdm/core/include/properties.h b/libwvdrmengine/cdm/core/include/properties.h index f5406e0f..cb0709cb 100644 --- a/libwvdrmengine/cdm/core/include/properties.h +++ b/libwvdrmengine/cdm/core/include/properties.h @@ -87,6 +87,14 @@ class Properties { security_level_path_backward_compatibility_support_ = flag; } +#if defined(UNIT_TEST) + FRIEND_TEST(CdmSessionTest, InitWithCertificate); + FRIEND_TEST(CdmSessionTest, InitWithKeybox); + FRIEND_TEST(CdmSessionTest, ReInitFail); + FRIEND_TEST(CdmSessionTest, InitFailCryptoError); + FRIEND_TEST(CdmSessionTest, InitNeedsProvisioning); +#endif + private: static bool oem_crypto_use_secure_buffers_; static bool oem_crypto_use_fifo_; diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index d136ac57..22b2c4c4 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -702,7 +702,7 @@ void CdmEngine::OnTimerEvent() { for (CdmSessionMap::iterator iter = sessions_.begin(); iter != sessions_.end(); ++iter) { - iter->second->OnTimerEvent(); + iter->second->OnTimerEvent(update_usage_information); if (update_usage_information && iter->second->is_usage_update_needed()) { // usage is updated for all sessions so this needs to be diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index cad53517..0ce4d2f8 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -25,46 +25,96 @@ namespace wvcdm { typedef std::set::iterator CdmEventListenerIter; -CdmSession::CdmSession(const CdmClientPropertySet* cdm_client_property_set) - : session_id_(GenerateSessionId()), - crypto_session_(NULL), - license_received_(false), - is_offline_(false), - is_release_(false), - is_usage_update_needed_(false), - is_initial_decryption_(true) { +CdmSession::CdmSession(const CdmClientPropertySet* cdm_client_property_set) { + Create(new CdmLicense(), new CryptoSession(), new PolicyEngine(), + new DeviceFiles(), cdm_client_property_set); +} + +CdmSession::CdmSession( + CdmLicense* license_parser, + CryptoSession* crypto_session, + PolicyEngine* policy_engine, + DeviceFiles* file_handle, + const CdmClientPropertySet* cdm_client_property_set) { + Create(license_parser, crypto_session, policy_engine, file_handle, + cdm_client_property_set); +} + +void CdmSession::Create( + CdmLicense* license_parser, + CryptoSession* crypto_session, + PolicyEngine* policy_engine, + DeviceFiles* file_handle, + const CdmClientPropertySet* cdm_client_property_set) { + // Just return on failures. Failures will be signaled in Init. + if (NULL == license_parser) { + LOGE("CdmSession::Create: License parser not provided"); + return; + } + if (NULL == crypto_session) { + LOGE("CdmSession::Create: Crypto session not provided"); + return; + } + if (NULL == policy_engine) { + LOGE("CdmSession::Create: Policy engine not provided"); + return; + } + if (NULL == file_handle) { + LOGE("CdmSession::Create: Device files not provided"); + return; + } + initialized_ = false; + session_id_ = GenerateSessionId(); + license_parser_.reset(license_parser); + crypto_session_.reset(crypto_session); + file_handle_.reset(file_handle); + policy_engine_.reset(policy_engine); + license_received_ = false; + is_offline_ = false; + is_release_ = false; + is_usage_update_needed_ = false; + is_initial_decryption_ = true; + has_decrypted_recently_ = false; if (cdm_client_property_set) { Properties::AddSessionPropertySet(session_id_, cdm_client_property_set); } + security_level_ = GetRequestedSecurityLevel() == kLevel3 + ? kSecurityLevelL3 : GetSecurityLevel(); } CdmSession::~CdmSession() { Properties::RemoveSessionPropertySet(session_id_); } CdmResponseType CdmSession::Init() { - scoped_ptr session(new CryptoSession()); - - CdmResponseType sts = session->Open(GetRequestedSecurityLevel()); + if (session_id_.empty()) { + LOGE("CdmSession::Init: Failed, session not properly constructed"); + return UNKNOWN_ERROR; + } + if (initialized_) { + LOGE("CdmSession::Init: Failed due to previous initialization"); + return UNKNOWN_ERROR; + } + CdmResponseType sts = crypto_session_->Open(GetRequestedSecurityLevel()); if (NO_ERROR != sts) return sts; std::string token; if (Properties::use_certificates_as_identification()) { - DeviceFiles handle; std::string wrapped_key; - if (!handle.Init(session.get()->GetSecurityLevel()) || - !handle.RetrieveCertificate(&token, &wrapped_key) || - !session->LoadCertificatePrivateKey(wrapped_key)) { + if (!file_handle_->Init(security_level_) || + !file_handle_->RetrieveCertificate(&token, &wrapped_key) || + !crypto_session_->LoadCertificatePrivateKey(wrapped_key)) { return NEED_PROVISIONING; } } else { - if (!session->GetToken(&token)) return UNKNOWN_ERROR; + if (!crypto_session_->GetToken(&token)) return UNKNOWN_ERROR; } - if (!license_parser_.Init(token, session.get(), &policy_engine_)) + if (!license_parser_->Init(token, crypto_session_.get(), + policy_engine_.get())) return UNKNOWN_ERROR; - crypto_session_.reset(session.release()); license_received_ = false; is_initial_decryption_ = true; + initialized_ = true; return NO_ERROR; } @@ -73,17 +123,21 @@ CdmResponseType CdmSession::RestoreOfflineSession( key_set_id_ = key_set_id; // Retrieve license information from persistent store - DeviceFiles handle; - if (!handle.Init(crypto_session_->GetSecurityLevel())) + if (!file_handle_->Reset(security_level_)) return UNKNOWN_ERROR; DeviceFiles::LicenseState license_state; + int64_t playback_start_time; + int64_t last_playback_time; - if (!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_)) { + 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)) { LOGE("CdmSession::Init failed to retrieve license. key set id = %s", key_set_id.c_str()); return UNKNOWN_ERROR; @@ -94,8 +148,10 @@ CdmResponseType CdmSession::RestoreOfflineSession( return UNKNOWN_ERROR; } - if (!license_parser_.RestoreOfflineLicense(key_request_, key_response_, - offline_key_renewal_response_)) { + if (!license_parser_->RestoreOfflineLicense(key_request_, key_response_, + offline_key_renewal_response_, + playback_start_time, + last_playback_time)) { return UNKNOWN_ERROR; } @@ -111,7 +167,8 @@ CdmResponseType CdmSession::RestoreUsageSession( key_request_ = key_request; key_response_ = key_response; - if (!license_parser_.RestoreUsageLicense(key_request_, key_response_)) { + + if (!license_parser_->RestoreUsageLicense(key_request_, key_response_)) { return UNKNOWN_ERROR; } @@ -155,14 +212,14 @@ CdmResponseType CdmSession::GenerateKeyRequest( init_data.type().c_str()); return KEY_ERROR; } - if (init_data.IsEmpty() && !license_parser_.HasInitData()) { + if (init_data.IsEmpty() && !license_parser_->HasInitData()) { LOGW("CdmSession::GenerateKeyRequest: init data absent"); return KEY_ERROR; } - if (!license_parser_.PrepareKeyRequest(init_data, license_type, - app_parameters, session_id_, - key_request, server_url)) { + if (!license_parser_->PrepareKeyRequest(init_data, license_type, + app_parameters, session_id_, + key_request, server_url)) { return KEY_ERROR; } @@ -195,14 +252,14 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response, } else if (license_received_) { // renewal return RenewKey(key_response); } else { - CdmResponseType sts = license_parser_.HandleKeyResponse(key_response); + CdmResponseType sts = license_parser_->HandleKeyResponse(key_response); if (sts != KEY_ADDED) return sts; license_received_ = true; key_response_ = key_response; - if (is_offline_ || !license_parser_.provider_session_token().empty()) { + if (is_offline_ || !license_parser_->provider_session_token().empty()) { sts = StoreLicense(); if (sts != NO_ERROR) return sts; } @@ -245,7 +302,7 @@ CdmResponseType CdmSession::QueryStatus(CdmQueryMap* key_info) { } CdmResponseType CdmSession::QueryKeyStatus(CdmQueryMap* key_info) { - return policy_engine_.Query(key_info); + return policy_engine_->Query(key_info); } CdmResponseType CdmSession::QueryKeyControlInfo(CdmQueryMap* key_info) { @@ -276,27 +333,35 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) { if (crypto_session_.get() == NULL || !crypto_session_->IsOpen()) return UNKNOWN_ERROR; + if (params.is_encrypted && !policy_engine_->can_decrypt()) { + return policy_engine_->IsLicenseForFuture() ? KEY_ERROR : NEED_KEY; + } + CdmResponseType status = crypto_session_->Decrypt(params); switch (status) { case NO_ERROR: if (is_initial_decryption_) { - policy_engine_.BeginDecryption(); + policy_engine_->BeginDecryption(); is_initial_decryption_ = false; } + has_decrypted_recently_ = true; if (!is_usage_update_needed_) { is_usage_update_needed_ = - !license_parser_.provider_session_token().empty(); + !license_parser_->provider_session_token().empty(); } break; - case UNKNOWN_ERROR: + case UNKNOWN_ERROR: { Clock clock; int64_t current_time = clock.GetCurrentTime(); - if (policy_engine_.IsLicenseDurationExpired(current_time) || - policy_engine_.IsPlaybackDurationExpired(current_time)) { + if (policy_engine_->IsLicenseDurationExpired(current_time) || + policy_engine_->IsPlaybackDurationExpired(current_time)) { return NEED_KEY; } break; + } + default: //Ignore + break; } return status; @@ -307,7 +372,8 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) { // session keys. CdmResponseType CdmSession::GenerateRenewalRequest(CdmKeyMessage* key_request, std::string* server_url) { - if (!license_parser_.PrepareKeyUpdateRequest(true, key_request, server_url)) { + if (!license_parser_->PrepareKeyUpdateRequest(true, key_request, + server_url)) { LOGE("CdmSession::GenerateRenewalRequest: ERROR on prepare"); return KEY_ERROR; } @@ -321,7 +387,7 @@ CdmResponseType CdmSession::GenerateRenewalRequest(CdmKeyMessage* key_request, // RenewKey() - Accept renewal response and update key info. CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) { CdmResponseType sts = - license_parser_.HandleKeyUpdateResponse(true, key_response); + license_parser_->HandleKeyUpdateResponse(true, key_response); if (sts != KEY_ADDED) return sts; if (is_offline_) { @@ -334,7 +400,7 @@ CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) { CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyMessage* key_request, std::string* server_url) { is_release_ = true; - if (!license_parser_.PrepareKeyUpdateRequest(false, key_request, server_url)) + if (!license_parser_->PrepareKeyUpdateRequest(false, key_request, server_url)) return UNKNOWN_ERROR; if (is_offline_) { // Mark license as being released @@ -346,19 +412,19 @@ CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyMessage* key_request, // ReleaseKey() - Accept release response and release license. CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) { - CdmResponseType sts = license_parser_.HandleKeyUpdateResponse(false, + CdmResponseType sts = license_parser_->HandleKeyUpdateResponse(false, key_response); if (KEY_ADDED != sts) return sts; - if (is_offline_ || !license_parser_.provider_session_token().empty()) { + if (is_offline_ || !license_parser_->provider_session_token().empty()) { DeleteLicense(); } return NO_ERROR; } bool CdmSession::IsKeyLoaded(const KeyId& key_id) { - return license_parser_.IsKeyLoaded(key_id); + return license_parser_->IsKeyLoaded(key_id); } CdmSessionId CdmSession::GenerateSessionId() { @@ -375,8 +441,7 @@ bool CdmSession::GenerateKeySetId(CdmKeySetId* key_set_id) { std::vector random_data( (kKeySetIdLength - sizeof(KEY_SET_ID_PREFIX)) / 2, 0); - DeviceFiles handle; - if (!handle.Init(crypto_session_->GetSecurityLevel())) + if (!file_handle_->Reset(security_level_)) return false; while (key_set_id->empty()) { @@ -386,7 +451,7 @@ bool CdmSession::GenerateKeySetId(CdmKeySetId* key_set_id) { *key_set_id = KEY_SET_ID_PREFIX + b2a_hex(random_data); // key set collision - if (handle.LicenseExists(*key_set_id)) { + if (file_handle_->LicenseExists(*key_set_id)) { key_set_id->clear(); } } @@ -414,20 +479,20 @@ CdmResponseType CdmSession::StoreLicense() { return NO_ERROR; } - std::string provider_session_token = license_parser_.provider_session_token(); + std::string provider_session_token = + license_parser_->provider_session_token(); if (provider_session_token.empty()) { LOGE("CdmSession::StoreLicense: No provider session token and not offline"); return UNKNOWN_ERROR; } - DeviceFiles handle; - if (!handle.Init(crypto_session_->GetSecurityLevel())) { + if (!file_handle_->Reset(security_level_)) { LOGE("CdmSession::StoreLicense: Unable to initialize device files"); return UNKNOWN_ERROR; } - if (!handle.StoreUsageInfo(provider_session_token, key_request_, - key_response_)) { + if (!file_handle_->StoreUsageInfo(provider_session_token, key_request_, + key_response_)) { LOGE("CdmSession::StoreLicense: Unable to store usage info"); return UNKNOWN_ERROR; } @@ -435,31 +500,31 @@ CdmResponseType CdmSession::StoreLicense() { } bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) { - DeviceFiles handle; - if (!handle.Init(crypto_session_->GetSecurityLevel())) + if (!file_handle_->Reset(security_level_)) return false; - return handle.StoreLicense( + 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_); + offline_key_renewal_response_, offline_release_server_url_, + policy_engine_->GetPlaybackStartTime(), + policy_engine_->GetLastPlaybackTime()); } bool CdmSession::DeleteLicense() { - if (!is_offline_ && license_parser_.provider_session_token().empty()) + if (!is_offline_ && license_parser_->provider_session_token().empty()) return false; - DeviceFiles handle; - if (!handle.Init(crypto_session_->GetSecurityLevel())) { + if (!file_handle_->Reset(security_level_)) { LOGE("CdmSession::DeleteLicense: Unable to initialize device files"); return false; } if (is_offline_) - return handle.DeleteLicense(key_set_id_); + return file_handle_->DeleteLicense(key_set_id_); else - return handle.DeleteUsageInfo( - license_parser_.provider_session_token()); + return file_handle_->DeleteUsageInfo( + license_parser_->provider_session_token()); } bool CdmSession::AttachEventListener(WvCdmEventListener* listener) { @@ -471,11 +536,19 @@ bool CdmSession::DetachEventListener(WvCdmEventListener* listener) { return (listeners_.erase(listener) == 1); } -void CdmSession::OnTimerEvent() { +void CdmSession::OnTimerEvent(bool update_usage) { bool event_occurred = false; CdmEventType event; - policy_engine_.OnTimerEvent(&event_occurred, &event); + if (update_usage && has_decrypted_recently_) { + policy_engine_->DecryptionEvent(); + has_decrypted_recently_ = false; + } + policy_engine_->OnTimerEvent(&event_occurred, &event); + + if (is_offline_ && !is_release_) { + StoreLicense(DeviceFiles::kLicenseStateActive); + } if (event_occurred) { for (CdmEventListenerIter iter = listeners_.begin(); diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 57fe57b1..e5f9ab4a 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -169,13 +169,8 @@ bool CryptoSession::GetApiVersion(uint32_t* version) { if (!initialized_) { return false; } - CdmSecurityLevel level = GetSecurityLevel(); - SecurityLevel security_level = kLevelDefault; - if (kSecurityLevelL3 == level) security_level = kLevel3; - - LOGV("CryptoSession::GetApiVersion: Lock"); - AutoLock auto_lock(crypto_lock_); - *version = OEMCrypto_APIVersion(security_level); + *version = OEMCrypto_APIVersion( + kSecurityLevelL3 == GetSecurityLevel() ? kLevel3 : kLevelDefault); return true; } @@ -267,13 +262,19 @@ void CryptoSession::Close() { } } -void CryptoSession::GenerateRequestId(std::string& req_id_str) { +bool CryptoSession::GenerateRequestId(std::string* req_id_str) { LOGV("CryptoSession::GenerateRequestId: Lock"); AutoLock auto_lock(crypto_lock_); - req_id_str = HexEncode(reinterpret_cast(&request_id_base_), - sizeof(request_id_base_)) + - HexEncode(reinterpret_cast(&request_id_index_), - sizeof(request_id_index_)); + if (!req_id_str) { + LOGE("CryptoSession::GenerateRequestId: No output destination provided."); + return false; + } + + *req_id_str = HexEncode(reinterpret_cast(&request_id_base_), + sizeof(request_id_base_)) + + HexEncode(reinterpret_cast(&request_id_index_), + sizeof(request_id_index_)); + return true; } bool CryptoSession::PrepareRequest(const std::string& message, @@ -662,19 +663,31 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) { } } -CdmResponseType CryptoSession::UpdateUsageInformation() { - return (OEMCrypto_UpdateUsageTable() == OEMCrypto_SUCCESS) ? NO_ERROR - : UNKNOWN_ERROR; +bool CryptoSession::UsageInformationSupport(bool* has_support) { + LOGV("UsageInformationSupport: id=%ld", (uint32_t)oec_session_id_); + if (!initialized_) return false; + + *has_support = OEMCrypto_SupportsUsageTable( + kSecurityLevelL3 == GetSecurityLevel() ? kLevel3 : kLevelDefault); + return true; } -CdmResponseType CryptoSession::GenerateUsageReport( - const std::string& provider_session_token, std::string* usage_report) { - LOGV("GenerateUsageReport: id=%ld", (uint32_t)oec_session_id_); +CdmResponseType CryptoSession::UpdateUsageInformation() { + LOGV("UpdateUsageInformation: id=%ld", (uint32_t)oec_session_id_); + AutoLock auto_lock(crypto_lock_); + if (!initialized_) return UNKNOWN_ERROR; - if (NULL == usage_report) { - LOGE("usage_report parameter is null"); + OEMCryptoResult status = OEMCrypto_UpdateUsageTable(); + if (status != OEMCrypto_SUCCESS) { + LOGE("CryptoSession::UsageUsageInformation: error=%ld", status); return UNKNOWN_ERROR; } + return NO_ERROR; +} + +CdmResponseType CryptoSession::DeactivateUsageInformation( + const std::string& provider_session_token) { + LOGV("DeactivateUsageInformation: id=%ld", (uint32_t)oec_session_id_); AutoLock auto_lock(crypto_lock_); uint8_t* pst = reinterpret_cast( @@ -684,19 +697,41 @@ CdmResponseType CryptoSession::GenerateUsageReport( OEMCrypto_DeactivateUsageEntry(pst, provider_session_token.length()); if (OEMCrypto_SUCCESS != status) { - LOGE("CryptoSession::GenerateUsageReport: Deactivate Usage Entry error=%ld", - status); + LOGE("CryptoSession::DeactivateUsageInformation: Deactivate Usage Entry " + " error=%ld", + status); + return UNKNOWN_ERROR; + } + return NO_ERROR; +} + +CdmResponseType CryptoSession::GenerateUsageReport( + const std::string& provider_session_token, std::string* usage_report, + UsageDurationStatus* usage_duration_status, int64_t* seconds_since_started, + int64_t* seconds_since_last_played) { + LOGV("GenerateUsageReport: id=%ld", (uint32_t)oec_session_id_); + + if (NULL == usage_report) { + LOGE("CryptoSession::GenerateUsageReport: usage_report parameter is null"); return UNKNOWN_ERROR; } - size_t usage_length = 0; - status = OEMCrypto_ReportUsage(oec_session_id_, pst, - provider_session_token.length(), NULL, - &usage_length); + AutoLock auto_lock(crypto_lock_); + uint8_t* pst = reinterpret_cast( + const_cast(provider_session_token.data())); - if (OEMCrypto_ERROR_SHORT_BUFFER != status) { - LOGE("CryptoSession::GenerateUsageReport: Report Usage error=%ld", status); - return UNKNOWN_ERROR; + size_t usage_length = 0; + OEMCryptoResult status = + OEMCrypto_ReportUsage(oec_session_id_, pst, + provider_session_token.length(), NULL, + &usage_length); + + if (OEMCrypto_SUCCESS != status) { + if (OEMCrypto_ERROR_SHORT_BUFFER != status) { + LOGE("CryptoSession::GenerateUsageReport: Report Usage error=%ld", + status); + return UNKNOWN_ERROR; + } } usage_report->resize(usage_length); @@ -711,10 +746,27 @@ CdmResponseType CryptoSession::GenerateUsageReport( return UNKNOWN_ERROR; } - if (usage_length < usage_report->length()) { + if (usage_length != usage_report->length()) { usage_report->resize(usage_length); } + OEMCrypto_PST_Report pst_report; + *usage_duration_status = kUsageDurationsInvalid; + if (usage_length < sizeof(pst_report)) { + LOGE("CryptoSession::GenerateUsageReport: usage report too small=%ld", + usage_length); + return NO_ERROR; // usage report available but no duration information + } + + memcpy(&pst_report, usage_report->data(), sizeof(pst_report)); + if (kUnused == pst_report.status) { + *usage_duration_status = kUsageDurationPlaybackNotBegun; + return NO_ERROR; + } + + *usage_duration_status = kUsageDurationsValid; + *seconds_since_started = pst_report.seconds_since_first_decrypt; + *seconds_since_last_played = pst_report.seconds_since_last_decrypt; return NO_ERROR; } @@ -822,6 +874,24 @@ bool CryptoSession::RewrapDeviceRSAKey(const std::string& message, return true; } +bool CryptoSession::GetHdcpCapabilities( + OemCryptoHdcpVersion* current_version, + OemCryptoHdcpVersion* max_version) { + LOGV("GetHdcpCapabilities: id=%ld", (uint32_t)oec_session_id_); + if (!initialized_) return UNKNOWN_ERROR; + OEMCrypto_HDCP_Capability current, max; + OEMCryptoResult status = OEMCrypto_GetHDCPCapability(¤t, &max); + + if (OEMCrypto_SUCCESS != status) { + LOGW("OEMCrypto_GetHDCPCapability fails with %d", status); + return false; + } + *current_version = static_cast(current); + *max_version = static_cast(max); + + return true; +} + bool CryptoSession::GetRandom(size_t data_length, uint8_t* random_data) { if (random_data == NULL) { LOGE("CryptoSession::GetRandom: random data destination not provided"); diff --git a/libwvdrmengine/cdm/core/src/device_files.cpp b/libwvdrmengine/cdm/core/src/device_files.cpp index 2b8487e2..19fd57b6 100644 --- a/libwvdrmengine/cdm/core/src/device_files.cpp +++ b/libwvdrmengine/cdm/core/src/device_files.cpp @@ -55,8 +55,13 @@ bool Hash(const std::string& data, std::string* hash) { namespace wvcdm { +DeviceFiles::DeviceFiles() + : file_(NULL), security_level_(kSecurityLevelUninitialized), + initialized_(false), test_file_(false) { +} + DeviceFiles::~DeviceFiles() { - if (!file_ && !test_file_) delete file_; + if (test_file_) file_.release(); } bool DeviceFiles::Init(CdmSecurityLevel security_level) { @@ -69,7 +74,7 @@ bool DeviceFiles::Init(CdmSecurityLevel security_level) { LOGW("DeviceFiles::Init: Unsupported security level %d", security_level); return false; } - file_ = new File(); + if (!test_file_) file_.reset(new File()); security_level_ = security_level; initialized_ = true; return true; @@ -148,7 +153,9 @@ bool DeviceFiles::StoreLicense(const std::string& key_set_id, const CdmKeyResponse& license_message, const CdmKeyMessage& license_renewal_request, const CdmKeyResponse& license_renewal, - const std::string& release_server_url) { + const std::string& release_server_url, + int64_t playback_start_time, + int64_t last_playback_time) { if (!initialized_) { LOGW("DeviceFiles::StoreLicense: not initialized"); return false; @@ -179,6 +186,8 @@ bool DeviceFiles::StoreLicense(const std::string& key_set_id, license->set_renewal_request(license_renewal_request); license->set_renewal(license_renewal); license->set_release_server_url(release_server_url); + license->set_playback_start_time(playback_start_time); + license->set_last_playback_time(last_playback_time); std::string serialized_file; file.SerializeToString(&serialized_file); @@ -193,7 +202,9 @@ bool DeviceFiles::RetrieveLicense(const std::string& key_set_id, CdmKeyResponse* license_message, CdmKeyMessage* license_renewal_request, CdmKeyResponse* license_renewal, - std::string* release_server_url) { + std::string* release_server_url, + int64_t* playback_start_time, + int64_t* last_playback_time) { if (!initialized_) { LOGW("DeviceFiles::RetrieveLicense: not initialized"); return false; @@ -245,6 +256,8 @@ bool DeviceFiles::RetrieveLicense(const std::string& key_set_id, *license_renewal_request = license.renewal_request(); *license_renewal = license.renewal(); *release_server_url = license.release_server_url(); + *playback_start_time = license.playback_start_time(); + *last_playback_time = license.last_playback_time(); return true; } @@ -454,7 +467,7 @@ bool DeviceFiles::RetrieveUsageInfo(std::vector< bool DeviceFiles::StoreFile(const char* name, const std::string& serialized_file) { - if (!file_) { + if (!file_.get()) { LOGW("DeviceFiles::StoreFile: Invalid file handle"); return false; } @@ -514,7 +527,7 @@ bool DeviceFiles::StoreFile(const char* name, } bool DeviceFiles::RetrieveFile(const char* name, std::string* serialized_file) { - if (!file_) { + if (!file_.get()) { LOGW("DeviceFiles::RetrieveFile: Invalid file handle"); return false; } @@ -663,8 +676,7 @@ std::string DeviceFiles::GetUsageInfoFileName() { } void DeviceFiles::SetTestFile(File* file) { - if (file_) delete file_; - file_ = file; + file_.reset(file); test_file_ = true; } diff --git a/libwvdrmengine/cdm/core/src/device_files.proto b/libwvdrmengine/cdm/core/src/device_files.proto index fb57ca9e..fe700bdd 100644 --- a/libwvdrmengine/cdm/core/src/device_files.proto +++ b/libwvdrmengine/cdm/core/src/device_files.proto @@ -31,6 +31,8 @@ message License { optional bytes renewal_request = 5; optional bytes renewal = 6; optional bytes release_server_url = 7; + optional int64 playback_start_time = 8 [default = 0]; + optional int64 last_playback_time = 9 [default = 0]; } message UsageInfo { diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index adde2746..f73df395 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -2,8 +2,11 @@ #include "license.h" +#include + #include +#include "clock.h" #include "crypto_key.h" #include "crypto_session.h" #include "device_files.h" @@ -22,7 +25,6 @@ std::string kDeviceNameKey = "device_name"; std::string kProductNameKey = "product_name"; std::string kBuildInfoKey = "build_info"; std::string kDeviceIdKey = "device_id"; -std::string kOemCryptoApiVersion = "oemcrypto_api_version"; const unsigned char kServiceCertificateCAPublicKey[] = { 0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01, 0x81, 0x00, 0xb4, 0xfe, 0x39, 0xc3, 0x65, 0x90, 0x03, @@ -80,6 +82,7 @@ namespace wvcdm { // Protobuf generated classes. using video_widevine_server::sdk::ClientIdentification; +using video_widevine_server::sdk::ClientIdentification_ClientCapabilities; using video_widevine_server::sdk::ClientIdentification_NameValue; using video_widevine_server::sdk::DeviceCertificate; using video_widevine_server::sdk::EncryptedClientIdentification; @@ -140,6 +143,24 @@ static std::vector ExtractContentKeys(const License& license) { return key_array; } +CdmLicense::CdmLicense() + : session_(NULL), + initialized_(false), + clock_(new Clock()) { +} + +CdmLicense::CdmLicense(Clock* clock) + : session_(NULL), + initialized_(false) { + if (NULL == clock) { + LOGE("CdmLicense::CdmLicense: clock parameter not provided"); + return; + } + clock_.reset(clock); +} + +CdmLicense::~CdmLicense() {} + bool CdmLicense::Init(const std::string& token, CryptoSession* session, PolicyEngine* policy_engine) { if (token.size() == 0) { @@ -206,7 +227,7 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data, } std::string request_id; - session_->GenerateRequestId(request_id); + session_->GenerateRequestId(&request_id); LicenseRequest license_request; ClientIdentification* client_id = license_request.mutable_client_id(); @@ -260,11 +281,54 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data, client_info->set_name(kDeviceIdKey); client_info->set_value(value); } + + ClientIdentification_ClientCapabilities* client_capabilities = + client_id->mutable_client_capabilities(); + bool supports_usage_information; + if (session_->UsageInformationSupport(&supports_usage_information)) { + client_capabilities->set_session_token(supports_usage_information); + } + + CryptoSession::OemCryptoHdcpVersion current_version, max_version; + if (session_->GetHdcpCapabilities(¤t_version, &max_version)) { + switch (max_version) { + case CryptoSession::kOemCryptoHdcpNotSupported: + client_capabilities->set_max_hdcp_version( + video_widevine_server::sdk:: + ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NONE); + break; + case CryptoSession::kOemCryptoHdcpVersion1: + client_capabilities->set_max_hdcp_version( + video_widevine_server::sdk:: + ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V1); + break; + case CryptoSession::kOemCryptoHdcpVersion2: + client_capabilities->set_max_hdcp_version( + video_widevine_server::sdk:: + ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2); + break; + case CryptoSession::kOemCryptoHdcpVersion2_1: + client_capabilities->set_max_hdcp_version( + video_widevine_server::sdk:: + ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_1); + break; + case CryptoSession::kOemCryptoHdcpVersion2_2: + client_capabilities->set_max_hdcp_version( + video_widevine_server::sdk:: + ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_2); + break; + case CryptoSession::kOemCryptoNoHdcpDeviceAttached: + default: + LOGW( + "CdmLicense::PrepareKeyRequest: unexpected HDCP max capability " + "version %d", + max_version); + } + } + uint32_t version = 0; if (session_->GetApiVersion(&version)) { - client_info = client_id->add_client_info(); - client_info->set_name(kOemCryptoApiVersion); - client_info->set_value(UintToString(version)); + client_capabilities->set_oem_crypto_api_version(version); } if (privacy_mode_enabled) { @@ -359,12 +423,10 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data, return false; } - // The time field will be updated once the cdm wrapper - // has been updated to pass us in the time. - license_request.set_request_time(0); - license_request.set_type(LicenseRequest::NEW); + license_request.set_request_time(clock_->GetCurrentTime()); + // Get/set the nonce. This value will be reflected in the Key Control Block // of the license response. uint32_t nonce; @@ -430,21 +492,47 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal, else license_request.set_type(LicenseRequest::RELEASE); + license_request.set_request_time(clock_->GetCurrentTime()); + LicenseRequest_ContentIdentification_ExistingLicense* current_license = license_request.mutable_content_id()->mutable_license(); LicenseIdentification license_id = policy_engine_->license_id(); current_license->mutable_license_id()->CopyFrom(license_id); - if (!is_renewal) { - if (license_id.has_provider_session_token()) { - std::string usage_report; - if (NO_ERROR != - session_->GenerateUsageReport(license_id.provider_session_token(), - &usage_report)) { + int64_t seconds_since_started, seconds_since_last_played; + CryptoSession::UsageDurationStatus usage_duration_status = + CryptoSession::kUsageDurationsInvalid; + if (!provider_session_token_.empty()) { + if (!is_renewal) { + CdmResponseType status = + session_->DeactivateUsageInformation(provider_session_token_); + if (NO_ERROR != status) return false; - } - current_license->set_session_usage_table_entry(usage_report); } + + std::string usage_report; + CdmResponseType status = + session_->GenerateUsageReport(provider_session_token_, + &usage_report, &usage_duration_status, + &seconds_since_started, + &seconds_since_last_played); + if (!is_renewal) { + if (NO_ERROR == status) + current_license->set_session_usage_table_entry(usage_report); + else + return false; + } + } + + if (CryptoSession::kUsageDurationsValid != usage_duration_status) { + if (policy_engine_->GetSecondsSinceStarted(&seconds_since_started) && + policy_engine_->GetSecondsSinceLastPlayed(&seconds_since_last_played)) + usage_duration_status = CryptoSession::kUsageDurationsValid; + } + + if (CryptoSession::kUsageDurationsValid == usage_duration_status) { + current_license->set_seconds_since_started(seconds_since_started); + current_license->set_seconds_since_last_played(seconds_since_last_played); } // Get/set the nonce. This value will be reflected in the Key Control Block @@ -664,7 +752,9 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse( bool CdmLicense::RestoreOfflineLicense( const CdmKeyMessage& license_request, const CdmKeyResponse& license_response, - const CdmKeyResponse& license_renewal_response) { + const CdmKeyResponse& license_renewal_response, + int64_t playback_start_time, + int64_t last_playback_time) { if (license_request.empty() || license_response.empty()) { LOGE( @@ -704,6 +794,36 @@ bool CdmLicense::RestoreOfflineLicense( if (sts != KEY_ADDED) return false; } + if (!provider_session_token_.empty()) { + std::string usage_report; + CryptoSession::UsageDurationStatus usage_duration_status = + CryptoSession::kUsageDurationsInvalid; + int64_t seconds_since_started, seconds_since_last_played; + sts = session_->GenerateUsageReport( + provider_session_token_, &usage_report, &usage_duration_status, + &seconds_since_started, &seconds_since_last_played); + + if (NO_ERROR == sts) { + switch (usage_duration_status) { + case CryptoSession::kUsageDurationPlaybackNotBegun: + playback_start_time = 0; + last_playback_time = 0; + break; + case CryptoSession::kUsageDurationsValid: { + int64_t current_time = clock_->GetCurrentTime(); + if (current_time - seconds_since_started > 0) + playback_start_time = current_time - seconds_since_started; + if (current_time - last_playback_time > 0) + last_playback_time = current_time - seconds_since_last_played; + break; + } + default: + break; + } + } + } + + policy_engine_->RestorePlaybackTimes(playback_start_time, last_playback_time); return true; } diff --git a/libwvdrmengine/cdm/core/src/license_protocol.proto b/libwvdrmengine/cdm/core/src/license_protocol.proto index 6dec3bfd..163549a7 100644 --- a/libwvdrmengine/cdm/core/src/license_protocol.proto +++ b/libwvdrmengine/cdm/core/src/license_protocol.proto @@ -287,12 +287,6 @@ message SignedMessage { // This message is used to pass optional data on initial license issuance. message SessionInit { - enum ReplayControl { - NO_SESSION_USAGE = 0; - NONCE_REQUIRED_AND_NEW_SESSION_USAGE = 1; - NONCE_REQUIRED_OR_EXISTING_SESSION_USAGE = 2; - } - optional bytes session_id = 1; optional bytes purchase_id = 2; // master_signing_key should be 128 bits in length. @@ -312,8 +306,6 @@ message SessionInit { // LicenseIdentfication::provider_session_token, and sent back in all // license renewal and release requests for the session thereafter. optional bytes provider_session_token = 7; - // Replay control indicator which will be encoded into V9+ KeyControl blocks. - optional ReplayControl replay_control = 8 [default = NO_SESSION_USAGE]; } // This message is used by the server to preserve and restore session state. @@ -415,6 +407,7 @@ message ClientIdentification { optional bool session_token = 2 [default = false]; optional bool video_resolution_constraints = 3 [default = false]; optional HdcpVersion max_hdcp_version = 4 [default = HDCP_NONE]; + optional uint32 oem_crypto_api_version = 5; } // Type of factory-provisioned device root of trust. Optional. diff --git a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_static_v8.cpp b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_static_v8.cpp index e631d05b..5b567042 100644 --- a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_static_v8.cpp +++ b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_static_v8.cpp @@ -95,7 +95,7 @@ OEMCryptoResult OEMCrypto_GetHDCPCapability(OEMCrypto_HDCP_Capability *current, } extern "C" bool OEMCrypto_SupportsUsageTable() { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; + return false; } extern "C" OEMCryptoResult OEMCrypto_UpdateUsageTable() { diff --git a/libwvdrmengine/cdm/core/src/policy_engine.cpp b/libwvdrmengine/cdm/core/src/policy_engine.cpp index 2b4f0244..dc3eca00 100644 --- a/libwvdrmengine/cdm/core/src/policy_engine.cpp +++ b/libwvdrmengine/cdm/core/src/policy_engine.cpp @@ -33,8 +33,8 @@ void PolicyEngine::Init(Clock* clock) { license_state_ = kLicenseStateInitial; can_decrypt_ = false; license_start_time_ = 0; - license_received_time_ = 0; playback_start_time_ = 0; + last_playback_time_ = 0; next_renewal_time_ = 0; policy_max_duration_seconds_ = 0; clock_ = clock; @@ -76,6 +76,14 @@ void PolicyEngine::OnTimerEvent(bool* event_occurred, CdmEventType* event) { break; } + case kLicenseStatePending: { + if (current_time >= license_start_time_) { + license_state_ = kLicenseStateCanPlay; + can_decrypt_ = true; + } + break; + } + case kLicenseStateInitial: case kLicenseStateExpired: { break; @@ -115,13 +123,11 @@ void PolicyEngine::UpdateLicense( policy_.MergeFrom(license.policy()); // some basic license validation - if (license_state_ == kLicenseStateInitial) { - // license start time needs to be present in the initial response - if (!license.has_license_start_time()) - return; - } - else { - // if renewal, discard license if version has not been updated + // license start time needs to be specified in the initial response + if (!license.has_license_start_time()) return; + + // if renewal, discard license if version has not been updated + if (license_state_ != kLicenseStateInitial) { if (license.id().version() > license_id_.version()) license_id_.CopyFrom(license.id()); else @@ -129,12 +135,8 @@ void PolicyEngine::UpdateLicense( } // Update time information - int64_t current_time = clock_->GetCurrentTime(); - if (license.has_license_start_time()) - license_start_time_ = license.license_start_time(); - license_received_time_ = current_time; - next_renewal_time_ = current_time + - policy_.renewal_delay_seconds(); + license_start_time_ = license.license_start_time(); + next_renewal_time_ = license_start_time_ + policy_.renewal_delay_seconds(); // Calculate policy_max_duration_seconds_. policy_max_duration_seconds_ // will be set to the minimum of the following policies : @@ -157,12 +159,18 @@ void PolicyEngine::UpdateLicense( return; } + int64_t current_time = clock_->GetCurrentTime(); if (IsLicenseDurationExpired(current_time)) return; if (IsPlaybackDurationExpired(current_time)) return; // Update state - license_state_ = kLicenseStateCanPlay; - can_decrypt_ = true; + if (current_time >= license_start_time_) { + license_state_ = kLicenseStateCanPlay; + can_decrypt_ = true; + } else { + license_state_ = kLicenseStatePending; + can_decrypt_ = false; + } } void PolicyEngine::BeginDecryption() { @@ -172,12 +180,14 @@ void PolicyEngine::BeginDecryption() { case kLicenseStateNeedRenewal: case kLicenseStateWaitingLicenseUpdate: playback_start_time_ = clock_->GetCurrentTime(); + last_playback_time_ = playback_start_time_; if (policy_.renew_with_usage()) { license_state_ = kLicenseStateNeedRenewal; } break; case kLicenseStateInitial: + case kLicenseStatePending: case kLicenseStateExpired: default: break; @@ -185,6 +195,10 @@ void PolicyEngine::BeginDecryption() { } } +void PolicyEngine::DecryptionEvent() { + last_playback_time_ = clock_->GetCurrentTime(); +} + CdmResponseType PolicyEngine::Query(CdmQueryMap* key_info) { std::stringstream ss; int64_t current_time = clock_->GetCurrentTime(); @@ -211,6 +225,27 @@ CdmResponseType PolicyEngine::Query(CdmQueryMap* key_info) { return NO_ERROR; } +bool PolicyEngine::GetSecondsSinceStarted(int64_t* seconds_since_started) { + if (playback_start_time_ == 0) return false; + + *seconds_since_started = clock_->GetCurrentTime() - playback_start_time_; + return (*seconds_since_started >= 0) ? true : false; +} + +bool PolicyEngine::GetSecondsSinceLastPlayed( + int64_t* seconds_since_last_played) { + if (last_playback_time_ == 0) return false; + + *seconds_since_last_played = clock_->GetCurrentTime() - last_playback_time_; + return (*seconds_since_last_played >= 0) ? true : false; +} + +void PolicyEngine::RestorePlaybackTimes(int64_t playback_start_time, + int64_t last_playback_time) { + playback_start_time_ = (playback_start_time > 0) ? playback_start_time : 0; + last_playback_time_ = (last_playback_time > 0) ? last_playback_time : 0; +} + void PolicyEngine::UpdateRenewalRequest(int64_t current_time) { license_state_ = kLicenseStateWaitingLicenseUpdate; next_renewal_time_ = current_time + policy_.renewal_retry_interval_seconds(); @@ -221,7 +256,7 @@ void PolicyEngine::UpdateRenewalRequest(int64_t current_time) { // will always return false if the value is 0. bool PolicyEngine::IsLicenseDurationExpired(int64_t current_time) { return policy_max_duration_seconds_ && - license_received_time_ + policy_max_duration_seconds_ <= + license_start_time_ + policy_max_duration_seconds_ <= current_time; } @@ -229,9 +264,12 @@ int64_t PolicyEngine::GetLicenseDurationRemaining(int64_t current_time) { if (0 == policy_max_duration_seconds_) return LLONG_MAX; int64_t remaining_time = policy_max_duration_seconds_ - + license_received_time_ - current_time; + + license_start_time_ - current_time; - if (remaining_time < 0) remaining_time = 0; + if (remaining_time < 0) + remaining_time = 0; + else if (remaining_time > policy_max_duration_seconds_) + remaining_time = policy_max_duration_seconds_; return remaining_time; } @@ -256,7 +294,7 @@ int64_t PolicyEngine::GetPlaybackDurationRemaining(int64_t current_time) { bool PolicyEngine::IsRenewalDelayExpired(int64_t current_time) { return policy_.can_renew() && (policy_.renewal_delay_seconds() > 0) && - license_received_time_ + policy_.renewal_delay_seconds() <= + license_start_time_ + policy_.renewal_delay_seconds() <= current_time; } @@ -264,7 +302,7 @@ bool PolicyEngine::IsRenewalRecoveryDurationExpired( int64_t current_time) { // NOTE: Renewal Recovery Duration is currently not used. return (policy_.renewal_recovery_duration_seconds() > 0) && - license_received_time_ + policy_.renewal_recovery_duration_seconds() <= + license_start_time_ + policy_.renewal_recovery_duration_seconds() <= current_time; } diff --git a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp index 0d89a2db..61cb328b 100644 --- a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp @@ -125,6 +125,8 @@ struct LicenseInfo { std::string key_renewal_request; std::string key_renewal_response; std::string key_release_url; + int64_t playback_start_time; + int64_t last_playback_time; std::string file_data; }; @@ -231,101 +233,89 @@ LicenseInfo license_test_data[] = { "0112001A16200342120A106B63746C0000000000ECDCBE0000000020DBDF" "A68F051A20182F029E35047A3841FA176C74E5B387350E8D58DEA6878FF0" "BEA6CABACA1C2C"), - "https://test.google.com/license/GetCencLicense", + "https://test.google.com/license/GetCencLicense", 0x0, 0x0, wvcdm::a2bs_hex( - "0AAF150802100122A8150801121408011210303132333435363738394142" - "434445461A9D0E080112950C0AD70B080112EF090AB002080212103E560E" - "C5335E346F591BC4D07A7D507618A5D3A68F05228E023082010A02820101" - "00A947904B8DBD55FB685FDB3025574517CCCC74EE4FEAF6629D5179A52F" - "F85CE7409528EFFA0E5DFC3DE9A34BA5F08BE349553C319A9FB274905A87" - "70ADC9CA4A2CBCD8E556A1587FA18BFD4D286C644A6904F19EAAFBDFADD3" - "B371B306D0B289F459B491C814B5AD1F747610E990A60248A7DA5152F1CC" - "FC047EF42300131F9C4758F4D9F30579393B860AAD9AD2EE43D721D6DB9F" - "5800EF188386B94825AE05A883AC976D6970DF43EA6C83B86CE6D0F54020" - "7725B9890FCCEC83A49027872DAFD2740B7748E9C3B1752D6F12859CED07" - "E8882969B433EC66F17FFC29AC6FDBEA79230B0FAED5D94CF6B829A420BB" - "E3270323941776EE60DD6BFD660BDDCA8702030100012880013001128002" - "50D1F8B1ECF849B60FF93E37C4DEEF09E6FFB10BCFC996A4A24B7AA96928" - "835ED5A72E15846D0A14015733239BD8B6E6D5E5D229B08394CE1E0692C1" - "59C44337CA7CAF88476449B068D9D2FADED8EB1BC0F4B8F0FCAF293E8690" - "E74032095341803408A0E8279E545945EE97838FDE7812F7171C3CC4F5EC" - "F9418BBF1D336CE58F4CBB1B44D4ADE6BF3364BAE7EC093281846E569E13" - "E7719014030A6059044FE7BBFF3E8F5723AEDD54DC6E0D041B309D7700B5" - "5575690E95CE6085D0914F991C5F45E98CBB9C45BA33F47FD0862EBCC7EE" - "BA8E60643C86E85476B18AEF8DE871571A75681A75F75028A5B58751C09A" - "5296AAE99CEDCD9785E9E2103240D40A1AB6050AB002080112102CE5CCF4" - "2200D6B5BCCF33D7CC2D9C7018EAD1B88D05228E023082010A0282010100" - "BE1B661EEC4700DF4B0C83292D02AE029B8A224DD3048125049F74E30E12" - "57FC2BE8D9CFAF0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4" - "396A805833730DC6E534C62408B7C5076FC22568021C59ED34F98487196D" - "A32078DAFCA37C7CFB8E79612FA384963DF2167D5E87305D7BC92D621C10" - "160672C27B9A691B1534F60D78C5893E40C5FF8A3F9DF8898612E9A5CCB5" - "6F4A0CC2A61A7AEB04A9DCC015D9BC37DEF2AB9EAA9AAFD838869081D924" - "9755F129BB0DBECA3B894975A65A36FD005CE77CD407E925D3172E33122A" - "11D327968A08F8E771FAEB2540EB52D17C4906405F47C31F60F0AF6C78AF" - "53291B236E692B506A2AF92AF43E3A81020301000128800130011280033A" - "08A60418E5C81B8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259" - "834000FE35DCD814426F9C5D332418ED94C9C0C992217B1B6DC01C99085A" - "3C3956C8267B8773BABCF3F2C841C67D830F9DBC780DD68BF4E2FE424C6A" - "54123BE4B2A1F7E1F4DB58AB1164DAE9CF75C3392284A44B8CDB85D837E8" - "6C6B908243987E552C8693878C9A1B7BEA3759783036F1595C406D6CBBA7" - "F8642A9B3B244DAA1F00531D0B908ADE4B533FD9FAFA21D0FB0C033D2AD5" - "DDF24C60F4FAC30820758877F2E1A78EB44E9336DCFAFDF572BB22A84A5D" - "EFDF2EB87B61DE26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1" - "C379C96961316B5D2A66F38C222091AF74141B6CAF93507485A5D8F82808" - "025451824F00C8B6A0CD5803F6564584138C8B18BC679B442D837307B5CC" - "90B1FD1FD32288B4A5D18D2D80E5E6A7A9EFD255B8B363038BCC67AF534E" - "AEE4A5903E304EED4990BB5BE735DB027A6DE35329D321EC051B956C55A5" - "B11674017517FCC3C7FF7397C13A7B7087A1F6AEC7F6761A130A0C636F6D" - "70616E795F6E616D6512034C47451A150A0A6D6F64656C5F6E616D651207" - "4E6578757320341A200A116172636869746563747572655F6E616D65120B" - "61726D656162692D7637611A130A0B6465766963655F6E616D6512046D61" - "6B6F1A150A0C70726F647563745F6E616D6512056F6363616D1A440A0A62" - "75696C645F696E666F1236676F6F676C652F6F6363616D2F6D616B6F3A34" - "2E332F4A425F4D52322F3731343239313A7573657264656275672F646576" - "2D6B6579731A210A096465766963655F696412144C474D43323031323130" - "3035303036333932373812250A230A140801121030313233343536373839" - "41424344454610021A09393837363534333231180120002A0C3339343037" - "3934373337000030151A8002734FBDED946EB74A1B61811C4C4A491214F6" - "BEA125A80F014165B28AA97AD0AF60E4D129EB7F424AD659F24E5EED4B70" - "2BEE328E38B72CA6F38CD0ECFD2E6D7B98147744C9B8A9610B3BDFE17675" - "FF7D584C5BF68064B0FE513FC322C9148795E4C2F2443C3024F5C1F29E6F" - "EFB6D77005DAB22CD2B63131908DE4D88795BB931CEA38452CC568BE2503" - "2245E372F07A1297F51748C7EA02F2C88360AFE7ABBC71DCDD5366126258" - "E5AFA27C2A20B339FA1E7AE925B494B361F6F7116F20BE8EE6E446146027" - "F4FD4300F4A0B0A3361EE34925F338D0AACF20AE919B4BAE81C1D57A8D2B" - "8FA38732A57697C316C180717C182A971C94E4AC4C7DF8F161CB8CC122F6" - "04080212CC020A190A0939383736353433323112084B9F26DAB8B06E1120" - "022800124108011801301E4239687474703A2F2F6B697230336663706731" - "37342E7769646576696E652E6E65742F7769646576696E652F6367692D62" - "696E2F64726D2E6367691A6612102531DFD6CCEA511D00F8C0172F1189AA" - "1A5057FF9D9DBD5A205B1DEB075E4A90467C1E074CDE6071BFF831AD590B" - "D5D117614F33CE2C3CE1824FC0D54B36ECEAE58DF5C8F9347C2FEED17A33" - "27E8F52B8ECA6313A1FA6A042EB9525DD328113C05F920011A7E0A103031" - "323334353637383941424344454612106D23622142B58F6D1EDD33AF3ECD" - "2C7E1A20884EE13BEA9DECDDBF68B532131C82B11CEC4D23C7FA9F3EF4C5" - "EE172E7C9736200242340A2050BFE71BB1BA683E35E0B49BB33048E5103F" - "BBB9C3E1CD6EBCDA7DD485DBAF431210D69D6F14C95CB6CFDB998E50D00F" - "4DA020DBDFA68F051A20AE5D6895E70F86F42F5FE3C58A505A865D05AB94" - "B1ABAA6CC59C3322F61C458D228002331F2BE95B5C796E0921CC27A72955" - "01DA10044E5CA36C0E2866FF068EA3515A6786BD5D60D74D80C6BA8BE6AA" - "D085AF967909A143171E9CDDE36EA528402867CD04FB6F97A150CDE55F9B" - "819F4104BEF48E4280D76645569E10AEF524D34D865B5B9E3EBC66C45EEB" - "BE16AB04493E7AEC4F99E7A99F3FC08FA431BECCC1978A079FA4801DB75E" - "1329A9921604E6F80CB148AA2DD5C8348057E9F4FC2AEA57EA4D215D0A8D" - "486294860DFB4F4C42D57D9542B76179E179DD4AA23F9F7B2AE432B39E4C" - "E8F156E84877DDA781AAAAFC797FF75AFE2019ADC3A2E419BF0253C705BD" - "4797A96866AC4C059AD8F2E9C6B617C60C6ADCDB894C25F0C7D29252F52F" - "D52A5708011231121D1A1B0A190A0939383736353433323112084B9F26DA" - "B8B06E112002280018022A0C31353532333030360000000030151A20C303" - "75683C4D2033E05DCC95DDFB278CFB5125A021C3C043A16ACC933A768A27" - "32610802123B0A190A0939383736353433323112084B9F26DAB8B06E1120" - "02280112001A16200342120A106B63746C0000000000ECDCBE0000000020" - "DBDFA68F051A20182F029E35047A3841FA176C74E5B387350E8D58DEA687" - "8FF0BEA6CABACA1C2C3A3968747470733A2F2F6A6D7431372E676F6F676C" - "652E636F6D2F766964656F2D6465762F6C6963656E73652F47657443656E" - "634C6963656E73651220F6974C1CFFD00E3144488FC092D3DF4F6007A3CA" - "C4756EB046DC74B1C2E512CC")}, + "0AA8150802100122A1150801121408011210303132333435363738394142434445461" + "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" + "7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302" + "5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B" + "E349553C319A9FB274905A8770ADC9CA4A2CBCD8E556A1587FA18BFD4D286C644A690" + "4F19EAAFBDFADD3B371B306D0B289F459B491C814B5AD1F747610E990A60248A7DA51" + "52F1CCFC047EF42300131F9C4758F4D9F30579393B860AAD9AD2EE43D721D6DB9F580" + "0EF188386B94825AE05A883AC976D6970DF43EA6C83B86CE6D0F540207725B9890FCC" + "EC83A49027872DAFD2740B7748E9C3B1752D6F12859CED07E8882969B433EC66F17FF" + "C29AC6FDBEA79230B0FAED5D94CF6B829A420BBE3270323941776EE60DD6BFD660BDD" + "CA870203010001288001300112800250D1F8B1ECF849B60FF93E37C4DEEF09E6FFB10" + "BCFC996A4A24B7AA96928835ED5A72E15846D0A14015733239BD8B6E6D5E5D229B083" + "94CE1E0692C159C44337CA7CAF88476449B068D9D2FADED8EB1BC0F4B8F0FCAF293E8" + "690E74032095341803408A0E8279E545945EE97838FDE7812F7171C3CC4F5ECF9418B" + "BF1D336CE58F4CBB1B44D4ADE6BF3364BAE7EC093281846E569E13E7719014030A605" + "9044FE7BBFF3E8F5723AEDD54DC6E0D041B309D7700B55575690E95CE6085D0914F99" + "1C5F45E98CBB9C45BA33F47FD0862EBCC7EEBA8E60643C86E85476B18AEF8DE871571" + "A75681A75F75028A5B58751C09A5296AAE99CEDCD9785E9E2103240D40A1AB6050AB0" + "02080112102CE5CCF42200D6B5BCCF33D7CC2D9C7018EAD1B88D05228E023082010A0" + "282010100BE1B661EEC4700DF4B0C83292D02AE029B8A224DD3048125049F74E30E12" + "57FC2BE8D9CFAF0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4396A80583" + "3730DC6E534C62408B7C5076FC22568021C59ED34F98487196DA32078DAFCA37C7CFB" + "8E79612FA384963DF2167D5E87305D7BC92D621C10160672C27B9A691B1534F60D78C" + "5893E40C5FF8A3F9DF8898612E9A5CCB56F4A0CC2A61A7AEB04A9DCC015D9BC37DEF2" + "AB9EAA9AAFD838869081D9249755F129BB0DBECA3B894975A65A36FD005CE77CD407E" + "925D3172E33122A11D327968A08F8E771FAEB2540EB52D17C4906405F47C31F60F0AF" + "6C78AF53291B236E692B506A2AF92AF43E3A81020301000128800130011280033A08A" + "60418E5C81B8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259834000FE35DC" + "D814426F9C5D332418ED94C9C0C992217B1B6DC01C99085A3C3956C8267B8773BABCF" + "3F2C841C67D830F9DBC780DD68BF4E2FE424C6A54123BE4B2A1F7E1F4DB58AB1164DA" + "E9CF75C3392284A44B8CDB85D837E86C6B908243987E552C8693878C9A1B7BEA37597" + "83036F1595C406D6CBBA7F8642A9B3B244DAA1F00531D0B908ADE4B533FD9FAFA21D0" + "FB0C033D2AD5DDF24C60F4FAC30820758877F2E1A78EB44E9336DCFAFDF572BB22A84" + "A5DEFDF2EB87B61DE26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1C379C9" + "6961316B5D2A66F38C222091AF74141B6CAF93507485A5D8F82808025451824F00C8B" + "6A0CD5803F6564584138C8B18BC679B442D837307B5CC90B1FD1FD32288B4A5D18D2D" + "80E5E6A7A9EFD255B8B363038BCC67AF534EAEE4A5903E304EED4990BB5BE735DB027" + "A6DE35329D321EC051B956C55A5B11674017517FCC3C7FF7397C13A7B7087A1F6AEC7" + "F6761A130A0C636F6D70616E795F6E616D6512034C47451A150A0A6D6F64656C5F6E6" + "16D6512074E6578757320341A200A116172636869746563747572655F6E616D65120B" + "61726D656162692D7637611A130A0B6465766963655F6E616D6512046D616B6F1A150" + "A0C70726F647563745F6E616D6512056F6363616D1A440A0A6275696C645F696E666F" + "1236676F6F676C652F6F6363616D2F6D616B6F3A342E332F4A425F4D52322F3731343" + "239313A7573657264656275672F6465762D6B6579731A210A096465766963655F6964" + "12144C474D433230313231303035303036333932373812250A230A140801121030313" + "23334353637383941424344454610021A09393837363534333231180120002A0C3339" + "3430373934373337000030151A8002734FBDED946EB74A1B61811C4C4A491214F6BEA" + "125A80F014165B28AA97AD0AF60E4D129EB7F424AD659F24E5EED4B702BEE328E38B7" + "2CA6F38CD0ECFD2E6D7B98147744C9B8A9610B3BDFE17675FF7D584C5BF68064B0FE5" + "13FC322C9148795E4C2F2443C3024F5C1F29E6FEFB6D77005DAB22CD2B63131908DE4" + "D88795BB931CEA38452CC568BE25032245E372F07A1297F51748C7EA02F2C88360AFE" + "7ABBC71DCDD5366126258E5AFA27C2A20B339FA1E7AE925B494B361F6F7116F20BE8E" + "E6E446146027F4FD4300F4A0B0A3361EE34925F338D0AACF20AE919B4BAE81C1D57A8" + "D2B8FA38732A57697C316C180717C182A971C94E4AC4C7DF8F161CB8CC122F6040802" + "12CC020A190A0939383736353433323112084B9F26DAB8B06E1120022800124108011" + "801301E4239687474703A2F2F6B69723033666370673137342E7769646576696E652E" + "6E65742F7769646576696E652F6367692D62696E2F64726D2E6367691A6612102531D" + "FD6CCEA511D00F8C0172F1189AA1A5057FF9D9DBD5A205B1DEB075E4A90467C1E074C" + "DE6071BFF831AD590BD5D117614F33CE2C3CE1824FC0D54B36ECEAE58DF5C8F9347C2" + "FEED17A3327E8F52B8ECA6313A1FA6A042EB9525DD328113C05F920011A7E0A103031" + "323334353637383941424344454612106D23622142B58F6D1EDD33AF3ECD2C7E1A208" + "84EE13BEA9DECDDBF68B532131C82B11CEC4D23C7FA9F3EF4C5EE172E7C9736200242" + "340A2050BFE71BB1BA683E35E0B49BB33048E5103FBBB9C3E1CD6EBCDA7DD485DBAF4" + "31210D69D6F14C95CB6CFDB998E50D00F4DA020DBDFA68F051A20AE5D6895E70F86F4" + "2F5FE3C58A505A865D05AB94B1ABAA6CC59C3322F61C458D228002331F2BE95B5C796" + "E0921CC27A7295501DA10044E5CA36C0E2866FF068EA3515A6786BD5D60D74D80C6BA" + "8BE6AAD085AF967909A143171E9CDDE36EA528402867CD04FB6F97A150CDE55F9B819" + "F4104BEF48E4280D76645569E10AEF524D34D865B5B9E3EBC66C45EEBBE16AB04493E" + "7AEC4F99E7A99F3FC08FA431BECCC1978A079FA4801DB75E1329A9921604E6F80CB14" + "8AA2DD5C8348057E9F4FC2AEA57EA4D215D0A8D486294860DFB4F4C42D57D9542B761" + "79E179DD4AA23F9F7B2AE432B39E4CE8F156E84877DDA781AAAAFC797FF75AFE2019A" + "DC3A2E419BF0253C705BD4797A96866AC4C059AD8F2E9C6B617C60C6ADCDB894C25F0" + "C7D29252F52FD52A5708011231121D1A1B0A190A0939383736353433323112084B9F2" + "6DAB8B06E112002280018022A0C31353532333030360000000030151A20C30375683C" + "4D2033E05DCC95DDFB278CFB5125A021C3C043A16ACC933A768A2732610802123B0A1" + "90A0939383736353433323112084B9F26DAB8B06E112002280112001A16200342120A" + "106B63746C0000000000ECDCBE0000000020DBDFA68F051A20182F029E35047A3841F" + "A176C74E5B387350E8D58DEA6878FF0BEA6CABACA1C2C3A2E68747470733A2F2F7465" + "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" + "365400048001220CD0599C2B85D9F2D573AC7893CE77CB5A10B326828BA8C89047505" + "A8C9B606AC")}, // license 1 {"ksidC8EAA2579A282EB0", DeviceFiles::kLicenseStateReleasing, @@ -423,102 +413,89 @@ LicenseInfo license_test_data[] = { "0112001A16200342120A106B63746C00000000CA3A6A75000000002083E5" "A68F051A20BDA6A56F7CBFD0942198F87C23A34AA5CBD64AFEB134277774" "CCF8E789D815DD"), - "https://test.google.com/license/GetCencLicense", + "https://test.google.com/license/GetCencLicense", 0x12345678, 0x12348765, wvcdm::a2bs_hex( - "0AC7150802100122C0150802121408011210303132333435363738394142" - "434445461A9D0E080112950C0AD70B080112EF090AB002080212103E560E" - "C5335E346F591BC4D07A7D507618A5D3A68F05228E023082010A02820101" - "00A947904B8DBD55FB685FDB3025574517CCCC74EE4FEAF6629D5179A52F" - "F85CE7409528EFFA0E5DFC3DE9A34BA5F08BE349553C319A9FB274905A87" - "70ADC9CA4A2CBCD8E556A1587FA18BFD4D286C644A6904F19EAAFBDFADD3" - "B371B306D0B289F459B491C814B5AD1F747610E990A60248A7DA5152F1CC" - "FC047EF42300131F9C4758F4D9F30579393B860AAD9AD2EE43D721D6DB9F" - "5800EF188386B94825AE05A883AC976D6970DF43EA6C83B86CE6D0F54020" - "7725B9890FCCEC83A49027872DAFD2740B7748E9C3B1752D6F12859CED07" - "E8882969B433EC66F17FFC29AC6FDBEA79230B0FAED5D94CF6B829A420BB" - "E3270323941776EE60DD6BFD660BDDCA8702030100012880013001128002" - "50D1F8B1ECF849B60FF93E37C4DEEF09E6FFB10BCFC996A4A24B7AA96928" - "835ED5A72E15846D0A14015733239BD8B6E6D5E5D229B08394CE1E0692C1" - "59C44337CA7CAF88476449B068D9D2FADED8EB1BC0F4B8F0FCAF293E8690" - "E74032095341803408A0E8279E545945EE97838FDE7812F7171C3CC4F5EC" - "F9418BBF1D336CE58F4CBB1B44D4ADE6BF3364BAE7EC093281846E569E13" - "E7719014030A6059044FE7BBFF3E8F5723AEDD54DC6E0D041B309D7700B5" - "5575690E95CE6085D0914F991C5F45E98CBB9C45BA33F47FD0862EBCC7EE" - "BA8E60643C86E85476B18AEF8DE871571A75681A75F75028A5B58751C09A" - "5296AAE99CEDCD9785E9E2103240D40A1AB6050AB002080112102CE5CCF4" - "2200D6B5BCCF33D7CC2D9C7018EAD1B88D05228E023082010A0282010100" - "BE1B661EEC4700DF4B0C83292D02AE029B8A224DD3048125049F74E30E12" - "57FC2BE8D9CFAF0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4" - "396A805833730DC6E534C62408B7C5076FC22568021C59ED34F98487196D" - "A32078DAFCA37C7CFB8E79612FA384963DF2167D5E87305D7BC92D621C10" - "160672C27B9A691B1534F60D78C5893E40C5FF8A3F9DF8898612E9A5CCB5" - "6F4A0CC2A61A7AEB04A9DCC015D9BC37DEF2AB9EAA9AAFD838869081D924" - "9755F129BB0DBECA3B894975A65A36FD005CE77CD407E925D3172E33122A" - "11D327968A08F8E771FAEB2540EB52D17C4906405F47C31F60F0AF6C78AF" - "53291B236E692B506A2AF92AF43E3A81020301000128800130011280033A" - "08A60418E5C81B8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259" - "834000FE35DCD814426F9C5D332418ED94C9C0C992217B1B6DC01C99085A" - "3C3956C8267B8773BABCF3F2C841C67D830F9DBC780DD68BF4E2FE424C6A" - "54123BE4B2A1F7E1F4DB58AB1164DAE9CF75C3392284A44B8CDB85D837E8" - "6C6B908243987E552C8693878C9A1B7BEA3759783036F1595C406D6CBBA7" - "F8642A9B3B244DAA1F00531D0B908ADE4B533FD9FAFA21D0FB0C033D2AD5" - "DDF24C60F4FAC30820758877F2E1A78EB44E9336DCFAFDF572BB22A84A5D" - "EFDF2EB87B61DE26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1" - "C379C96961316B5D2A66F38C222091AF74141B6CAF93507485A5D8F82808" - "025451824F00C8B6A0CD5803F6564584138C8B18BC679B442D837307B5CC" - "90B1FD1FD32288B4A5D18D2D80E5E6A7A9EFD255B8B363038BCC67AF534E" - "AEE4A5903E304EED4990BB5BE735DB027A6DE35329D321EC051B956C55A5" - "B11674017517FCC3C7FF7397C13A7B7087A1F6AEC7F6761A130A0C636F6D" - "70616E795F6E616D6512034C47451A150A0A6D6F64656C5F6E616D651207" - "4E6578757320341A200A116172636869746563747572655F6E616D65120B" - "61726D656162692D7637611A130A0B6465766963655F6E616D6512046D61" - "6B6F1A150A0C70726F647563745F6E616D6512056F6363616D1A440A0A62" - "75696C645F696E666F1236676F6F676C652F6F6363616D2F6D616B6F3A34" - "2E332F4A425F4D52322F3731343239313A7573657264656275672F646576" - "2D6B6579731A210A096465766963655F696412144C474D43323031323130" - "3035303036333932373812250A230A140801121030313233343536373839" - "41424344454610021A09393837363534333231180120002A0C3838373031" - "3633350000000030151A80023F7318E29C5A50C8ADAA4B09ADCD97B75588" - "B17002C5C2BC9AFA35C53098AF22DF5CC300407CD2E84EBE01911C785513" - "649E2CCF4E429020D3B93F3A54748C11ECFF4D62F562A4D3E96812F663D4" - "F761C00C3E88ABD8A1DC10E017A44DD3E040775FED5F07649090D1142C9D" - "21373CD604219E24935E10F287F20B0E080FDF76B6096B24F82A3E37850D" - "E229DE33EBCE7A0FA53F652C33007EA7027F95A44C36D04CBD676EB5C0BF" - "69508F45E0C3220D1706B0B851B3FCAF7AC2370EAD80C5D1620887633A42" - "024862FCEA9F95A719AAB989C1923C6452ECB0B75AF1CAFBFB06C5EC31BB" - "F0EE4D16ACCC9AF05B77D61C4855491B3D4AC150F3BCB7AE536AF33322F6" - "04080212CC020A190A093938373635343332311208F97F2B3856CBB3DD20" - "022800124108011801301E4239687474703A2F2F6B697230336663706731" - "37342E7769646576696E652E6E65742F7769646576696E652F6367692D62" - "696E2F64726D2E6367691A661210C5C43FE0178AEE7B85042F749D5A4025" - "1A5013A1501E0F90A64E103336944A37BAAAEAC17E46E880DF6EA23A7A89" - "0DA082CBBF82710B8C3982E8AB25A208A89EEFB5250D4B2CCC2F362856E0" - "5D1941E387801A19886B1F3AAE60D06EDA400087B06920011A7E0A103031" - "32333435363738394142434445461210A34D2B04D596DFE1DC29CFDF116E" - "39211A2031AD1B369D225842A14B5D5F8366F5FF8EB94AA7CD13EB45BA72" - "9168E19D5F5F200242340A20A0D6D65CC677C12B86A7A99F89F446BCFDA1" - "8544B15B2FEF8349ED5C247F7BE91210ED8D58320B0F4F948F960C7D4987" - "2CDE2083E5A68F051A207481A2B82C83DF3090D57EDC042711A42CF4F87E" - "79CE136DAFE25F48F4A9068322800256113CA771F4250CAD2928161D07B5" - "2561019003DBFBD362F20587D51BD999D57D2B035BC115C54C8B4BC37661" - "A66A101DE5B42D82E582309AFD8E211C947A2D33CAFB58F89EEE2DA95246" - "140311134429D8A5D15E03A169B0EB2579DA3BD6E4322D6C46EE964F6931" - "CF9DA52FB59B1D3B9BCC5959211CC23D97690FA8E869ADF68BCDA8A1211D" - "DBEBF967617AF0BFDA73E0AE79D8A7CCED208602EDC72CEF44A02901A52E" - "EB87CF9841D186BC95A65956BAD48F3C9E43F027CC03B73DFF5CAFC0B647" - "27E2D7B3A9CF25F97C475207C8A9DF091A585288A71AE64B7B2089871F72" - "72381CCBEF55EBF3DCB21B134FE48BFD5299DCCA6B01B55EEA61F9F990D0" - "AF2A5708011231121D1A1B0A190A093938373635343332311208F97F2B38" - "56CBB3DD2002280018022A0C33333932383235393733000030151A209ADE" - "9B0A411583962BDA31BE5BE937E589BB3DCC06F6F4C48FBE4FAE86DC9ABA" - "32610802123B0A190A093938373635343332311208F97F2B3856CBB3DD20" - "02280112001A16200342120A106B63746C00000000CA3A6A750000000020" - "83E5A68F051A20BDA6A56F7CBFD0942198F87C23A34AA5CBD64AFEB13427" - "7774CCF8E789D815DD3A5168747470733A2F2F7777772E796F7574756265" - "2E636F6D2F6170692F64726D2F7769646576696E653F766964656F5F6964" - "3D3033363831323632646334313263303626736F757263653D594F555455" - "42451220EC449C6B026C43004743061B3A3DCB7208B2AD11600254841B96" - "1CFA1AD57172")}, + "0AB0150802100122A9150802121408011210303132333435363738394142434445461" + "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" + "7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302" + "5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B" + "E349553C319A9FB274905A8770ADC9CA4A2CBCD8E556A1587FA18BFD4D286C644A690" + "4F19EAAFBDFADD3B371B306D0B289F459B491C814B5AD1F747610E990A60248A7DA51" + "52F1CCFC047EF42300131F9C4758F4D9F30579393B860AAD9AD2EE43D721D6DB9F580" + "0EF188386B94825AE05A883AC976D6970DF43EA6C83B86CE6D0F540207725B9890FCC" + "EC83A49027872DAFD2740B7748E9C3B1752D6F12859CED07E8882969B433EC66F17FF" + "C29AC6FDBEA79230B0FAED5D94CF6B829A420BBE3270323941776EE60DD6BFD660BDD" + "CA870203010001288001300112800250D1F8B1ECF849B60FF93E37C4DEEF09E6FFB10" + "BCFC996A4A24B7AA96928835ED5A72E15846D0A14015733239BD8B6E6D5E5D229B083" + "94CE1E0692C159C44337CA7CAF88476449B068D9D2FADED8EB1BC0F4B8F0FCAF293E8" + "690E74032095341803408A0E8279E545945EE97838FDE7812F7171C3CC4F5ECF9418B" + "BF1D336CE58F4CBB1B44D4ADE6BF3364BAE7EC093281846E569E13E7719014030A605" + "9044FE7BBFF3E8F5723AEDD54DC6E0D041B309D7700B55575690E95CE6085D0914F99" + "1C5F45E98CBB9C45BA33F47FD0862EBCC7EEBA8E60643C86E85476B18AEF8DE871571" + "A75681A75F75028A5B58751C09A5296AAE99CEDCD9785E9E2103240D40A1AB6050AB0" + "02080112102CE5CCF42200D6B5BCCF33D7CC2D9C7018EAD1B88D05228E023082010A0" + "282010100BE1B661EEC4700DF4B0C83292D02AE029B8A224DD3048125049F74E30E12" + "57FC2BE8D9CFAF0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4396A80583" + "3730DC6E534C62408B7C5076FC22568021C59ED34F98487196DA32078DAFCA37C7CFB" + "8E79612FA384963DF2167D5E87305D7BC92D621C10160672C27B9A691B1534F60D78C" + "5893E40C5FF8A3F9DF8898612E9A5CCB56F4A0CC2A61A7AEB04A9DCC015D9BC37DEF2" + "AB9EAA9AAFD838869081D9249755F129BB0DBECA3B894975A65A36FD005CE77CD407E" + "925D3172E33122A11D327968A08F8E771FAEB2540EB52D17C4906405F47C31F60F0AF" + "6C78AF53291B236E692B506A2AF92AF43E3A81020301000128800130011280033A08A" + "60418E5C81B8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259834000FE35DC" + "D814426F9C5D332418ED94C9C0C992217B1B6DC01C99085A3C3956C8267B8773BABCF" + "3F2C841C67D830F9DBC780DD68BF4E2FE424C6A54123BE4B2A1F7E1F4DB58AB1164DA" + "E9CF75C3392284A44B8CDB85D837E86C6B908243987E552C8693878C9A1B7BEA37597" + "83036F1595C406D6CBBA7F8642A9B3B244DAA1F00531D0B908ADE4B533FD9FAFA21D0" + "FB0C033D2AD5DDF24C60F4FAC30820758877F2E1A78EB44E9336DCFAFDF572BB22A84" + "A5DEFDF2EB87B61DE26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1C379C9" + "6961316B5D2A66F38C222091AF74141B6CAF93507485A5D8F82808025451824F00C8B" + "6A0CD5803F6564584138C8B18BC679B442D837307B5CC90B1FD1FD32288B4A5D18D2D" + "80E5E6A7A9EFD255B8B363038BCC67AF534EAEE4A5903E304EED4990BB5BE735DB027" + "A6DE35329D321EC051B956C55A5B11674017517FCC3C7FF7397C13A7B7087A1F6AEC7" + "F6761A130A0C636F6D70616E795F6E616D6512034C47451A150A0A6D6F64656C5F6E6" + "16D6512074E6578757320341A200A116172636869746563747572655F6E616D65120B" + "61726D656162692D7637611A130A0B6465766963655F6E616D6512046D616B6F1A150" + "A0C70726F647563745F6E616D6512056F6363616D1A440A0A6275696C645F696E666F" + "1236676F6F676C652F6F6363616D2F6D616B6F3A342E332F4A425F4D52322F3731343" + "239313A7573657264656275672F6465762D6B6579731A210A096465766963655F6964" + "12144C474D433230313231303035303036333932373812250A230A140801121030313" + "23334353637383941424344454610021A09393837363534333231180120002A0C3838" + "3730313633350000000030151A80023F7318E29C5A50C8ADAA4B09ADCD97B75588B17" + "002C5C2BC9AFA35C53098AF22DF5CC300407CD2E84EBE01911C785513649E2CCF4E42" + "9020D3B93F3A54748C11ECFF4D62F562A4D3E96812F663D4F761C00C3E88ABD8A1DC1" + "0E017A44DD3E040775FED5F07649090D1142C9D21373CD604219E24935E10F287F20B" + "0E080FDF76B6096B24F82A3E37850DE229DE33EBCE7A0FA53F652C33007EA7027F95A" + "44C36D04CBD676EB5C0BF69508F45E0C3220D1706B0B851B3FCAF7AC2370EAD80C5D1" + "620887633A42024862FCEA9F95A719AAB989C1923C6452ECB0B75AF1CAFBFB06C5EC3" + "1BBF0EE4D16ACCC9AF05B77D61C4855491B3D4AC150F3BCB7AE536AF33322F6040802" + "12CC020A190A093938373635343332311208F97F2B3856CBB3DD20022800124108011" + "801301E4239687474703A2F2F6B69723033666370673137342E7769646576696E652E" + "6E65742F7769646576696E652F6367692D62696E2F64726D2E6367691A661210C5C43" + "FE0178AEE7B85042F749D5A40251A5013A1501E0F90A64E103336944A37BAAAEAC17E" + "46E880DF6EA23A7A890DA082CBBF82710B8C3982E8AB25A208A89EEFB5250D4B2CCC2" + "F362856E05D1941E387801A19886B1F3AAE60D06EDA400087B06920011A7E0A103031" + "32333435363738394142434445461210A34D2B04D596DFE1DC29CFDF116E39211A203" + "1AD1B369D225842A14B5D5F8366F5FF8EB94AA7CD13EB45BA729168E19D5F5F200242" + "340A20A0D6D65CC677C12B86A7A99F89F446BCFDA18544B15B2FEF8349ED5C247F7BE" + "91210ED8D58320B0F4F948F960C7D49872CDE2083E5A68F051A207481A2B82C83DF30" + "90D57EDC042711A42CF4F87E79CE136DAFE25F48F4A9068322800256113CA771F4250" + "CAD2928161D07B52561019003DBFBD362F20587D51BD999D57D2B035BC115C54C8B4B" + "C37661A66A101DE5B42D82E582309AFD8E211C947A2D33CAFB58F89EEE2DA95246140" + "311134429D8A5D15E03A169B0EB2579DA3BD6E4322D6C46EE964F6931CF9DA52FB59B" + "1D3B9BCC5959211CC23D97690FA8E869ADF68BCDA8A1211DDBEBF967617AF0BFDA73E" + "0AE79D8A7CCED208602EDC72CEF44A02901A52EEB87CF9841D186BC95A65956BAD48F" + "3C9E43F027CC03B73DFF5CAFC0B64727E2D7B3A9CF25F97C475207C8A9DF091A58528" + "8A71AE64B7B2089871F7272381CCBEF55EBF3DCB21B134FE48BFD5299DCCA6B01B55E" + "EA61F9F990D0AF2A5708011231121D1A1B0A190A093938373635343332311208F97F2" + "B3856CBB3DD2002280018022A0C33333932383235393733000030151A209ADE9B0A41" + "1583962BDA31BE5BE937E589BB3DCC06F6F4C48FBE4FAE86DC9ABA32610802123B0A1" + "90A093938373635343332311208F97F2B3856CBB3DD2002280112001A16200342120A" + "106B63746C00000000CA3A6A75000000002083E5A68F051A20BDA6A56F7CBFD094219" + "8F87C23A34AA5CBD64AFEB134277774CCF8E789D815DD3A2E68747470733A2F2F7465" + "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" + "36540F8ACD1910148E58ED291011220C47DDCB3FA0DF569B95DD9F46F83608632C93E" + "E0EA5C9360D7D537730D028EC6")}, // license 2 {"ksidE8C37662C88DC673", DeviceFiles::kLicenseStateReleasing, @@ -616,100 +593,90 @@ LicenseInfo license_test_data[] = { "0112001A16200342120A106B63746C000000001FF4944E000000002082E7" "A68F051A2041EF0A9267D613D17AA90E1D1DA5BE091860E5E296D41D6D0F" "75E73660C279B3"), - "https://test.google.com/license/GetCencLicense", + "https://test.google.com/license/GetCencLicense", 0x0123456789abcdef, + 0x123456789abfedc, wvcdm::a2bs_hex( - "0A9F15080210012298150802121408011210303132333435363738394142" - "434445461A9D0E080112950C0AD70B080112EF090AB002080212103E560E" - "C5335E346F591BC4D07A7D507618A5D3A68F05228E023082010A02820101" - "00A947904B8DBD55FB685FDB3025574517CCCC74EE4FEAF6629D5179A52F" - "F85CE7409528EFFA0E5DFC3DE9A34BA5F08BE349553C319A9FB274905A87" - "70ADC9CA4A2CBCD8E556A1587FA18BFD4D286C644A6904F19EAAFBDFADD3" - "B371B306D0B289F459B491C814B5AD1F747610E990A60248A7DA5152F1CC" - "FC047EF42300131F9C4758F4D9F30579393B860AAD9AD2EE43D721D6DB9F" - "5800EF188386B94825AE05A883AC976D6970DF43EA6C83B86CE6D0F54020" - "7725B9890FCCEC83A49027872DAFD2740B7748E9C3B1752D6F12859CED07" - "E8882969B433EC66F17FFC29AC6FDBEA79230B0FAED5D94CF6B829A420BB" - "E3270323941776EE60DD6BFD660BDDCA8702030100012880013001128002" - "50D1F8B1ECF849B60FF93E37C4DEEF09E6FFB10BCFC996A4A24B7AA96928" - "835ED5A72E15846D0A14015733239BD8B6E6D5E5D229B08394CE1E0692C1" - "59C44337CA7CAF88476449B068D9D2FADED8EB1BC0F4B8F0FCAF293E8690" - "E74032095341803408A0E8279E545945EE97838FDE7812F7171C3CC4F5EC" - "F9418BBF1D336CE58F4CBB1B44D4ADE6BF3364BAE7EC093281846E569E13" - "E7719014030A6059044FE7BBFF3E8F5723AEDD54DC6E0D041B309D7700B5" - "5575690E95CE6085D0914F991C5F45E98CBB9C45BA33F47FD0862EBCC7EE" - "BA8E60643C86E85476B18AEF8DE871571A75681A75F75028A5B58751C09A" - "5296AAE99CEDCD9785E9E2103240D40A1AB6050AB002080112102CE5CCF4" - "2200D6B5BCCF33D7CC2D9C7018EAD1B88D05228E023082010A0282010100" - "BE1B661EEC4700DF4B0C83292D02AE029B8A224DD3048125049F74E30E12" - "57FC2BE8D9CFAF0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4" - "396A805833730DC6E534C62408B7C5076FC22568021C59ED34F98487196D" - "A32078DAFCA37C7CFB8E79612FA384963DF2167D5E87305D7BC92D621C10" - "160672C27B9A691B1534F60D78C5893E40C5FF8A3F9DF8898612E9A5CCB5" - "6F4A0CC2A61A7AEB04A9DCC015D9BC37DEF2AB9EAA9AAFD838869081D924" - "9755F129BB0DBECA3B894975A65A36FD005CE77CD407E925D3172E33122A" - "11D327968A08F8E771FAEB2540EB52D17C4906405F47C31F60F0AF6C78AF" - "53291B236E692B506A2AF92AF43E3A81020301000128800130011280033A" - "08A60418E5C81B8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259" - "834000FE35DCD814426F9C5D332418ED94C9C0C992217B1B6DC01C99085A" - "3C3956C8267B8773BABCF3F2C841C67D830F9DBC780DD68BF4E2FE424C6A" - "54123BE4B2A1F7E1F4DB58AB1164DAE9CF75C3392284A44B8CDB85D837E8" - "6C6B908243987E552C8693878C9A1B7BEA3759783036F1595C406D6CBBA7" - "F8642A9B3B244DAA1F00531D0B908ADE4B533FD9FAFA21D0FB0C033D2AD5" - "DDF24C60F4FAC30820758877F2E1A78EB44E9336DCFAFDF572BB22A84A5D" - "EFDF2EB87B61DE26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1" - "C379C96961316B5D2A66F38C222091AF74141B6CAF93507485A5D8F82808" - "025451824F00C8B6A0CD5803F6564584138C8B18BC679B442D837307B5CC" - "90B1FD1FD32288B4A5D18D2D80E5E6A7A9EFD255B8B363038BCC67AF534E" - "AEE4A5903E304EED4990BB5BE735DB027A6DE35329D321EC051B956C55A5" - "B11674017517FCC3C7FF7397C13A7B7087A1F6AEC7F6761A130A0C636F6D" - "70616E795F6E616D6512034C47451A150A0A6D6F64656C5F6E616D651207" - "4E6578757320341A200A116172636869746563747572655F6E616D65120B" - "61726D656162692D7637611A130A0B6465766963655F6E616D6512046D61" - "6B6F1A150A0C70726F647563745F6E616D6512056F6363616D1A440A0A62" - "75696C645F696E666F1236676F6F676C652F6F6363616D2F6D616B6F3A34" - "2E332F4A425F4D52322F3731343239313A7573657264656275672F646576" - "2D6B6579731A210A096465766963655F696412144C474D43323031323130" - "3035303036333932373812250A230A140801121030313233343536373839" - "41424344454610021A09393837363534333231180120002A0C3130383135" - "3136393638000030151A80027EA7ADEF77500FBC6A6081E739E0C50E1BDE" - "6DE4AB391109386768A95A04A52BE6693A5A98A25AC8EB9CDD6F40DCCF86" - "A3DA6C700E256A676BD3D7E492090DCF732C57333D9370F6D7AB87661701" - "597099CD45C2BCDFF1D47183E510D7A6D3561EFC7D4EB21814CB2CA0777F" - "26DD491B4D01469BB81A701545E2D3E98E1ADAB3A3BBD1D0433B312B3B51" - "39E88D3A92520BA399B2BE3489A72C3629745E4D8FC6DF6C8925A8FD8D6C" - "809CA80DBC29030615A55523305BC64DDFF52A87BD0DE9EEAB6445C5A184" - "7E5E6FE8D640C7B07F3B066B911793F06E973A02FA6EDD274570C4CA982D" - "353F1E72A5B77695D554B4FB554B46F5FA5B3B00805C136A9ED21FC222F6" - "04080212CC020A190A0939383736353433323112087AD49366C8D9191320" - "022800124108011801301E4239687474703A2F2F6B697230336663706731" - "37342E7769646576696E652E6E65742F7769646576696E652F6367692D62" - "696E2F64726D2E6367691A6612109161841718D5D0A4C4368820F4D03072" - "1A500F94F9BC0FF6B730709C6DEFD88D1CA8C7991A149D470493BDAD89E3" - "33AFC949F77D995CEA5E3D3DA5F7DF84E90CD4A9B4E138EA5F7EA75A520A" - "25017D69A9460D46548259F82959304CDEFE41936BE420011A7E0A103031" - "323334353637383941424344454612104F88BFEECE468B962BF09EA1257D" - "A50B1A200D48C122E022033C3E67A6ED4DA99B8AEA6F4B9E78634A548C06" - "0F49D39D9700200242340A209DE408B6F116F428C8E801C63AF34570A6C3" - "1D72180AA11F85D8DD4BC1C4D35412104E73935C2CC38C21408C537B3A5F" - "198B2081E7A68F051A20BC2696A2A1FBDF425675CAD455DEA2B44040D1F8" - "F0B6C675A28384CACFDF2F132280022D09FDA096972AA77FFEB09EA08AE8" - "82E89AC8591B398452CFB1383CCA16611571E223FE8DE82CDE9111557B2A" - "87A253B87B822F037FB492DE4B91B8AD4DB2E2F8B2E81BF1DE36CC7520CB" - "4BB3516E18322777287310257F2EC7110332504756DA8BC873448E93BA05" - "FD1AEB7AD1016D7BBB7FF5E7111987005322E342679F3D241429AE930A47" - "9D9F338699D3D6969A6479D1363AEB4AF19BDE9A73B33CD0EBFCF272FCEE" - "C6222AC08DCBD36077E0459D940BAE84ABA584700C02E70F3AE034ED7B76" - "4C6EE5E85663D657270C9AB40D3109920AB1C1C5DA1358E384EDF673253C" - "04F20AA6B0CC98F421A4CD86C4C88042B0DE9902D5D00B6AD817B1A313ED" - "5B2A5708011231121D1A1B0A190A0939383736353433323112087AD49366" - "C8D919132002280018022A0C35333631323234343600000030151A208CC3" - "C7D328DFACD43764C9FB582B858C8FF1D9863FF59C4D983478DB858AC32A" - "32610802123B0A190A0939383736353433323112087AD49366C8D9191320" - "02280112001A16200342120A106B63746C000000001FF4944E0000000020" - "82E7A68F051A2041EF0A9267D613D17AA90E1D1DA5BE091860E5E296D41D" - "6D0F75E73660C279B33A29687474703A2F2F68616D69642E6B69722E636F" - "72702E676F6F676C652E636F6D3A383838382F64726D12205CD2C43C618C" - "CA27BBCB2EEBDE32B57CBD51B424FD85DAB715B7F5A87546FD40")}}; + "0AB8150802100122B1150802121408011210303132333435363738394142434445461" + "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" + "7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302" + "5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B" + "E349553C319A9FB274905A8770ADC9CA4A2CBCD8E556A1587FA18BFD4D286C644A690" + "4F19EAAFBDFADD3B371B306D0B289F459B491C814B5AD1F747610E990A60248A7DA51" + "52F1CCFC047EF42300131F9C4758F4D9F30579393B860AAD9AD2EE43D721D6DB9F580" + "0EF188386B94825AE05A883AC976D6970DF43EA6C83B86CE6D0F540207725B9890FCC" + "EC83A49027872DAFD2740B7748E9C3B1752D6F12859CED07E8882969B433EC66F17FF" + "C29AC6FDBEA79230B0FAED5D94CF6B829A420BBE3270323941776EE60DD6BFD660BDD" + "CA870203010001288001300112800250D1F8B1ECF849B60FF93E37C4DEEF09E6FFB10" + "BCFC996A4A24B7AA96928835ED5A72E15846D0A14015733239BD8B6E6D5E5D229B083" + "94CE1E0692C159C44337CA7CAF88476449B068D9D2FADED8EB1BC0F4B8F0FCAF293E8" + "690E74032095341803408A0E8279E545945EE97838FDE7812F7171C3CC4F5ECF9418B" + "BF1D336CE58F4CBB1B44D4ADE6BF3364BAE7EC093281846E569E13E7719014030A605" + "9044FE7BBFF3E8F5723AEDD54DC6E0D041B309D7700B55575690E95CE6085D0914F99" + "1C5F45E98CBB9C45BA33F47FD0862EBCC7EEBA8E60643C86E85476B18AEF8DE871571" + "A75681A75F75028A5B58751C09A5296AAE99CEDCD9785E9E2103240D40A1AB6050AB0" + "02080112102CE5CCF42200D6B5BCCF33D7CC2D9C7018EAD1B88D05228E023082010A0" + "282010100BE1B661EEC4700DF4B0C83292D02AE029B8A224DD3048125049F74E30E12" + "57FC2BE8D9CFAF0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4396A80583" + "3730DC6E534C62408B7C5076FC22568021C59ED34F98487196DA32078DAFCA37C7CFB" + "8E79612FA384963DF2167D5E87305D7BC92D621C10160672C27B9A691B1534F60D78C" + "5893E40C5FF8A3F9DF8898612E9A5CCB56F4A0CC2A61A7AEB04A9DCC015D9BC37DEF2" + "AB9EAA9AAFD838869081D9249755F129BB0DBECA3B894975A65A36FD005CE77CD407E" + "925D3172E33122A11D327968A08F8E771FAEB2540EB52D17C4906405F47C31F60F0AF" + "6C78AF53291B236E692B506A2AF92AF43E3A81020301000128800130011280033A08A" + "60418E5C81B8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259834000FE35DC" + "D814426F9C5D332418ED94C9C0C992217B1B6DC01C99085A3C3956C8267B8773BABCF" + "3F2C841C67D830F9DBC780DD68BF4E2FE424C6A54123BE4B2A1F7E1F4DB58AB1164DA" + "E9CF75C3392284A44B8CDB85D837E86C6B908243987E552C8693878C9A1B7BEA37597" + "83036F1595C406D6CBBA7F8642A9B3B244DAA1F00531D0B908ADE4B533FD9FAFA21D0" + "FB0C033D2AD5DDF24C60F4FAC30820758877F2E1A78EB44E9336DCFAFDF572BB22A84" + "A5DEFDF2EB87B61DE26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1C379C9" + "6961316B5D2A66F38C222091AF74141B6CAF93507485A5D8F82808025451824F00C8B" + "6A0CD5803F6564584138C8B18BC679B442D837307B5CC90B1FD1FD32288B4A5D18D2D" + "80E5E6A7A9EFD255B8B363038BCC67AF534EAEE4A5903E304EED4990BB5BE735DB027" + "A6DE35329D321EC051B956C55A5B11674017517FCC3C7FF7397C13A7B7087A1F6AEC7" + "F6761A130A0C636F6D70616E795F6E616D6512034C47451A150A0A6D6F64656C5F6E6" + "16D6512074E6578757320341A200A116172636869746563747572655F6E616D65120B" + "61726D656162692D7637611A130A0B6465766963655F6E616D6512046D616B6F1A150" + "A0C70726F647563745F6E616D6512056F6363616D1A440A0A6275696C645F696E666F" + "1236676F6F676C652F6F6363616D2F6D616B6F3A342E332F4A425F4D52322F3731343" + "239313A7573657264656275672F6465762D6B6579731A210A096465766963655F6964" + "12144C474D433230313231303035303036333932373812250A230A140801121030313" + "23334353637383941424344454610021A09393837363534333231180120002A0C3130" + "3831353136393638000030151A80027EA7ADEF77500FBC6A6081E739E0C50E1BDE6DE" + "4AB391109386768A95A04A52BE6693A5A98A25AC8EB9CDD6F40DCCF86A3DA6C700E25" + "6A676BD3D7E492090DCF732C57333D9370F6D7AB87661701597099CD45C2BCDFF1D47" + "183E510D7A6D3561EFC7D4EB21814CB2CA0777F26DD491B4D01469BB81A701545E2D3" + "E98E1ADAB3A3BBD1D0433B312B3B5139E88D3A92520BA399B2BE3489A72C3629745E4" + "D8FC6DF6C8925A8FD8D6C809CA80DBC29030615A55523305BC64DDFF52A87BD0DE9EE" + "AB6445C5A1847E5E6FE8D640C7B07F3B066B911793F06E973A02FA6EDD274570C4CA9" + "82D353F1E72A5B77695D554B4FB554B46F5FA5B3B00805C136A9ED21FC222F6040802" + "12CC020A190A0939383736353433323112087AD49366C8D9191320022800124108011" + "801301E4239687474703A2F2F6B69723033666370673137342E7769646576696E652E" + "6E65742F7769646576696E652F6367692D62696E2F64726D2E6367691A66121091618" + "41718D5D0A4C4368820F4D030721A500F94F9BC0FF6B730709C6DEFD88D1CA8C7991A" + "149D470493BDAD89E333AFC949F77D995CEA5E3D3DA5F7DF84E90CD4A9B4E138EA5F7" + "EA75A520A25017D69A9460D46548259F82959304CDEFE41936BE420011A7E0A103031" + "323334353637383941424344454612104F88BFEECE468B962BF09EA1257DA50B1A200" + "D48C122E022033C3E67A6ED4DA99B8AEA6F4B9E78634A548C060F49D39D9700200242" + "340A209DE408B6F116F428C8E801C63AF34570A6C31D72180AA11F85D8DD4BC1C4D35" + "412104E73935C2CC38C21408C537B3A5F198B2081E7A68F051A20BC2696A2A1FBDF42" + "5675CAD455DEA2B44040D1F8F0B6C675A28384CACFDF2F132280022D09FDA096972AA" + "77FFEB09EA08AE882E89AC8591B398452CFB1383CCA16611571E223FE8DE82CDE9111" + "557B2A87A253B87B822F037FB492DE4B91B8AD4DB2E2F8B2E81BF1DE36CC7520CB4BB" + "3516E18322777287310257F2EC7110332504756DA8BC873448E93BA05FD1AEB7AD101" + "6D7BBB7FF5E7111987005322E342679F3D241429AE930A479D9F338699D3D6969A647" + "9D1363AEB4AF19BDE9A73B33CD0EBFCF272FCEEC6222AC08DCBD36077E0459D940BAE" + "84ABA584700C02E70F3AE034ED7B764C6EE5E85663D657270C9AB40D3109920AB1C1C" + "5DA1358E384EDF673253C04F20AA6B0CC98F421A4CD86C4C88042B0DE9902D5D00B6A" + "D817B1A313ED5B2A5708011231121D1A1B0A190A0939383736353433323112087AD49" + "366C8D919132002280018022A0C35333631323234343600000030151A208CC3C7D328" + "DFACD43764C9FB582B858C8FF1D9863FF59C4D983478DB858AC32A32610802123B0A1" + "90A0939383736353433323112087AD49366C8D919132002280112001A16200342120A" + "106B63746C000000001FF4944E000000002082E7A68F051A2041EF0A9267D613D17AA" + "90E1D1DA5BE091860E5E296D41D6D0F75E73660C279B33A2E68747470733A2F2F7465" + "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" + "36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910112201486F63DAF90694D3C63C8" + "EA8D2B68A7592252154A193D4DF8CEA95635EA0543")}}; // Sample license data and related data for storage and use for offline // playback. The license data and URLs in this test are not real. @@ -811,198 +778,175 @@ LicenseInfo license_update_test_data[] = { "0112001A16200342120A106B63746C0000000071FEF30B0000000020F4DF" "B68F051A2000351030900858FCFD6977B67803ADFD1280AA661E6B0BD30B" "08B2C467355129"), - "https://test.google.com/license/GetCencLicense", + "https://test.google.com/license/GetCencLicense", 0x0123456789abcdef, + 0x123456789abfedc, wvcdm::a2bs_hex( - "0AA41508021001229D150801121408011210303132333435363738394142" - "434445461A9D0E080112950C0AD70B080112EF090AB002080212103E560E" - "C5335E346F591BC4D07A7D5076189EDFB68F05228E023082010A02820101" - "00CC1715C81AD3F6F279C686F826E6D7C8961EB13318367D06B4061BBC57" - "E3C616A226A10F042CAD54D44C6484C725CD721A2A97C088E60AFF0E9C8E" - "03477A1B56B4C555C27CEAF55024375D8D3FB352DA4AAA2E911C876CB1B3" - "6162922E9130CCC5FB72F8DD41D05DE6889C4814A7344BA8C605DE399CA3" - "CBBF1E7DE3411EDFC60F9D3802C0BEE2B98FB71A5AB9C1A3D53FB5559918" - "3B84FDDC98AC3096B2EF99C62B545C5DCA3371F4D27DEF2052A23F13DE42" - "DE46B462CED2ABABB96B610A47E0620AA10D862FEB66BB4F00B13DFE6170" - "3AE872F0B4850C39138FC5DE4538E27BEAC8A48CC9526401BE3B42C7C6C5" - "D9624662081D7A5A1C581EB09619DD9DD302030100012880013001128002" - "6AB9AC42F1C17C1ECFB710BF2C35383F41CF7EFAB0DFDCC69090C20DE141" - "CB43055FD707C611CDAEE700076A1EBA32432D5C2B62A73B8B1672AD2C43" - "03598C02D34823A6BE387046937F55BB65F5B3571FDC6A1F0D947031003B" - "A651F8E48BF33D66B7A32A72CAC75EF66EF280B2D4F14FBCA70ECC508091" - "FE83AD886A680F55AB62F306435BC0043825F6A401BB9C341230127D3298" - "B67F82767050C95769964B0B5C27A36FA76ED161ABE4B6C18556C8077065" - "09A5146ADD958AF79B49EDE48CBCD6320C4DEC0BF564C5DD7E7EBA37A4CD" - "1D27F8D80E1B6931C92AC8E5C3BEC0ADAE621A3B78952485EBFC81A194BA" - "75BBD2C821C28AEB5D21CBE0A270E55E1AB6050AB002080112102CE5CCF4" - "2200D6B5BCCF33D7CC2D9C7018EAD1B88D05228E023082010A0282010100" - "BE1B661EEC4700DF4B0C83292D02AE029B8A224DD3048125049F74E30E12" - "57FC2BE8D9CFAF0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4" - "396A805833730DC6E534C62408B7C5076FC22568021C59ED34F98487196D" - "A32078DAFCA37C7CFB8E79612FA384963DF2167D5E87305D7BC92D621C10" - "160672C27B9A691B1534F60D78C5893E40C5FF8A3F9DF8898612E9A5CCB5" - "6F4A0CC2A61A7AEB04A9DCC015D9BC37DEF2AB9EAA9AAFD838869081D924" - "9755F129BB0DBECA3B894975A65A36FD005CE77CD407E925D3172E33122A" - "11D327968A08F8E771FAEB2540EB52D17C4906405F47C31F60F0AF6C78AF" - "53291B236E692B506A2AF92AF43E3A81020301000128800130011280033A" - "08A60418E5C81B8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259" - "834000FE35DCD814426F9C5D332418ED94C9C0C992217B1B6DC01C99085A" - "3C3956C8267B8773BABCF3F2C841C67D830F9DBC780DD68BF4E2FE424C6A" - "54123BE4B2A1F7E1F4DB58AB1164DAE9CF75C3392284A44B8CDB85D837E8" - "6C6B908243987E552C8693878C9A1B7BEA3759783036F1595C406D6CBBA7" - "F8642A9B3B244DAA1F00531D0B908ADE4B533FD9FAFA21D0FB0C033D2AD5" - "DDF24C60F4FAC30820758877F2E1A78EB44E9336DCFAFDF572BB22A84A5D" - "EFDF2EB87B61DE26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1" - "C379C96961316B5D2A66F38C222091AF74141B6CAF93507485A5D8F82808" - "025451824F00C8B6A0CD5803F6564584138C8B18BC679B442D837307B5CC" - "90B1FD1FD32288B4A5D18D2D80E5E6A7A9EFD255B8B363038BCC67AF534E" - "AEE4A5903E304EED4990BB5BE735DB027A6DE35329D321EC051B956C55A5" - "B11674017517FCC3C7FF7397C13A7B7087A1F6AEC7F6761A130A0C636F6D" - "70616E795F6E616D6512034C47451A150A0A6D6F64656C5F6E616D651207" - "4E6578757320341A200A116172636869746563747572655F6E616D65120B" - "61726D656162692D7637611A130A0B6465766963655F6E616D6512046D61" - "6B6F1A150A0C70726F647563745F6E616D6512056F6363616D1A440A0A62" - "75696C645F696E666F1236676F6F676C652F6F6363616D2F6D616B6F3A34" - "2E332F4A425F4D52322F3731343239313A7573657264656275672F646576" - "2D6B6579731A210A096465766963655F696412144C474D43323031323130" - "3035303036333932373812250A230A140801121030313233343536373839" - "41424344454610021A09393837363534333231180120002A0C3330373830" - "3630323034000030151A8002B5CA9C6B097EF2CBE2F8136C761130F3456E" - "D706127260151B4FF044DE233C1828B8618A312C031A2F844BEF0917F9B8" - "C6B8993A5D33E24B57B672A6C79D93EC98C46C5263EB8195FF7A5EBEBA08" - "A6F1080C19340A068E575568AE5EBADDD638FB435AC3EEC901E5F250BC97" - "4C498D6378C8BC1F4BACCED5725B8B77160444923DA3B729DCB681186565" - "B49EEFFE27CF1631F09EC31E543AAFE9F5996FB0BEAA5F80305D67ECF173" - "A8BD4A3B2CC75CEC3AA5881FF433E80838E1E1FA23CE7F22346DDDF7FEC3" - "DB0CE2C3F845CF9471088A022C8D0A63860764AE558BD0B5F66D78881ADB" - "F2D398F9BA349EFB2532C61E243DD45BB11C99422D13A82B7AAE967122F6" - "04080212CC020A190A09393837363534333231120892BE96420F0D5BF320" - "022800124108011801301E4239687474703A2F2F6B697230336663706731" - "37342E7769646576696E652E6E65742F7769646576696E652F6367692D62" - "696E2F64726D2E6367691A661210BB2E2D2B9C39697794897E08262749B4" - "1A50C0DED62431B1701F59E076E07EB0D2D43AEC6C589B35790739EB0B0E" - "D47236D0ECCE9A5408BE5F46F412334A5F4A4E3E493F202A263E185F06AE" - "37BA4351647BB9E6C997189FE1A03DCBF3FC90F46E5120011A7E0A103031" - "32333435363738394142434445461210319D7FB66154DFEC2AEDB164F29A" - "AC301A207448440734605CB29424FD1DA435A405DEE837757EA6A68C633A" - "65228317843D200242340A207F287706380C8085A4E5F85843D1C3B379F9" - "CE19ED5A2DAAF476B8AFE10488BF12100C8CDB1DA4C9FEBE5BBB530FE0D3" - "DA8720F4DFB68F051A20F4BCCEEEA658C5DD18D7B841E6D8991E616B57B5" - "92C44ED67050939B136815272280025CD92AB4672778CB865D528A2EAAAD" - "06435AE9186F1C159AFA1689473C4D8C8A5B8C64400CBBD0A02659EA0271" - "A1F40052030CA285B9C7211791BDD72193D5E01CEE43B0482DEAF034C8E9" - "BD88C7331BFA5CD71C2A3062EBD07CE1C80CCF3C5D7EC2D921D1BC5414D7" - "970CB098889D3FB5BF669EE5283E009CDCC880E79C77A21B12C7C0B8062D" - "66CBDEC2DCFD23885144C776B98C8A7A176C4EA183085EF02D2060904ADA" - "3CB161F4D198A0279DA19D7001EB2D20C70ABAA04B3760CB165006F6CBA4" - "BE0A2628C0C8398C122FF0DCF9292590E3C37BC7DB20F3B0921268F41FE7" - "6BD3EE764EBA13A22FDABC170860503FB93CC4A08D61102519D56A25EB9E" - "302A5708011231121D1A1B0A190A09393837363534333231120892BE9642" - "0F0D5BF32002280018022A0C31393132353333373731000030151A20F4FD" - "BECE547252D12BB9D488DAD50C76577A2FBCCC73F36D3C6B35096B8A3DC6" - "32610802123B0A190A09393837363534333231120892BE96420F0D5BF320" - "02280112001A16200342120A106B63746C0000000071FEF30B0000000020" - "F4DFB68F051A2000351030900858FCFD6977B67803ADFD1280AA661E6B0B" - "D30B08B2C4673551293A2E68747470733A2F2F746573742E676F6F676C65" - "2E636F6D2F6C6963656E73652F47657443656E634C6963656E736512200A" - "1C78D0E574D0827C3AE78A05EEC90BAC31D10686EC19EB0599F75B2D1AB4" - "C5")}, + "0AB8150802100122B1150801121408011210303132333435363738394142434445461" + "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" + "7A7D5076189EDFB68F05228E023082010A0282010100CC1715C81AD3F6F279C686F82" + "6E6D7C8961EB13318367D06B4061BBC57E3C616A226A10F042CAD54D44C6484C725CD" + "721A2A97C088E60AFF0E9C8E03477A1B56B4C555C27CEAF55024375D8D3FB352DA4AA" + "A2E911C876CB1B36162922E9130CCC5FB72F8DD41D05DE6889C4814A7344BA8C605DE" + "399CA3CBBF1E7DE3411EDFC60F9D3802C0BEE2B98FB71A5AB9C1A3D53FB55599183B8" + "4FDDC98AC3096B2EF99C62B545C5DCA3371F4D27DEF2052A23F13DE42DE46B462CED2" + "ABABB96B610A47E0620AA10D862FEB66BB4F00B13DFE61703AE872F0B4850C39138FC" + "5DE4538E27BEAC8A48CC9526401BE3B42C7C6C5D9624662081D7A5A1C581EB09619DD" + "9DD3020301000128800130011280026AB9AC42F1C17C1ECFB710BF2C35383F41CF7EF" + "AB0DFDCC69090C20DE141CB43055FD707C611CDAEE700076A1EBA32432D5C2B62A73B" + "8B1672AD2C4303598C02D34823A6BE387046937F55BB65F5B3571FDC6A1F0D9470310" + "03BA651F8E48BF33D66B7A32A72CAC75EF66EF280B2D4F14FBCA70ECC508091FE83AD" + "886A680F55AB62F306435BC0043825F6A401BB9C341230127D3298B67F82767050C95" + "769964B0B5C27A36FA76ED161ABE4B6C18556C807706509A5146ADD958AF79B49EDE4" + "8CBCD6320C4DEC0BF564C5DD7E7EBA37A4CD1D27F8D80E1B6931C92AC8E5C3BEC0ADA" + "E621A3B78952485EBFC81A194BA75BBD2C821C28AEB5D21CBE0A270E55E1AB6050AB0" + "02080112102CE5CCF42200D6B5BCCF33D7CC2D9C7018EAD1B88D05228E023082010A0" + "282010100BE1B661EEC4700DF4B0C83292D02AE029B8A224DD3048125049F74E30E12" + "57FC2BE8D9CFAF0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4396A80583" + "3730DC6E534C62408B7C5076FC22568021C59ED34F98487196DA32078DAFCA37C7CFB" + "8E79612FA384963DF2167D5E87305D7BC92D621C10160672C27B9A691B1534F60D78C" + "5893E40C5FF8A3F9DF8898612E9A5CCB56F4A0CC2A61A7AEB04A9DCC015D9BC37DEF2" + "AB9EAA9AAFD838869081D9249755F129BB0DBECA3B894975A65A36FD005CE77CD407E" + "925D3172E33122A11D327968A08F8E771FAEB2540EB52D17C4906405F47C31F60F0AF" + "6C78AF53291B236E692B506A2AF92AF43E3A81020301000128800130011280033A08A" + "60418E5C81B8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259834000FE35DC" + "D814426F9C5D332418ED94C9C0C992217B1B6DC01C99085A3C3956C8267B8773BABCF" + "3F2C841C67D830F9DBC780DD68BF4E2FE424C6A54123BE4B2A1F7E1F4DB58AB1164DA" + "E9CF75C3392284A44B8CDB85D837E86C6B908243987E552C8693878C9A1B7BEA37597" + "83036F1595C406D6CBBA7F8642A9B3B244DAA1F00531D0B908ADE4B533FD9FAFA21D0" + "FB0C033D2AD5DDF24C60F4FAC30820758877F2E1A78EB44E9336DCFAFDF572BB22A84" + "A5DEFDF2EB87B61DE26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1C379C9" + "6961316B5D2A66F38C222091AF74141B6CAF93507485A5D8F82808025451824F00C8B" + "6A0CD5803F6564584138C8B18BC679B442D837307B5CC90B1FD1FD32288B4A5D18D2D" + "80E5E6A7A9EFD255B8B363038BCC67AF534EAEE4A5903E304EED4990BB5BE735DB027" + "A6DE35329D321EC051B956C55A5B11674017517FCC3C7FF7397C13A7B7087A1F6AEC7" + "F6761A130A0C636F6D70616E795F6E616D6512034C47451A150A0A6D6F64656C5F6E6" + "16D6512074E6578757320341A200A116172636869746563747572655F6E616D65120B" + "61726D656162692D7637611A130A0B6465766963655F6E616D6512046D616B6F1A150" + "A0C70726F647563745F6E616D6512056F6363616D1A440A0A6275696C645F696E666F" + "1236676F6F676C652F6F6363616D2F6D616B6F3A342E332F4A425F4D52322F3731343" + "239313A7573657264656275672F6465762D6B6579731A210A096465766963655F6964" + "12144C474D433230313231303035303036333932373812250A230A140801121030313" + "23334353637383941424344454610021A09393837363534333231180120002A0C3330" + "3738303630323034000030151A8002B5CA9C6B097EF2CBE2F8136C761130F3456ED70" + "6127260151B4FF044DE233C1828B8618A312C031A2F844BEF0917F9B8C6B8993A5D33" + "E24B57B672A6C79D93EC98C46C5263EB8195FF7A5EBEBA08A6F1080C19340A068E575" + "568AE5EBADDD638FB435AC3EEC901E5F250BC974C498D6378C8BC1F4BACCED5725B8B" + "77160444923DA3B729DCB681186565B49EEFFE27CF1631F09EC31E543AAFE9F5996FB" + "0BEAA5F80305D67ECF173A8BD4A3B2CC75CEC3AA5881FF433E80838E1E1FA23CE7F22" + "346DDDF7FEC3DB0CE2C3F845CF9471088A022C8D0A63860764AE558BD0B5F66D78881" + "ADBF2D398F9BA349EFB2532C61E243DD45BB11C99422D13A82B7AAE967122F6040802" + "12CC020A190A09393837363534333231120892BE96420F0D5BF320022800124108011" + "801301E4239687474703A2F2F6B69723033666370673137342E7769646576696E652E" + "6E65742F7769646576696E652F6367692D62696E2F64726D2E6367691A661210BB2E2" + "D2B9C39697794897E08262749B41A50C0DED62431B1701F59E076E07EB0D2D43AEC6C" + "589B35790739EB0B0ED47236D0ECCE9A5408BE5F46F412334A5F4A4E3E493F202A263" + "E185F06AE37BA4351647BB9E6C997189FE1A03DCBF3FC90F46E5120011A7E0A103031" + "32333435363738394142434445461210319D7FB66154DFEC2AEDB164F29AAC301A207" + "448440734605CB29424FD1DA435A405DEE837757EA6A68C633A65228317843D200242" + "340A207F287706380C8085A4E5F85843D1C3B379F9CE19ED5A2DAAF476B8AFE10488B" + "F12100C8CDB1DA4C9FEBE5BBB530FE0D3DA8720F4DFB68F051A20F4BCCEEEA658C5DD" + "18D7B841E6D8991E616B57B592C44ED67050939B136815272280025CD92AB4672778C" + "B865D528A2EAAAD06435AE9186F1C159AFA1689473C4D8C8A5B8C64400CBBD0A02659" + "EA0271A1F40052030CA285B9C7211791BDD72193D5E01CEE43B0482DEAF034C8E9BD8" + "8C7331BFA5CD71C2A3062EBD07CE1C80CCF3C5D7EC2D921D1BC5414D7970CB098889D" + "3FB5BF669EE5283E009CDCC880E79C77A21B12C7C0B8062D66CBDEC2DCFD23885144C" + "776B98C8A7A176C4EA183085EF02D2060904ADA3CB161F4D198A0279DA19D7001EB2D" + "20C70ABAA04B3760CB165006F6CBA4BE0A2628C0C8398C122FF0DCF9292590E3C37BC" + "7DB20F3B0921268F41FE76BD3EE764EBA13A22FDABC170860503FB93CC4A08D611025" + "19D56A25EB9E302A5708011231121D1A1B0A190A09393837363534333231120892BE9" + "6420F0D5BF32002280018022A0C31393132353333373731000030151A20F4FDBECE54" + "7252D12BB9D488DAD50C76577A2FBCCC73F36D3C6B35096B8A3DC632610802123B0A1" + "90A09393837363534333231120892BE96420F0D5BF32002280112001A16200342120A" + "106B63746C0000000071FEF30B0000000020F4DFB68F051A2000351030900858FCFD6" + "977B67803ADFD1280AA661E6B0BD30B08B2C4673551293A2E68747470733A2F2F7465" + "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" + "36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD191011220C7ACA00F6877DAAE2E8F50" + "126C3222C2E584A50D08EFA75BC4FC091E7034E1DD")}, // license being released. all fields are identical except for license // state and hashed file data - {"", DeviceFiles::kLicenseStateReleasing, "", "", "", "", "", "", + {"", DeviceFiles::kLicenseStateReleasing, "", "", "", "", "", "", 0, 0, wvcdm::a2bs_hex( - "0AA41508021001229D150802121408011210303132333435363738394142" - "434445461A9D0E080112950C0AD70B080112EF090AB002080212103E560E" - "C5335E346F591BC4D07A7D5076189EDFB68F05228E023082010A02820101" - "00CC1715C81AD3F6F279C686F826E6D7C8961EB13318367D06B4061BBC57" - "E3C616A226A10F042CAD54D44C6484C725CD721A2A97C088E60AFF0E9C8E" - "03477A1B56B4C555C27CEAF55024375D8D3FB352DA4AAA2E911C876CB1B3" - "6162922E9130CCC5FB72F8DD41D05DE6889C4814A7344BA8C605DE399CA3" - "CBBF1E7DE3411EDFC60F9D3802C0BEE2B98FB71A5AB9C1A3D53FB5559918" - "3B84FDDC98AC3096B2EF99C62B545C5DCA3371F4D27DEF2052A23F13DE42" - "DE46B462CED2ABABB96B610A47E0620AA10D862FEB66BB4F00B13DFE6170" - "3AE872F0B4850C39138FC5DE4538E27BEAC8A48CC9526401BE3B42C7C6C5" - "D9624662081D7A5A1C581EB09619DD9DD302030100012880013001128002" - "6AB9AC42F1C17C1ECFB710BF2C35383F41CF7EFAB0DFDCC69090C20DE141" - "CB43055FD707C611CDAEE700076A1EBA32432D5C2B62A73B8B1672AD2C43" - "03598C02D34823A6BE387046937F55BB65F5B3571FDC6A1F0D947031003B" - "A651F8E48BF33D66B7A32A72CAC75EF66EF280B2D4F14FBCA70ECC508091" - "FE83AD886A680F55AB62F306435BC0043825F6A401BB9C341230127D3298" - "B67F82767050C95769964B0B5C27A36FA76ED161ABE4B6C18556C8077065" - "09A5146ADD958AF79B49EDE48CBCD6320C4DEC0BF564C5DD7E7EBA37A4CD" - "1D27F8D80E1B6931C92AC8E5C3BEC0ADAE621A3B78952485EBFC81A194BA" - "75BBD2C821C28AEB5D21CBE0A270E55E1AB6050AB002080112102CE5CCF4" - "2200D6B5BCCF33D7CC2D9C7018EAD1B88D05228E023082010A0282010100" - "BE1B661EEC4700DF4B0C83292D02AE029B8A224DD3048125049F74E30E12" - "57FC2BE8D9CFAF0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4" - "396A805833730DC6E534C62408B7C5076FC22568021C59ED34F98487196D" - "A32078DAFCA37C7CFB8E79612FA384963DF2167D5E87305D7BC92D621C10" - "160672C27B9A691B1534F60D78C5893E40C5FF8A3F9DF8898612E9A5CCB5" - "6F4A0CC2A61A7AEB04A9DCC015D9BC37DEF2AB9EAA9AAFD838869081D924" - "9755F129BB0DBECA3B894975A65A36FD005CE77CD407E925D3172E33122A" - "11D327968A08F8E771FAEB2540EB52D17C4906405F47C31F60F0AF6C78AF" - "53291B236E692B506A2AF92AF43E3A81020301000128800130011280033A" - "08A60418E5C81B8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259" - "834000FE35DCD814426F9C5D332418ED94C9C0C992217B1B6DC01C99085A" - "3C3956C8267B8773BABCF3F2C841C67D830F9DBC780DD68BF4E2FE424C6A" - "54123BE4B2A1F7E1F4DB58AB1164DAE9CF75C3392284A44B8CDB85D837E8" - "6C6B908243987E552C8693878C9A1B7BEA3759783036F1595C406D6CBBA7" - "F8642A9B3B244DAA1F00531D0B908ADE4B533FD9FAFA21D0FB0C033D2AD5" - "DDF24C60F4FAC30820758877F2E1A78EB44E9336DCFAFDF572BB22A84A5D" - "EFDF2EB87B61DE26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1" - "C379C96961316B5D2A66F38C222091AF74141B6CAF93507485A5D8F82808" - "025451824F00C8B6A0CD5803F6564584138C8B18BC679B442D837307B5CC" - "90B1FD1FD32288B4A5D18D2D80E5E6A7A9EFD255B8B363038BCC67AF534E" - "AEE4A5903E304EED4990BB5BE735DB027A6DE35329D321EC051B956C55A5" - "B11674017517FCC3C7FF7397C13A7B7087A1F6AEC7F6761A130A0C636F6D" - "70616E795F6E616D6512034C47451A150A0A6D6F64656C5F6E616D651207" - "4E6578757320341A200A116172636869746563747572655F6E616D65120B" - "61726D656162692D7637611A130A0B6465766963655F6E616D6512046D61" - "6B6F1A150A0C70726F647563745F6E616D6512056F6363616D1A440A0A62" - "75696C645F696E666F1236676F6F676C652F6F6363616D2F6D616B6F3A34" - "2E332F4A425F4D52322F3731343239313A7573657264656275672F646576" - "2D6B6579731A210A096465766963655F696412144C474D43323031323130" - "3035303036333932373812250A230A140801121030313233343536373839" - "41424344454610021A09393837363534333231180120002A0C3330373830" - "3630323034000030151A8002B5CA9C6B097EF2CBE2F8136C761130F3456E" - "D706127260151B4FF044DE233C1828B8618A312C031A2F844BEF0917F9B8" - "C6B8993A5D33E24B57B672A6C79D93EC98C46C5263EB8195FF7A5EBEBA08" - "A6F1080C19340A068E575568AE5EBADDD638FB435AC3EEC901E5F250BC97" - "4C498D6378C8BC1F4BACCED5725B8B77160444923DA3B729DCB681186565" - "B49EEFFE27CF1631F09EC31E543AAFE9F5996FB0BEAA5F80305D67ECF173" - "A8BD4A3B2CC75CEC3AA5881FF433E80838E1E1FA23CE7F22346DDDF7FEC3" - "DB0CE2C3F845CF9471088A022C8D0A63860764AE558BD0B5F66D78881ADB" - "F2D398F9BA349EFB2532C61E243DD45BB11C99422D13A82B7AAE967122F6" - "04080212CC020A190A09393837363534333231120892BE96420F0D5BF320" - "022800124108011801301E4239687474703A2F2F6B697230336663706731" - "37342E7769646576696E652E6E65742F7769646576696E652F6367692D62" - "696E2F64726D2E6367691A661210BB2E2D2B9C39697794897E08262749B4" - "1A50C0DED62431B1701F59E076E07EB0D2D43AEC6C589B35790739EB0B0E" - "D47236D0ECCE9A5408BE5F46F412334A5F4A4E3E493F202A263E185F06AE" - "37BA4351647BB9E6C997189FE1A03DCBF3FC90F46E5120011A7E0A103031" - "32333435363738394142434445461210319D7FB66154DFEC2AEDB164F29A" - "AC301A207448440734605CB29424FD1DA435A405DEE837757EA6A68C633A" - "65228317843D200242340A207F287706380C8085A4E5F85843D1C3B379F9" - "CE19ED5A2DAAF476B8AFE10488BF12100C8CDB1DA4C9FEBE5BBB530FE0D3" - "DA8720F4DFB68F051A20F4BCCEEEA658C5DD18D7B841E6D8991E616B57B5" - "92C44ED67050939B136815272280025CD92AB4672778CB865D528A2EAAAD" - "06435AE9186F1C159AFA1689473C4D8C8A5B8C64400CBBD0A02659EA0271" - "A1F40052030CA285B9C7211791BDD72193D5E01CEE43B0482DEAF034C8E9" - "BD88C7331BFA5CD71C2A3062EBD07CE1C80CCF3C5D7EC2D921D1BC5414D7" - "970CB098889D3FB5BF669EE5283E009CDCC880E79C77A21B12C7C0B8062D" - "66CBDEC2DCFD23885144C776B98C8A7A176C4EA183085EF02D2060904ADA" - "3CB161F4D198A0279DA19D7001EB2D20C70ABAA04B3760CB165006F6CBA4" - "BE0A2628C0C8398C122FF0DCF9292590E3C37BC7DB20F3B0921268F41FE7" - "6BD3EE764EBA13A22FDABC170860503FB93CC4A08D61102519D56A25EB9E" - "302A5708011231121D1A1B0A190A09393837363534333231120892BE9642" - "0F0D5BF32002280018022A0C31393132353333373731000030151A20F4FD" - "BECE547252D12BB9D488DAD50C76577A2FBCCC73F36D3C6B35096B8A3DC6" - "32610802123B0A190A09393837363534333231120892BE96420F0D5BF320" - "02280112001A16200342120A106B63746C0000000071FEF30B0000000020" - "F4DFB68F051A2000351030900858FCFD6977B67803ADFD1280AA661E6B0B" - "D30B08B2C4673551293A2E68747470733A2F2F746573742E676F6F676C65" - "2E636F6D2F6C6963656E73652F47657443656E634C6963656E736512208F" - "7186A244EF561E3B07DC459BC681A0798B180667EA448327F6BBBD30212A" - "49")}}; + "0AB8150802100122B1150802121408011210303132333435363738394142434445461" + "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" + "7A7D5076189EDFB68F05228E023082010A0282010100CC1715C81AD3F6F279C686F82" + "6E6D7C8961EB13318367D06B4061BBC57E3C616A226A10F042CAD54D44C6484C725CD" + "721A2A97C088E60AFF0E9C8E03477A1B56B4C555C27CEAF55024375D8D3FB352DA4AA" + "A2E911C876CB1B36162922E9130CCC5FB72F8DD41D05DE6889C4814A7344BA8C605DE" + "399CA3CBBF1E7DE3411EDFC60F9D3802C0BEE2B98FB71A5AB9C1A3D53FB55599183B8" + "4FDDC98AC3096B2EF99C62B545C5DCA3371F4D27DEF2052A23F13DE42DE46B462CED2" + "ABABB96B610A47E0620AA10D862FEB66BB4F00B13DFE61703AE872F0B4850C39138FC" + "5DE4538E27BEAC8A48CC9526401BE3B42C7C6C5D9624662081D7A5A1C581EB09619DD" + "9DD3020301000128800130011280026AB9AC42F1C17C1ECFB710BF2C35383F41CF7EF" + "AB0DFDCC69090C20DE141CB43055FD707C611CDAEE700076A1EBA32432D5C2B62A73B" + "8B1672AD2C4303598C02D34823A6BE387046937F55BB65F5B3571FDC6A1F0D9470310" + "03BA651F8E48BF33D66B7A32A72CAC75EF66EF280B2D4F14FBCA70ECC508091FE83AD" + "886A680F55AB62F306435BC0043825F6A401BB9C341230127D3298B67F82767050C95" + "769964B0B5C27A36FA76ED161ABE4B6C18556C807706509A5146ADD958AF79B49EDE4" + "8CBCD6320C4DEC0BF564C5DD7E7EBA37A4CD1D27F8D80E1B6931C92AC8E5C3BEC0ADA" + "E621A3B78952485EBFC81A194BA75BBD2C821C28AEB5D21CBE0A270E55E1AB6050AB0" + "02080112102CE5CCF42200D6B5BCCF33D7CC2D9C7018EAD1B88D05228E023082010A0" + "282010100BE1B661EEC4700DF4B0C83292D02AE029B8A224DD3048125049F74E30E12" + "57FC2BE8D9CFAF0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4396A80583" + "3730DC6E534C62408B7C5076FC22568021C59ED34F98487196DA32078DAFCA37C7CFB" + "8E79612FA384963DF2167D5E87305D7BC92D621C10160672C27B9A691B1534F60D78C" + "5893E40C5FF8A3F9DF8898612E9A5CCB56F4A0CC2A61A7AEB04A9DCC015D9BC37DEF2" + "AB9EAA9AAFD838869081D9249755F129BB0DBECA3B894975A65A36FD005CE77CD407E" + "925D3172E33122A11D327968A08F8E771FAEB2540EB52D17C4906405F47C31F60F0AF" + "6C78AF53291B236E692B506A2AF92AF43E3A81020301000128800130011280033A08A" + "60418E5C81B8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259834000FE35DC" + "D814426F9C5D332418ED94C9C0C992217B1B6DC01C99085A3C3956C8267B8773BABCF" + "3F2C841C67D830F9DBC780DD68BF4E2FE424C6A54123BE4B2A1F7E1F4DB58AB1164DA" + "E9CF75C3392284A44B8CDB85D837E86C6B908243987E552C8693878C9A1B7BEA37597" + "83036F1595C406D6CBBA7F8642A9B3B244DAA1F00531D0B908ADE4B533FD9FAFA21D0" + "FB0C033D2AD5DDF24C60F4FAC30820758877F2E1A78EB44E9336DCFAFDF572BB22A84" + "A5DEFDF2EB87B61DE26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1C379C9" + "6961316B5D2A66F38C222091AF74141B6CAF93507485A5D8F82808025451824F00C8B" + "6A0CD5803F6564584138C8B18BC679B442D837307B5CC90B1FD1FD32288B4A5D18D2D" + "80E5E6A7A9EFD255B8B363038BCC67AF534EAEE4A5903E304EED4990BB5BE735DB027" + "A6DE35329D321EC051B956C55A5B11674017517FCC3C7FF7397C13A7B7087A1F6AEC7" + "F6761A130A0C636F6D70616E795F6E616D6512034C47451A150A0A6D6F64656C5F6E6" + "16D6512074E6578757320341A200A116172636869746563747572655F6E616D65120B" + "61726D656162692D7637611A130A0B6465766963655F6E616D6512046D616B6F1A150" + "A0C70726F647563745F6E616D6512056F6363616D1A440A0A6275696C645F696E666F" + "1236676F6F676C652F6F6363616D2F6D616B6F3A342E332F4A425F4D52322F3731343" + "239313A7573657264656275672F6465762D6B6579731A210A096465766963655F6964" + "12144C474D433230313231303035303036333932373812250A230A140801121030313" + "23334353637383941424344454610021A09393837363534333231180120002A0C3330" + "3738303630323034000030151A8002B5CA9C6B097EF2CBE2F8136C761130F3456ED70" + "6127260151B4FF044DE233C1828B8618A312C031A2F844BEF0917F9B8C6B8993A5D33" + "E24B57B672A6C79D93EC98C46C5263EB8195FF7A5EBEBA08A6F1080C19340A068E575" + "568AE5EBADDD638FB435AC3EEC901E5F250BC974C498D6378C8BC1F4BACCED5725B8B" + "77160444923DA3B729DCB681186565B49EEFFE27CF1631F09EC31E543AAFE9F5996FB" + "0BEAA5F80305D67ECF173A8BD4A3B2CC75CEC3AA5881FF433E80838E1E1FA23CE7F22" + "346DDDF7FEC3DB0CE2C3F845CF9471088A022C8D0A63860764AE558BD0B5F66D78881" + "ADBF2D398F9BA349EFB2532C61E243DD45BB11C99422D13A82B7AAE967122F6040802" + "12CC020A190A09393837363534333231120892BE96420F0D5BF320022800124108011" + "801301E4239687474703A2F2F6B69723033666370673137342E7769646576696E652E" + "6E65742F7769646576696E652F6367692D62696E2F64726D2E6367691A661210BB2E2" + "D2B9C39697794897E08262749B41A50C0DED62431B1701F59E076E07EB0D2D43AEC6C" + "589B35790739EB0B0ED47236D0ECCE9A5408BE5F46F412334A5F4A4E3E493F202A263" + "E185F06AE37BA4351647BB9E6C997189FE1A03DCBF3FC90F46E5120011A7E0A103031" + "32333435363738394142434445461210319D7FB66154DFEC2AEDB164F29AAC301A207" + "448440734605CB29424FD1DA435A405DEE837757EA6A68C633A65228317843D200242" + "340A207F287706380C8085A4E5F85843D1C3B379F9CE19ED5A2DAAF476B8AFE10488B" + "F12100C8CDB1DA4C9FEBE5BBB530FE0D3DA8720F4DFB68F051A20F4BCCEEEA658C5DD" + "18D7B841E6D8991E616B57B592C44ED67050939B136815272280025CD92AB4672778C" + "B865D528A2EAAAD06435AE9186F1C159AFA1689473C4D8C8A5B8C64400CBBD0A02659" + "EA0271A1F40052030CA285B9C7211791BDD72193D5E01CEE43B0482DEAF034C8E9BD8" + "8C7331BFA5CD71C2A3062EBD07CE1C80CCF3C5D7EC2D921D1BC5414D7970CB098889D" + "3FB5BF669EE5283E009CDCC880E79C77A21B12C7C0B8062D66CBDEC2DCFD23885144C" + "776B98C8A7A176C4EA183085EF02D2060904ADA3CB161F4D198A0279DA19D7001EB2D" + "20C70ABAA04B3760CB165006F6CBA4BE0A2628C0C8398C122FF0DCF9292590E3C37BC" + "7DB20F3B0921268F41FE76BD3EE764EBA13A22FDABC170860503FB93CC4A08D611025" + "19D56A25EB9E302A5708011231121D1A1B0A190A09393837363534333231120892BE9" + "6420F0D5BF32002280018022A0C31393132353333373731000030151A20F4FDBECE54" + "7252D12BB9D488DAD50C76577A2FBCCC73F36D3C6B35096B8A3DC632610802123B0A1" + "90A09393837363534333231120892BE96420F0D5BF32002280112001A16200342120A" + "106B63746C0000000071FEF30B0000000020F4DFB68F051A2000351030900858FCFD6" + "977B67803ADFD1280AA661E6B0BD30B08B2C4673551293A2E68747470733A2F2F7465" + "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" + "36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910112203D8933A735A22FE27AA956" + "802B597529E8FFCB91A5F3CBBB3CE0C38E4AF3DC88")}}; struct UsageInfo { std::string provider_session_token; @@ -1324,7 +1268,7 @@ class DeviceFilesTest : public ::testing::Test { return sizeof(DeviceFiles::LicenseState) + data.pssh_data.size() + data.key_request.size() + data.key_response.size() + data.key_renewal_request.size() + data.key_renewal_response.size() + - data.key_release_url.size(); + data.key_release_url.size() + 2 * sizeof(int64_t); } std::string device_base_path_; @@ -1519,7 +1463,9 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) { license_test_data[license_num].key_response, license_test_data[license_num].key_renewal_request, license_test_data[license_num].key_renewal_response, - license_test_data[license_num].key_release_url)); + license_test_data[license_num].key_release_url, + license_test_data[license_num].playback_start_time, + license_test_data[license_num].last_playback_time)); } INSTANTIATE_TEST_CASE_P(StoreLicense, DeviceFilesStoreTest, @@ -1563,7 +1509,9 @@ TEST_F(DeviceFilesTest, StoreLicenses) { license_test_data[i].key_response, license_test_data[i].key_renewal_request, license_test_data[i].key_renewal_response, - license_test_data[i].key_release_url)); + license_test_data[i].key_release_url, + license_test_data[i].playback_start_time, + license_test_data[i].last_playback_time)); } } @@ -1598,6 +1546,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) { CdmKeyResponse key_response; CdmKeyMessage key_renewal_request; CdmKeyResponse key_renewal_response; + int64_t playback_start_time, last_playback_time; std::string release_server_url; for (size_t i = 0; i < kNumberOfLicenses; i++) { @@ -1605,13 +1554,16 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) { EXPECT_TRUE(device_files.RetrieveLicense( license_test_data[i].key_set_id, &license_state, &pssh_data, &key_request, &key_response, &key_renewal_request, - &key_renewal_response, &release_server_url)); + &key_renewal_response, &release_server_url, &playback_start_time, + &last_playback_time)); EXPECT_EQ(license_test_data[i].license_state, license_state); EXPECT_EQ(license_test_data[i].pssh_data, pssh_data); EXPECT_EQ(license_test_data[i].key_request, key_request); EXPECT_EQ(license_test_data[i].key_response, key_response); EXPECT_EQ(license_test_data[i].key_request, key_request); EXPECT_EQ(license_test_data[i].key_response, key_response); + EXPECT_EQ(license_test_data[i].playback_start_time, playback_start_time); + EXPECT_EQ(license_test_data[i].last_playback_time, last_playback_time); } } @@ -1724,7 +1676,9 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) { license_update_test_data[0].key_response, license_update_test_data[0].key_renewal_request, license_update_test_data[0].key_renewal_response, - license_update_test_data[0].key_release_url)); + license_update_test_data[0].key_release_url, + license_update_test_data[0].playback_start_time, + license_update_test_data[0].last_playback_time)); EXPECT_TRUE(device_files.StoreLicense( license_update_test_data[0].key_set_id, @@ -1734,7 +1688,9 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) { license_update_test_data[0].key_response, license_update_test_data[0].key_renewal_request, license_update_test_data[0].key_renewal_response, - license_update_test_data[0].key_release_url)); + license_update_test_data[0].key_release_url, + license_update_test_data[0].playback_start_time, + license_update_test_data[0].last_playback_time)); } TEST_F(DeviceFilesTest, DeleteLicense) { @@ -1770,17 +1726,20 @@ TEST_F(DeviceFilesTest, DeleteLicense) { CdmKeyMessage key_renewal_request; CdmKeyResponse key_renewal_response; std::string release_server_url; + int64_t playback_start_time, last_playback_time; EXPECT_TRUE(device_files.RetrieveLicense( license_test_data[0].key_set_id, &license_state, &pssh_data, &key_request, &key_response, &key_renewal_request, &key_renewal_response, - &release_server_url)); + &release_server_url, &playback_start_time, &last_playback_time)); EXPECT_EQ(license_test_data[0].license_state, license_state); EXPECT_EQ(license_test_data[0].pssh_data, pssh_data); EXPECT_EQ(license_test_data[0].key_request, key_request); EXPECT_EQ(license_test_data[0].key_response, key_response); EXPECT_EQ(license_test_data[0].key_request, key_request); EXPECT_EQ(license_test_data[0].key_response, key_response); + EXPECT_EQ(license_test_data[0].playback_start_time, playback_start_time); + EXPECT_EQ(license_test_data[0].last_playback_time, last_playback_time); EXPECT_TRUE(device_files.DeleteLicense(license_test_data[0].key_set_id)); EXPECT_FALSE(device_files.LicenseExists(license_test_data[0].key_set_id)); diff --git a/libwvdrmengine/cdm/core/test/policy_engine_unittest.cpp b/libwvdrmengine/cdm/core/test/policy_engine_unittest.cpp index 24e67314..a093c8e0 100644 --- a/libwvdrmengine/cdm/core/test/policy_engine_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/policy_engine_unittest.cpp @@ -138,8 +138,7 @@ TEST_F(PolicyEngineTest, PlaybackFailed_CanPlayFalse) { policy->set_can_play(false); EXPECT_CALL(*mock_clock_, GetCurrentTime()) - .WillOnce(Return(kLicenseStartTime + 1)) - .WillOnce(Return(kLicenseStartTime + 5)); + .WillOnce(Return(kLicenseStartTime + 1)); policy_engine_->SetLicense(license_); EXPECT_FALSE(policy_engine_->can_decrypt()); @@ -163,8 +162,8 @@ TEST_F(PolicyEngineTest, PlaybackFails_RentalDurationExpired) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) .WillOnce(Return(kLicenseStartTime + 5)) - .WillOnce(Return(kLicenseStartTime + min_duration)) - .WillOnce(Return(kLicenseStartTime + min_duration + 1)); + .WillOnce(Return(kLicenseStartTime + min_duration - 1)) + .WillOnce(Return(kLicenseStartTime + min_duration)); policy_engine_->SetLicense(license_); @@ -220,8 +219,8 @@ TEST_F(PolicyEngineTest, PlaybackFails_LicenseDurationExpired) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) .WillOnce(Return(kLicenseStartTime + 5)) - .WillOnce(Return(kLicenseStartTime + min_duration)) - .WillOnce(Return(kLicenseStartTime + 1 + min_duration)); + .WillOnce(Return(kLicenseStartTime + min_duration - 1)) + .WillOnce(Return(kLicenseStartTime + min_duration)); policy_engine_->SetLicense(license_); @@ -248,8 +247,8 @@ TEST_F(PolicyEngineTest, PlaybackFails_ExpiryBeforeRenewalDelay) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) .WillOnce(Return(kLicenseStartTime + 5)) - .WillOnce(Return(kLicenseStartTime + min_duration)) - .WillOnce(Return(kLicenseStartTime + 1 + min_duration)); + .WillOnce(Return(kLicenseStartTime + min_duration - 1)) + .WillOnce(Return(kLicenseStartTime + min_duration)); policy_engine_->SetLicense(license_); @@ -277,10 +276,10 @@ TEST_F(PolicyEngineTest, PlaybackOk_RentalDuration0) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) .WillOnce(Return(kLicenseStartTime + 5)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay - 1)) .WillOnce(Return(kLicenseStartTime + license_renewal_delay)) - .WillOnce(Return(kLicenseStartTime + 1 + license_renewal_delay)) - .WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration)) - .WillOnce(Return(kLicenseStartTime + 1 + kStreamingLicenseDuration)); + .WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration - 1)) + .WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration)); policy_engine_->SetLicense(license_); @@ -357,8 +356,8 @@ TEST_F(PolicyEngineTest, PlaybackOk_LicenseDuration0) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) .WillOnce(Return(kLicenseStartTime + 5)) - .WillOnce(Return(kLicenseStartTime + min_duration)) - .WillOnce(Return(kLicenseStartTime + 1 + min_duration)); + .WillOnce(Return(kLicenseStartTime + min_duration - 1)) + .WillOnce(Return(kLicenseStartTime + min_duration)); policy_engine_->SetLicense(license_); @@ -387,8 +386,8 @@ TEST_F(PolicyEngineTest, PlaybackOk_Durations0) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) .WillOnce(Return(kLicenseStartTime + 5)) - .WillOnce(Return(kLicenseStartTime + kHighDuration)) - .WillOnce(Return(kLicenseStartTime + kHighDuration + 10)); + .WillOnce(Return(kLicenseStartTime + kHighDuration - 1)) + .WillOnce(Return(kLicenseStartTime + kHighDuration)); policy_engine_->SetLicense(license_); @@ -406,6 +405,29 @@ TEST_F(PolicyEngineTest, PlaybackOk_Durations0) { EXPECT_TRUE(policy_engine_->can_decrypt()); } +TEST_F(PolicyEngineTest, PlaybackOk_LicenseWithFutureStartTime) { + EXPECT_CALL(*mock_clock_, GetCurrentTime()) + .WillOnce(Return(kLicenseStartTime - 100)) + .WillOnce(Return(kLicenseStartTime - 50)) + .WillOnce(Return(kLicenseStartTime)) + .WillOnce(Return(kLicenseStartTime + 10)); + + policy_engine_->SetLicense(license_); + + bool event_occurred; + CdmEventType event; + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + EXPECT_FALSE(policy_engine_->can_decrypt()); + + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + EXPECT_TRUE(policy_engine_->can_decrypt()); + + policy_engine_->BeginDecryption(); + EXPECT_TRUE(policy_engine_->can_decrypt()); +} + TEST_F(PolicyEngineTest, PlaybackFailed_CanRenewFalse) { License_Policy* policy = license_.mutable_policy(); policy->set_can_renew(false); @@ -480,6 +502,49 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccess) { EXPECT_TRUE(policy_engine_->can_decrypt()); } +TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccess_WithFutureStartTime) { + int64_t license_renewal_delay = + GetLicenseRenewalDelay(kStreamingLicenseDuration); + + EXPECT_CALL(*mock_clock_, GetCurrentTime()) + .WillOnce(Return(kLicenseStartTime + 1)) + .WillOnce(Return(kLicenseStartTime + 5)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay - 15)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + 10)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + 20)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + 30)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + 60)); + + policy_engine_->SetLicense(license_); + + policy_engine_->BeginDecryption(); + EXPECT_TRUE(policy_engine_->can_decrypt()); + + bool event_occurred; + CdmEventType event; + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_TRUE(event_occurred); + EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event); + EXPECT_TRUE(policy_engine_->can_decrypt()); + + license_.set_license_start_time(kLicenseStartTime + license_renewal_delay + + 50); + LicenseIdentification* id = license_.mutable_id(); + id->set_version(2); + policy_engine_->UpdateLicense(license_); + + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + EXPECT_FALSE(policy_engine_->can_decrypt()); + + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + EXPECT_TRUE(policy_engine_->can_decrypt()); +} + TEST_F(PolicyEngineTest, PlaybackFailed_RenewFailedVersionNotUpdated) { int64_t license_renewal_delay = GetLicenseRenewalDelay(kStreamingLicenseDuration); @@ -790,7 +855,7 @@ TEST_F(PolicyEngineTest, QuerySuccess) { ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); ss >> remaining_time; ss.clear(); - EXPECT_EQ(kStreamingLicenseDuration - 99, remaining_time); + EXPECT_EQ(kStreamingLicenseDuration - 100, remaining_time); ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); ss >> remaining_time; EXPECT_EQ(kPlaybackDuration, remaining_time); @@ -816,7 +881,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_PlaybackNotBegun) { std::istringstream ss; ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); ss >> remaining_time; - EXPECT_EQ(kStreamingLicenseDuration - 99, remaining_time); + EXPECT_EQ(kStreamingLicenseDuration - 100, remaining_time); ss.clear(); ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); ss >> remaining_time; @@ -832,7 +897,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_PlaybackNotBegun) { ss.clear(); ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); ss >> remaining_time; - EXPECT_EQ(kStreamingLicenseDuration - 199, remaining_time); + EXPECT_EQ(kStreamingLicenseDuration - 200, remaining_time); ss.clear(); ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); ss >> remaining_time; @@ -861,7 +926,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_PlaybackBegun) { std::istringstream ss; ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); ss >> remaining_time; - EXPECT_EQ(kStreamingLicenseDuration - 49, remaining_time); + EXPECT_EQ(kStreamingLicenseDuration - 50, remaining_time); ss.clear(); ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); ss >> remaining_time; @@ -885,7 +950,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_PlaybackBegun) { ss.clear(); ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); ss >> remaining_time; - EXPECT_EQ(kStreamingLicenseDuration - 199, remaining_time); + EXPECT_EQ(kStreamingLicenseDuration - 200, remaining_time); ss.clear(); ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); ss >> remaining_time; @@ -931,7 +996,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_Offline) { std::istringstream ss; ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); ss >> remaining_time; - EXPECT_EQ(kOfflineLicenseDuration - 299, remaining_time); + EXPECT_EQ(kOfflineLicenseDuration - 300, remaining_time); ss.clear(); ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); ss >> remaining_time; @@ -952,8 +1017,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_CanPlayFalse) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) - .WillOnce(Return(kLicenseStartTime + 100)) - .WillOnce(Return(kLicenseStartTime + 200)); + .WillOnce(Return(kLicenseStartTime + 100)); policy_engine_->SetLicense(license_); EXPECT_FALSE(policy_engine_->can_decrypt()); @@ -977,7 +1041,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_CanPlayFalse) { std::istringstream ss; ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); ss >> remaining_time; - EXPECT_EQ(kOfflineLicenseDuration - 199, remaining_time); + EXPECT_EQ(kOfflineLicenseDuration - 100, remaining_time); ss.clear(); ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); ss >> remaining_time; @@ -995,8 +1059,8 @@ TEST_F(PolicyEngineTest, QuerySuccess_RentalDurationExpired) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) .WillOnce(Return(kLicenseStartTime + 5)) + .WillOnce(Return(kLicenseStartTime + min_duration - 1)) .WillOnce(Return(kLicenseStartTime + min_duration)) - .WillOnce(Return(kLicenseStartTime + min_duration + 1)) .WillOnce(Return(kLicenseStartTime + min_duration + 5)); policy_engine_->SetLicense(license_); @@ -1076,7 +1140,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_PlaybackDurationExpired) { std::istringstream ss; ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); ss >> remaining_time; - EXPECT_EQ(kHighDuration - 10004 - min_duration, remaining_time); + EXPECT_EQ(kHighDuration - 10005 - min_duration, remaining_time); ss.clear(); ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); ss >> remaining_time; @@ -1092,9 +1156,9 @@ TEST_F(PolicyEngineTest, QuerySuccess_LicenseDurationExpired) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) .WillOnce(Return(kLicenseStartTime + 5)) + .WillOnce(Return(kLicenseStartTime + min_duration - 1)) .WillOnce(Return(kLicenseStartTime + min_duration)) - .WillOnce(Return(kLicenseStartTime + 1 + min_duration)) - .WillOnce(Return(kLicenseStartTime + 5 + min_duration)); + .WillOnce(Return(kLicenseStartTime + min_duration + 5)); policy_engine_->SetLicense(license_); @@ -1140,11 +1204,11 @@ TEST_F(PolicyEngineTest, QuerySuccess_RentalDuration0) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) .WillOnce(Return(kLicenseStartTime + 5)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay - 1)) .WillOnce(Return(kLicenseStartTime + license_renewal_delay)) - .WillOnce(Return(kLicenseStartTime + 1 + license_renewal_delay)) + .WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration - 1)) .WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration)) - .WillOnce(Return(kLicenseStartTime + 1 + kStreamingLicenseDuration)) - .WillOnce(Return(kLicenseStartTime + 5 + kStreamingLicenseDuration)); + .WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration + 5)); policy_engine_->SetLicense(license_); @@ -1275,9 +1339,9 @@ TEST_F(PolicyEngineTest, QuerySuccess_LicenseDuration0) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) .WillOnce(Return(kLicenseStartTime + 5)) + .WillOnce(Return(kLicenseStartTime + min_duration - 1)) .WillOnce(Return(kLicenseStartTime + min_duration)) - .WillOnce(Return(kLicenseStartTime + 1 + min_duration)) - .WillOnce(Return(kLicenseStartTime + 5 + min_duration)); + .WillOnce(Return(kLicenseStartTime + min_duration + 5)); policy_engine_->SetLicense(license_); @@ -1325,7 +1389,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_Durations0) { .WillOnce(Return(kLicenseStartTime + 1)) .WillOnce(Return(kLicenseStartTime + 5)) .WillOnce(Return(kLicenseStartTime + kHighDuration)) - .WillOnce(Return(kLicenseStartTime + kHighDuration + 10)) + .WillOnce(Return(kLicenseStartTime + kHighDuration + 9)) .WillOnce(Return(kLicenseStartTime + kHighDuration + 15)); policy_engine_->SetLicense(license_); @@ -1361,4 +1425,213 @@ TEST_F(PolicyEngineTest, QuerySuccess_Durations0) { EXPECT_EQ(LLONG_MAX, remaining_time); EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]); } + +TEST_F(PolicyEngineTest, QuerySuccess_LicenseWithFutureStartTime) { + EXPECT_CALL(*mock_clock_, GetCurrentTime()) + .WillOnce(Return(kLicenseStartTime - 100)) + .WillOnce(Return(kLicenseStartTime - 50)) + .WillOnce(Return(kLicenseStartTime - 10)) + .WillOnce(Return(kLicenseStartTime)) + .WillOnce(Return(kLicenseStartTime + 10)) + .WillOnce(Return(kLicenseStartTime + 25)); + + policy_engine_->SetLicense(license_); + + bool event_occurred; + CdmEventType event; + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + EXPECT_FALSE(policy_engine_->can_decrypt()); + + CdmQueryMap query_info; + EXPECT_EQ(NO_ERROR, policy_engine_->Query(&query_info)); + EXPECT_EQ(QUERY_VALUE_STREAMING, query_info[QUERY_KEY_LICENSE_TYPE]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_PLAY_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_FALSE, query_info[QUERY_KEY_PERSIST_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_RENEW_ALLOWED]); + + int64_t remaining_time; + std::istringstream ss; + ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kStreamingLicenseDuration, remaining_time); + ss.clear(); + ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kPlaybackDuration, remaining_time); + EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]); + + EXPECT_FALSE(policy_engine_->can_decrypt()); + + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + EXPECT_TRUE(policy_engine_->can_decrypt()); + policy_engine_->BeginDecryption(); + + EXPECT_EQ(NO_ERROR, policy_engine_->Query(&query_info)); + EXPECT_EQ(QUERY_VALUE_STREAMING, query_info[QUERY_KEY_LICENSE_TYPE]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_PLAY_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_FALSE, query_info[QUERY_KEY_PERSIST_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_RENEW_ALLOWED]); + + ss.clear(); + ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kStreamingLicenseDuration - 25, remaining_time); + ss.clear(); + ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kPlaybackDuration - 15, remaining_time); + EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]); +} + +TEST_F(PolicyEngineTest, QuerySuccess_Renew) { + int64_t license_renewal_delay = + GetLicenseRenewalDelay(kStreamingLicenseDuration); + + EXPECT_CALL(*mock_clock_, GetCurrentTime()) + .WillOnce(Return(kLicenseStartTime + 1)) + .WillOnce(Return(kLicenseStartTime + 5)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay - 25)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + 10)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + 20)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + + kLicenseRenewalRetryInterval + 10)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + + kLicenseRenewalRetryInterval + 15)); + + policy_engine_->SetLicense(license_); + + policy_engine_->BeginDecryption(); + EXPECT_TRUE(policy_engine_->can_decrypt()); + + bool event_occurred; + CdmEventType event; + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_TRUE(event_occurred); + EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event); + EXPECT_TRUE(policy_engine_->can_decrypt()); + + license_.set_license_start_time(kLicenseStartTime + license_renewal_delay + + 15); + LicenseIdentification* id = license_.mutable_id(); + id->set_version(2); + policy_engine_->UpdateLicense(license_); + + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + EXPECT_TRUE(policy_engine_->can_decrypt()); + + CdmQueryMap query_info; + EXPECT_EQ(NO_ERROR, policy_engine_->Query(&query_info)); + EXPECT_EQ(QUERY_VALUE_STREAMING, query_info[QUERY_KEY_LICENSE_TYPE]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_PLAY_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_FALSE, query_info[QUERY_KEY_PERSIST_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_RENEW_ALLOWED]); + + int64_t remaining_time; + std::istringstream ss; + ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kStreamingLicenseDuration - kLicenseRenewalRetryInterval, + remaining_time); + ss.clear(); + ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kPlaybackDuration + 5 - license_renewal_delay - + kLicenseRenewalRetryInterval - 15, + remaining_time); + EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]); +} + +TEST_F(PolicyEngineTest, QuerySuccess_RenewWithFutureStartTime) { + int64_t license_renewal_delay = + GetLicenseRenewalDelay(kStreamingLicenseDuration); + + EXPECT_CALL(*mock_clock_, GetCurrentTime()) + .WillOnce(Return(kLicenseStartTime + 1)) + .WillOnce(Return(kLicenseStartTime + 5)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay - 25)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + 10)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + 20)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + + kLicenseRenewalRetryInterval + 10)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + + kLicenseRenewalRetryInterval + 20)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + + kLicenseRenewalRetryInterval + 30)) + .WillOnce(Return(kLicenseStartTime + license_renewal_delay + + kLicenseRenewalRetryInterval + 40)); + + policy_engine_->SetLicense(license_); + + policy_engine_->BeginDecryption(); + EXPECT_TRUE(policy_engine_->can_decrypt()); + + bool event_occurred; + CdmEventType event; + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_TRUE(event_occurred); + EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event); + EXPECT_TRUE(policy_engine_->can_decrypt()); + + license_.set_license_start_time(kLicenseStartTime + license_renewal_delay + + kLicenseRenewalRetryInterval + 20); + LicenseIdentification* id = license_.mutable_id(); + id->set_version(2); + policy_engine_->UpdateLicense(license_); + + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + EXPECT_FALSE(policy_engine_->can_decrypt()); + + CdmQueryMap query_info; + EXPECT_EQ(NO_ERROR, policy_engine_->Query(&query_info)); + EXPECT_EQ(QUERY_VALUE_STREAMING, query_info[QUERY_KEY_LICENSE_TYPE]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_PLAY_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_FALSE, query_info[QUERY_KEY_PERSIST_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_RENEW_ALLOWED]); + + int64_t remaining_time; + std::istringstream ss; + ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kStreamingLicenseDuration, remaining_time); + ss.clear(); + ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kPlaybackDuration + 5 - license_renewal_delay - + kLicenseRenewalRetryInterval - 20, + remaining_time); + EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]); + + policy_engine_->OnTimerEvent(&event_occurred, &event); + EXPECT_FALSE(event_occurred); + EXPECT_TRUE(policy_engine_->can_decrypt()); + + EXPECT_EQ(NO_ERROR, policy_engine_->Query(&query_info)); + EXPECT_EQ(QUERY_VALUE_STREAMING, query_info[QUERY_KEY_LICENSE_TYPE]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_PLAY_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_FALSE, query_info[QUERY_KEY_PERSIST_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_RENEW_ALLOWED]); + + ss.clear(); + ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kStreamingLicenseDuration - 20, remaining_time); + ss.clear(); + ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kPlaybackDuration + 5 - license_renewal_delay - + kLicenseRenewalRetryInterval - 40, + remaining_time); + EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]); +} + } // wvcdm