From 1ea92c34c878872fcac72eac2cc68f586f6afb75 Mon Sep 17 00:00:00 2001 From: Alex Dale Date: Wed, 30 Nov 2022 00:29:14 +0000 Subject: [PATCH] Revert "Core CDM: Remove usage info as a run-time type." This reverts commit 5dd2b07286bf86240e0261b37aeff99baef81521. Reason for revert: Feature rejected by Android Bug: 242289743 Change-Id: I8dc95139d113ad1d44acd2e8dd6cbda604b6c073 --- .../cdm/core/include/device_files.h | 23 +- .../cdm/core/include/usage_table_header.h | 82 +- .../cdm/core/include/wv_cdm_types.h | 86 +- libwvdrmengine/cdm/core/src/cdm_session.cpp | 6 +- libwvdrmengine/cdm/core/src/device_files.cpp | 30 +- .../cdm/core/src/usage_table_header.cpp | 551 ++++----- libwvdrmengine/cdm/core/src/wv_cdm_types.cpp | 13 + .../cdm/core/test/device_files_unittest.cpp | 52 +- .../core/test/usage_table_header_unittest.cpp | 1085 ++++++++++------- .../test/metrics_collections_unittest.cpp | 6 +- 10 files changed, 1066 insertions(+), 868 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/device_files.h b/libwvdrmengine/cdm/core/include/device_files.h index 8d5bc7ac..a1566b93 100644 --- a/libwvdrmengine/cdm/core/include/device_files.h +++ b/libwvdrmengine/cdm/core/include/device_files.h @@ -103,6 +103,17 @@ class DeviceFiles { CryptoWrappedKey wrapped_private_key; }; + struct CdmUsageData { + std::string provider_session_token; + CdmKeyMessage license_request; + CdmKeyResponse license; + std::string key_set_id; + CdmUsageEntry usage_entry; + uint32_t usage_entry_number; + std::string drm_certificate; + CryptoWrappedKey wrapped_private_key; + }; + DeviceFiles(wvutil::FileSystem*); virtual ~DeviceFiles(); @@ -168,7 +179,7 @@ class DeviceFiles { virtual bool StoreUsageTableInfo( const CdmUsageTableHeader& usage_table_header, - const std::vector& usage_entry_info_list); + const std::vector& usage_entry_info); // When retrieving usage table information from the file system; any // table that has yet to be updated for the LRU attributes will be @@ -179,7 +190,7 @@ class DeviceFiles { // is set to true if any are detected. virtual bool RetrieveUsageTableInfo( CdmUsageTableHeader* usage_table_header, - std::vector* usage_entry_info_list, bool* lru_upgrade, + std::vector* usage_entry_info, bool* lru_upgrade, bool* has_usage_info_entries); virtual bool DeleteUsageTableInfo(); @@ -251,6 +262,10 @@ class DeviceFiles { FRIEND_TEST(DeviceFilesTest, OkpInfo_FileDoesNotExist); FRIEND_TEST(DeviceFilesTest, OkpInfo_DeleteFile); FRIEND_TEST(DeviceFilesTest, OkpInfo_StoreAndRetrieve); + FRIEND_TEST(DeviceFilesUsageInfoTest, Delete); + FRIEND_TEST(DeviceFilesUsageInfoTest, DeleteAll); + FRIEND_TEST(DeviceFilesUsageInfoTest, Read); + FRIEND_TEST(DeviceFilesUsageInfoTest, Store); FRIEND_TEST(DeviceFilesUsageTableTest, Read); FRIEND_TEST(DeviceFilesUsageTableTest, Store); FRIEND_TEST(DeviceFilesUsageTableTest, ReadWithoutLruData); @@ -260,7 +275,11 @@ class DeviceFiles { FRIEND_TEST(StoreCertificateTest, DefaultAndLegacy); FRIEND_TEST(WvCdmRequestLicenseTest, UnprovisionTest); FRIEND_TEST(WvCdmRequestLicenseTest, ForceL3Test); + FRIEND_TEST(WvCdmRequestLicenseTest, UsageInfoRetryTest); FRIEND_TEST(WvCdmRequestLicenseTest, UsageReleaseAllTest); + FRIEND_TEST(WvCdmUsageInfoTest, UsageInfo); + FRIEND_TEST(WvCdmUsageTest, WithClientId); + FRIEND_TEST(WvCdmExtendedDurationTest, UsageOverflowTest); #endif static std::set reserved_license_ids_; diff --git a/libwvdrmengine/cdm/core/include/usage_table_header.h b/libwvdrmengine/cdm/core/include/usage_table_header.h index a479dffa..4fd992f5 100644 --- a/libwvdrmengine/cdm/core/include/usage_table_header.h +++ b/libwvdrmengine/cdm/core/include/usage_table_header.h @@ -46,7 +46,7 @@ namespace wvcdm { // // Upgrades from a fixed size usage table (supported by previous // versions of the OEMCrypto API v9-12) are handled by this class. -// |usage_entry| and |entry_number|s need to be saved in the license +// |usage_entry| and |usage_entry_number|s need to be saved in the license // and usage info records by the caller. class UsageTableHeader { public: @@ -65,30 +65,30 @@ class UsageTableHeader { // Adds a new entry to the OEMCrypto usage table header, and associates // the entry with the provided |crypto_session|. The index of the new - // usage entry will be returned by |entry_number|. + // usage entry will be returned by |usage_entry_number|. // - // Threading: Method takes exclusive use of |table_lock_|. + // Threading: Method takes exclusive use of |usage_table_header_lock_|. virtual CdmResponseType AddEntry(CryptoSession* crypto_session, const CdmKeySetId& key_set_id, const CdmKeyResponse& license_message, - uint32_t* entry_number); - // Threading: Method takes exclusive use of |table_lock_|. + uint32_t* usage_entry_number); + // Threading: Method takes exclusive use of |usage_table_header_lock_|. virtual CdmResponseType LoadEntry(CryptoSession* crypto_session, const CdmUsageEntry& usage_entry, - uint32_t entry_number); - // Threading: Method takes exclusive use of |table_lock_|. - virtual CdmResponseType UpdateEntry(uint32_t entry_number, + uint32_t usage_entry_number); + // Threading: Method takes exclusive use of |usage_table_header_lock_|. + virtual CdmResponseType UpdateEntry(uint32_t usage_entry_number, CryptoSession* crypto_session, CdmUsageEntry* usage_entry); - // The licenses or usage info records specified by |entry_number| + // The licenses or usage info records specified by |usage_entry_number| // should not be in use by any open CryptoSession objects when calls // to InvalidateEntry and MoveEntry are made. // If |defrag_table| is true, the table will be defragmented after // the entry has been invalidated. // - // Threading: Method takes exclusive use of |table_lock_|. - virtual CdmResponseType InvalidateEntry(uint32_t entry_number, + // Threading: Method takes exclusive use of |usage_table_header_lock_|. + virtual CdmResponseType InvalidateEntry(uint32_t usage_entry_number, bool defrag_table, DeviceFiles* device_files, metrics::CryptoMetrics* metrics); @@ -101,13 +101,13 @@ class UsageTableHeader { // for the objects that InvalidateEntry depends on. // // Threading: Method requires care of caller for exclusive access. - void InvalidateEntryForTest(uint32_t entry_number); + void InvalidateEntryForTest(uint32_t usage_entry_number); // == Table information methods == // Threading: None of the following are thread safe. Intended for // testing or internal use. - size_t size() { return entry_info_list_.size(); } + size_t size() { return usage_entry_info_.size(); } size_t potential_table_capacity() const { return potential_table_capacity_; } @@ -116,11 +116,11 @@ class UsageTableHeader { } // Returns the number of entries currently tracked by the CDM that - // are populated (non-empty). - size_t OccupiedEntryCount() const; + // are related to offline licenses. + size_t OfflineEntryCount() const; - const std::vector& entry_info_list() const { - return entry_info_list_; + const std::vector& usage_entry_info() const { + return usage_entry_info_; } // Set the reference clock used for the method GetCurrentTime(). @@ -132,10 +132,10 @@ class UsageTableHeader { } static bool DetermineLicenseToRemoveForTesting( - const std::vector& entry_info_list, + const std::vector& usage_entry_info_list, int64_t current_time, size_t unexpired_threshold, uint32_t* entry_to_remove) { - return DetermineLicenseToRemove(entry_info_list, current_time, + return DetermineLicenseToRemove(usage_entry_info_list, current_time, unexpired_threshold, entry_to_remove); } @@ -146,13 +146,13 @@ class UsageTableHeader { // Creates a new, empty usage table. Any existing usage table files // will be deleted. - // Threading: Method takes exclusive use of |table_lock_| + // Threading: Method takes exclusive use of |usage_table_header_lock_| // when required. bool CreateNewTable(CryptoSession* const crypto_session); // Attempts to restore the usage table from persistent storage, and // loads the usage table header into OEMCrypto. // Note: No other OEMCrypto session should be opened before calling. - // Threading: Method takes exclusive use of |table_lock_| + // Threading: Method takes exclusive use of |usage_table_header_lock_| // when required. bool RestoreTable(CryptoSession* const crypto_session); @@ -164,52 +164,52 @@ class UsageTableHeader { // one more entry if the table is at or near the reported capacity. // If this check fails, a new usage table SHOULD be created. // Threading: Method requires caller to take exclusive use of - // |table_lock_|. + // |usage_table_header_lock_|. bool CapacityCheck(CryptoSession* const crypto_session); // Attempts to determine the capacity of the OEMCrypto usage table. // Sets the result to |potential_table_capacity_|. // Threading: Method requires caller to take exclusive use of - // |table_lock_|. + // |usage_table_header_lock_|. bool DetermineTableCapacity(CryptoSession* crypto_session); // == Table operation methods == // Threading: All of the following methods require caller to take - // exclusive use of |table_lock_|. + // exclusive use of |usage_table_header_lock_|. // Creates a new entry for the provided crypto session. If the // entry is created successfully in OEMCrypto, then a new entry // info is added to the table's vector of entry info. CdmResponseType CreateEntry(CryptoSession* const crypto_session, - uint32_t* entry_number); + uint32_t* usage_entry_number); // Attempts to relocate a newly created usage entry associated with // the provided |crypto_session| to the lowest unoccupied position in // the table. - // |entry_number| is treated as both an input and output. + // |usage_entry_number| is treated as both an input and output. // Returns NO_ERROR so long as no internal operation fails, // regardless of whether the entry was moved or not. CdmResponseType RelocateNewEntry(CryptoSession* const crypto_session, - uint32_t* entry_number); + uint32_t* usage_entry_number); - // Checks if the specified |entry_number| is known to be + // Checks if the specified |usage_entry_number| is known to be // unoccupied (released). - bool IsEntryUnoccupied(const uint32_t entry_number) const; + bool IsEntryUnoccupied(const uint32_t usage_entry_number) const; // Populates the entry's meta-data with the required information based // entry meta-data with the required information based on the type // on the license content. - void SetOfflineEntryInfo(const uint32_t entry_number, + void SetOfflineEntryInfo(const uint32_t usage_entry_number, const std::string& key_set_id, const CdmKeyResponse& license_message); // Shrinks the table, removing all trailing unoccupied entries. - // |entry_info_| will be resized appropriately. + // |usage_entry_info_| will be resized appropriately. // Caller must store the table after a successful call. CdmResponseType RefitTable(CryptoSession* const crypto_session); virtual CdmResponseType InvalidateEntryInternal( - uint32_t entry_number, bool defrag_table, DeviceFiles* device_files, + uint32_t usage_entry_number, bool defrag_table, DeviceFiles* device_files, metrics::CryptoMetrics* metrics); CdmResponseType MoveEntry(uint32_t from /* usage entry number */, @@ -218,9 +218,11 @@ class UsageTableHeader { DeviceFiles* device_files, metrics::CryptoMetrics* metrics); - CdmResponseType GetEntry(uint32_t entry_number, DeviceFiles* device_files, + CdmResponseType GetEntry(uint32_t usage_entry_number, + DeviceFiles* device_files, CdmUsageEntry* usage_entry); - CdmResponseType StoreEntry(uint32_t entry_number, DeviceFiles* device_files, + CdmResponseType StoreEntry(uint32_t usage_entry_number, + DeviceFiles* device_files, const CdmUsageEntry& usage_entry); // Stores the usage table and it's info. This will increment @@ -271,7 +273,7 @@ class UsageTableHeader { // types. // // Parameters: - // [in] entry_info_list: The complete list of known usage + // [in] usage_entry_info_list: The complete list of known usage // entries. // [in] current_time: The current time to compare expiration times // against. @@ -286,20 +288,20 @@ class UsageTableHeader { // |true| if an entry has been determined to be removed. // Otherwise returns |false|. static bool DetermineLicenseToRemove( - const std::vector& entry_info_list, + const std::vector& usage_entry_info_list, int64_t current_time, size_t unexpired_threshold, uint32_t* entry_to_remove); // This handle and file system is only to be used when accessing - // |table_header|. Usage entries should use the file system provided + // usage_table_header. Usage entries should use the file system provided // by CdmSession. std::unique_ptr device_files_; std::unique_ptr file_system_; CdmSecurityLevel security_level_ = kSecurityLevelUninitialized; RequestedSecurityLevel requested_security_level_ = kLevelDefault; - CdmUsageTableHeader table_header_; - std::vector entry_info_list_; + CdmUsageTableHeader usage_table_header_; + std::vector usage_entry_info_; // Table is sync with persistent storage and can be used by the CDM // to interact with OEMCrypto. @@ -307,7 +309,7 @@ class UsageTableHeader { // Synchonizes access to the Usage Table Header and bookkeeping // data-structures - mutable std::mutex table_lock_; + mutable std::mutex usage_table_header_lock_; metrics::CryptoMetrics alternate_crypto_metrics_; diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index 69a5ae21..d1111d79 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -537,71 +537,44 @@ enum CdmUsageSupportType : int32_t { kUnknownUsageSupport, }; -class CdmUsageEntryInfo { - public: - CdmUsageEntryInfo() {} - CdmUsageEntryInfo(const std::string& key_set_id, int64_t last_use_time, - int64_t license_expiry_time) - : key_set_id_(key_set_id), - last_use_time_(last_use_time), - license_expiry_time_(license_expiry_time) { - if (key_set_id.empty()) Clear(); - } - - CdmUsageEntryInfo(const CdmUsageEntryInfo&) = default; - CdmUsageEntryInfo& operator=(const CdmUsageEntryInfo&) = default; - - CdmUsageEntryInfo(CdmUsageEntryInfo&&) = default; - CdmUsageEntryInfo& operator=(CdmUsageEntryInfo&&) = default; - - bool HasKeySetId() const { return !key_set_id_.empty(); } - bool IsEmpty() const { return key_set_id_.empty(); } - - const std::string& key_set_id() const { return key_set_id_; } - void SetKeySetId(const std::string& key_set_id) { - if (key_set_id.empty()) { - Clear(); - } else { - key_set_id_ = key_set_id; - } - } - - int64_t last_use_time() const { return last_use_time_; } - void SetLastUseTime(int64_t last_use_time) { last_use_time_ = last_use_time; } - // Used for testing. - void IncLastUseTime() { last_use_time_++; } - void DecLastUseTime() { last_use_time_--; } - - int64_t license_expiry_time() const { return license_expiry_time_; } - void SetLicenseExpiryTime(int64_t license_expiry_time) { - license_expiry_time_ = license_expiry_time; - } - - void Clear() { - key_set_id_.clear(); - last_use_time_ = license_expiry_time_ = 0; - } +enum CdmUsageEntryStorageType : int32_t { + kStorageLicense, + kStorageUsageInfo, + kStorageTypeUnknown, +}; +struct CdmUsageEntryInfo { + CdmUsageEntryStorageType storage_type; + CdmKeySetId key_set_id; + std::string usage_info_file_name; + int64_t last_use_time; + int64_t offline_license_expiry_time; // Only for offline licenses. bool operator==(const CdmUsageEntryInfo& other) const { if (this == &other) { return true; } - if (IsEmpty() && other.IsEmpty()) { - // All other fields are ignored if there is no key set ID set. - return true; - } - if (key_set_id_ != other.key_set_id_) { + if (storage_type != other.storage_type || key_set_id != other.key_set_id || + last_use_time != other.last_use_time) { return false; } - return last_use_time_ == other.last_use_time_ && - license_expiry_time_ == other.license_expiry_time_; + // Certain fields only have meaning based on the storage type. + if (storage_type == kStorageUsageInfo) { + return usage_info_file_name == other.usage_info_file_name; + } + if (storage_type == kStorageLicense) { + return offline_license_expiry_time == other.offline_license_expiry_time; + } + // else storage_type == kStorageTypeUnknown + return true; } - private: - // If |key_set_id_| is empty, the other fields are ignored. - CdmKeySetId key_set_id_ = ""; - int64_t last_use_time_ = 0; - int64_t license_expiry_time_ = 0; + void Clear() { + storage_type = kStorageTypeUnknown; + key_set_id.clear(); + usage_info_file_name.clear(); + last_use_time = 0; + offline_license_expiry_time = 0; + } }; enum CdmKeySecurityLevel : int32_t { @@ -873,6 +846,7 @@ const char* CdmOfflineLicenseStateToString( CdmOfflineLicenseState license_state); const std::string CdmResponseTypeToString(int cdm_response_type); const char* CdmSecurityLevelToString(CdmSecurityLevel security_level); +const char* CdmUsageEntryStorageTypeToString(CdmUsageEntryStorageType type); const char* RequestedSecurityLevelToString( RequestedSecurityLevel security_level); const char* CdmWatermarkingSupportToString(CdmWatermarkingSupport support); diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index 823f687f..9c1295a7 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -1049,9 +1049,9 @@ bool CdmSession::VerifyOfflineUsageEntry() { return false; } const CdmUsageEntryInfo& usage_entry_info = - usage_table_header_->entry_info_list().at(usage_entry_number_); - if (usage_entry_info.IsEmpty() || - usage_entry_info.key_set_id() != key_set_id_) { + usage_table_header_->usage_entry_info().at(usage_entry_number_); + if (usage_entry_info.storage_type != kStorageLicense || + usage_entry_info.key_set_id != key_set_id_) { LOGD("License usage entry does not match"); return false; } diff --git a/libwvdrmengine/cdm/core/src/device_files.cpp b/libwvdrmengine/cdm/core/src/device_files.cpp index 02dacd02..22c14086 100644 --- a/libwvdrmengine/cdm/core/src/device_files.cpp +++ b/libwvdrmengine/cdm/core/src/device_files.cpp @@ -1014,7 +1014,7 @@ bool DeviceFiles::DeleteHlsAttributes(const std::string& key_set_id) { bool DeviceFiles::StoreUsageTableInfo( const CdmUsageTableHeader& usage_table_header, - const std::vector& usage_entry_info_list) { + const std::vector& usage_entry_info) { RETURN_FALSE_IF_UNINITIALIZED(); using video_widevine_client::sdk::UsageTableInfo; using UsageEntryInfo = UsageTableInfo::UsageEntryInfo; @@ -1028,14 +1028,14 @@ bool DeviceFiles::StoreUsageTableInfo( UsageTableInfo* stored_table_info = file.mutable_usage_table_info(); stored_table_info->set_usage_table_header(usage_table_header); - for (const auto& entry_info : usage_entry_info_list) { + for (const auto& entry_info : usage_entry_info) { UsageEntryInfo* stored_info = stored_table_info->add_usage_entry_info(); - if (entry_info.HasKeySetId()) { + if (entry_info.storage_type == kStorageLicense) { stored_info->set_storage(UsageEntryInfo::LICENSE); - stored_info->set_key_set_id(entry_info.key_set_id()); - stored_info->set_last_use_time(entry_info.last_use_time()); + stored_info->set_key_set_id(entry_info.key_set_id); + stored_info->set_last_use_time(entry_info.last_use_time); stored_info->set_offline_license_expiry_time( - entry_info.license_expiry_time()); + entry_info.offline_license_expiry_time); } else { stored_info->set_storage(UsageEntryInfo::UNKNOWN); } @@ -1051,11 +1051,11 @@ bool DeviceFiles::StoreUsageTableInfo( bool DeviceFiles::RetrieveUsageTableInfo( CdmUsageTableHeader* usage_table_header, - std::vector* usage_entry_info_list, bool* lru_upgrade, + std::vector* usage_entry_info, bool* lru_upgrade, bool* has_usage_info_entries) { RETURN_FALSE_IF_UNINITIALIZED(); RETURN_FALSE_IF_NULL(usage_table_header); - RETURN_FALSE_IF_NULL(usage_entry_info_list); + RETURN_FALSE_IF_NULL(usage_entry_info); RETURN_FALSE_IF_NULL(lru_upgrade); RETURN_FALSE_IF_NULL(has_usage_info_entries); using video_widevine_client::sdk::UsageTableInfo; @@ -1091,22 +1091,22 @@ bool DeviceFiles::RetrieveUsageTableInfo( *lru_upgrade = !stored_table_info.use_lru(); *has_usage_info_entries = false; *usage_table_header = stored_table_info.usage_table_header(); - usage_entry_info_list->clear(); - usage_entry_info_list->reserve(stored_table_info.usage_entry_info_size()); + usage_entry_info->reserve(stored_table_info.usage_entry_info_size()); for (const auto& stored_entry_info : stored_table_info.usage_entry_info()) { CdmUsageEntryInfo entry_info; entry_info.Clear(); if (stored_entry_info.storage() == UsageEntryInfo::LICENSE) { - entry_info.SetKeySetId(stored_entry_info.key_set_id()); - entry_info.SetLastUseTime(stored_entry_info.last_use_time()); - entry_info.SetLicenseExpiryTime( - stored_entry_info.offline_license_expiry_time()); + entry_info.storage_type = kStorageLicense; + entry_info.key_set_id = stored_entry_info.key_set_id(); + entry_info.last_use_time = stored_entry_info.last_use_time(); + entry_info.offline_license_expiry_time = + stored_entry_info.offline_license_expiry_time(); } else if (stored_entry_info.storage() == UsageEntryInfo::USAGE_INFO) { // USAGE_INFO are deprecated, do not retrieve this entries. *has_usage_info_entries = true; } - usage_entry_info_list->emplace_back(std::move(entry_info)); + usage_entry_info->emplace_back(std::move(entry_info)); } return true; } diff --git a/libwvdrmengine/cdm/core/src/usage_table_header.cpp b/libwvdrmengine/cdm/core/src/usage_table_header.cpp index 4052210e..ba85f65e 100644 --- a/libwvdrmengine/cdm/core/src/usage_table_header.cpp +++ b/libwvdrmengine/cdm/core/src/usage_table_header.cpp @@ -71,7 +71,7 @@ bool ParseLicenseFromLicenseMessage(const CdmKeyResponse& license_message, bool RetrieveOfflineLicense(DeviceFiles* device_files, const std::string& key_set_id, CdmKeyResponse* license_message, - uint32_t* entry_number) { + uint32_t* usage_entry_number) { if (device_files == nullptr) { LOGE("DeviceFiles handle is null"); return false; @@ -80,8 +80,8 @@ bool RetrieveOfflineLicense(DeviceFiles* device_files, LOGE("Output parameter |license_message| is null"); return false; } - if (entry_number == nullptr) { - LOGE("Output parameter |entry_number| is null"); + if (usage_entry_number == nullptr) { + LOGE("Output parameter |usage_entry_number| is null"); return false; } DeviceFiles::CdmLicenseData license_data; @@ -92,30 +92,13 @@ bool RetrieveOfflineLicense(DeviceFiles* device_files, return false; } *license_message = std::move(license_data.license); - *entry_number = license_data.usage_entry_number; + *usage_entry_number = license_data.usage_entry_number; return true; } -int64_t CalculateOfflineLicenseExpiryTime(const CdmKeyResponse& license_message, - int64_t last_use_time) { - // Need to determine the expire time for offline licenses. - video_widevine::License license; - if (license_message.empty() || - !ParseLicenseFromLicenseMessage(license_message, &license)) { - // If the license duration cannot be determined for any reason, it - // is assumed to last at most 33 days. - return last_use_time + kDefaultExpireDuration; - } - // TODO(b/256037954): Fix how entry expiry time for unlimited licenses - // are calculated. They should last at least 33 days. - const video_widevine::License::Policy& policy = license.policy(); - return license.license_start_time() + policy.rental_duration_seconds() + - policy.playback_duration_seconds(); -} - -bool EntryIsOccupied(const CdmUsageEntryInfo& info) { +bool EntryIsOfflineLicense(const CdmUsageEntryInfo& info) { // Used for stl filters. - return info.HasKeySetId(); + return info.storage_type == kStorageLicense; } bool IsValidCdmSecurityLevelForUsageTable(CdmSecurityLevel security_level) { @@ -127,18 +110,6 @@ RequestedSecurityLevel CdmSecurityLevelToRequestedLevel( CdmSecurityLevel security_level) { return security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault; } - -const char* GetEntryStateString( - uint32_t entry_number, - const std::vector& entry_info_list) { - if (static_cast(entry_number) >= entry_info_list.size()) { - return ""; - } - if (entry_info_list[entry_number].HasKeySetId()) { - return ""; - } - return ""; -} } // namespace UsageTableHeader::UsageTableHeader() : clock_ref_(&clock_) { @@ -184,17 +155,17 @@ bool UsageTableHeader::Init(CdmSecurityLevel security_level, bool UsageTableHeader::RestoreTable(CryptoSession* const crypto_session) { bool run_lru_upgrade = false; bool has_usage_info_entries = false; - if (!device_files_->RetrieveUsageTableInfo(&table_header_, &entry_info_list_, - &run_lru_upgrade, - &has_usage_info_entries)) { + if (!device_files_->RetrieveUsageTableInfo( + &usage_table_header_, &usage_entry_info_, &run_lru_upgrade, + &has_usage_info_entries)) { LOGW("Could not retrieve usage table"); return false; } LOGI("Found usage table to restore: entry_count = %zu", - entry_info_list_.size()); + usage_entry_info_.size()); const CdmResponseType status = crypto_session->LoadUsageTableHeader( - requested_security_level_, table_header_); + requested_security_level_, usage_table_header_); if (status != NO_ERROR) { LOGE("Failed to load usage table header: sts = %d", static_cast(status)); @@ -232,11 +203,11 @@ bool UsageTableHeader::CreateNewTable(CryptoSession* const crypto_session) { device_files_->DeleteAllLicenses(); device_files_->DeleteAllUsageInfo(); device_files_->DeleteUsageTableInfo(); - entry_info_list_.clear(); - table_header_.clear(); + usage_entry_info_.clear(); + usage_table_header_.clear(); const CdmResponseType status = crypto_session->CreateUsageTableHeader( - requested_security_level_, &table_header_); + requested_security_level_, &usage_table_header_); if (status != NO_ERROR) { LOGE("Failed to create new usage table header"); return false; @@ -251,34 +222,34 @@ bool UsageTableHeader::CreateNewTable(CryptoSession* const crypto_session) { CdmResponseType UsageTableHeader::AddEntry( CryptoSession* crypto_session, const CdmKeySetId& key_set_id, - const CdmKeyResponse& license_message, uint32_t* entry_number) { + const CdmKeyResponse& license_message, uint32_t* usage_entry_number) { LOGD("key_set_id = %s, current_size = %zu", IdToString(key_set_id), - entry_info_list_.size()); + usage_entry_info_.size()); metrics::CryptoMetrics* metrics = crypto_session->GetCryptoMetrics(); if (metrics == nullptr) metrics = &alternate_crypto_metrics_; - TableLock auto_lock(table_lock_); + TableLock auto_lock(usage_table_header_lock_); - CdmResponseType status = CreateEntry(crypto_session, entry_number); + CdmResponseType status = CreateEntry(crypto_session, usage_entry_number); if (status == INSUFFICIENT_CRYPTO_RESOURCES) { LOGW("Usage table may be full, releasing oldest entry: size = %zu", - entry_info_list_.size()); + usage_entry_info_.size()); status = ReleaseOldestEntry(metrics); if (status == NO_ERROR) { - status = CreateEntry(crypto_session, entry_number); + status = CreateEntry(crypto_session, usage_entry_number); } } if (status != NO_ERROR) return status; - status = RelocateNewEntry(crypto_session, entry_number); + status = RelocateNewEntry(crypto_session, usage_entry_number); if (status != NO_ERROR) return status; - SetOfflineEntryInfo(*entry_number, key_set_id, license_message); + SetOfflineEntryInfo(*usage_entry_number, key_set_id, license_message); status = RefitTable(crypto_session); if (status != NO_ERROR) { // Clear new entry on failure. - entry_info_list_[*entry_number].Clear(); + usage_entry_info_[*usage_entry_number].Clear(); return status; } @@ -286,10 +257,11 @@ CdmResponseType UsageTableHeader::AddEntry( // entry. If the entry is used by the CDM, the CDM session will make // subsequent calls to update the usage entry and store that entry. std::string usage_entry; - status = crypto_session->UpdateUsageEntry(&table_header_, &usage_entry); + status = crypto_session->UpdateUsageEntry(&usage_table_header_, &usage_entry); if (status != NO_ERROR) { - LOGE("Failed to update new usage entry: entry_number = %u", *entry_number); - entry_info_list_[*entry_number].Clear(); + LOGE("Failed to update new usage entry: usage_entry_number = %u", + *usage_entry_number); + usage_entry_info_[*usage_entry_number].Clear(); return status; } StoreTable(); @@ -298,16 +270,16 @@ CdmResponseType UsageTableHeader::AddEntry( CdmResponseType UsageTableHeader::LoadEntry(CryptoSession* crypto_session, const CdmUsageEntry& usage_entry, - uint32_t entry_number) { + uint32_t usage_entry_number) { { - LOGD("entry_number = %u", entry_number); - std::unique_lock auto_lock(table_lock_); + LOGD("usage_entry_number = %u", usage_entry_number); + std::unique_lock auto_lock(usage_table_header_lock_); - if (entry_number >= entry_info_list_.size()) { + if (usage_entry_number >= usage_entry_info_.size()) { LOGE( "Requested usage entry number is larger than table size: " - "entry_number = %u, table_size = %zu", - entry_number, entry_info_list_.size()); + "usage_entry_number = %u, table_size = %zu", + usage_entry_number, usage_entry_info_.size()); return USAGE_INVALID_LOAD_ENTRY; } } @@ -315,66 +287,66 @@ CdmResponseType UsageTableHeader::LoadEntry(CryptoSession* crypto_session, if (metrics == nullptr) metrics = &alternate_crypto_metrics_; const CdmResponseType status = - crypto_session->LoadUsageEntry(entry_number, usage_entry); + crypto_session->LoadUsageEntry(usage_entry_number, usage_entry); if (status == NO_ERROR) { - entry_info_list_[entry_number].SetLastUseTime(GetCurrentTime()); + usage_entry_info_[usage_entry_number].last_use_time = GetCurrentTime(); } return status; } -CdmResponseType UsageTableHeader::UpdateEntry(uint32_t entry_number, +CdmResponseType UsageTableHeader::UpdateEntry(uint32_t usage_entry_number, CryptoSession* crypto_session, CdmUsageEntry* usage_entry) { - LOGD("entry_number = %u", entry_number); - std::unique_lock auto_lock(table_lock_); - if (entry_number >= entry_info_list_.size()) { + LOGD("usage_entry_number = %u", usage_entry_number); + std::unique_lock auto_lock(usage_table_header_lock_); + if (usage_entry_number >= usage_entry_info_.size()) { LOGE("Usage entry number %u is larger than usage entry size %zu", - entry_number, entry_info_list_.size()); + usage_entry_number, usage_entry_info_.size()); return USAGE_INVALID_PARAMETERS_2; } CdmResponseType status = - crypto_session->UpdateUsageEntry(&table_header_, usage_entry); + crypto_session->UpdateUsageEntry(&usage_table_header_, usage_entry); if (status != NO_ERROR) return status; - entry_info_list_[entry_number].SetLastUseTime(GetCurrentTime()); + usage_entry_info_[usage_entry_number].last_use_time = GetCurrentTime(); StoreTable(); return NO_ERROR; } CdmResponseType UsageTableHeader::InvalidateEntry( - uint32_t entry_number, bool defrag_table, DeviceFiles* device_files, + uint32_t usage_entry_number, bool defrag_table, DeviceFiles* device_files, metrics::CryptoMetrics* metrics) { - LOGD("entry_number = %u", entry_number); - TableLock auto_lock(table_lock_); - return InvalidateEntryInternal(entry_number, defrag_table, device_files, + LOGD("usage_entry_number = %u", usage_entry_number); + TableLock auto_lock(usage_table_header_lock_); + return InvalidateEntryInternal(usage_entry_number, defrag_table, device_files, metrics); } CdmResponseType UsageTableHeader::InvalidateEntryInternal( - uint32_t entry_number, bool defrag_table, DeviceFiles* device_files, + uint32_t usage_entry_number, bool defrag_table, DeviceFiles* device_files, metrics::CryptoMetrics* metrics) { // OEMCrypto does not have any concept of "deleting" an entry. - // Instead, the CDM clears the entry's meta data and then performs a - // "defrag" of the OEMCrypto table. - if (entry_number >= entry_info_list_.size()) { + // Instead, the CDM marks the entry's meta data as invalid (storage + // type unknown) and then performs a "defrag" of the OEMCrypto table. + if (usage_entry_number >= usage_entry_info_.size()) { LOGE( "Usage entry number is larger than table size: " - "entry_number = %u, table_size = %zu", - entry_number, entry_info_list_.size()); + "usage_entry_number = %u, table_size = %zu", + usage_entry_number, usage_entry_info_.size()); return USAGE_INVALID_PARAMETERS_1; } - entry_info_list_[entry_number].Clear(); + usage_entry_info_[usage_entry_number].Clear(); if (defrag_table) { // The defrag operation calls many OEMCrypto functions that are - // unrelated to the caller, the only error that will be returned - // is a SYSTEM_INVALIDATED_ERROR. As long as the entry is cleared - // the operation is considered successful. + // unrelated to the caller, the only error that will be returned is + // a SYSTEM_INVALIDATED_ERROR. As long as the storage type is + // properly set to unknown, the operation is considered successful. // SYSTEM_INVALIDATED_ERROR is a special type of error that must be // sent back to the caller for the CDM as a whole to handle. const uint32_t pre_defrag_store_counter = store_table_counter_; @@ -397,10 +369,10 @@ CdmResponseType UsageTableHeader::InvalidateEntryInternal( return NO_ERROR; } -size_t UsageTableHeader::OccupiedEntryCount() const { - LOGV("Locking to count occupied entries"); - return std::count_if(entry_info_list_.cbegin(), entry_info_list_.cend(), - EntryIsOccupied); +size_t UsageTableHeader::OfflineEntryCount() const { + LOGV("Locking to count offline license entries"); + return std::count_if(usage_entry_info_.cbegin(), usage_entry_info_.cend(), + EntryIsOfflineLicense); } bool UsageTableHeader::OpenSessionCheck(CryptoSession* const crypto_session) { @@ -427,7 +399,7 @@ bool UsageTableHeader::CapacityCheck(CryptoSession* const crypto_session) { const size_t capacity_threshold = HasUnlimitedTableCapacity() ? kMinimumUsageTableEntriesSupported : potential_table_capacity(); - if (entry_info_list_.size() <= capacity_threshold) { + if (usage_entry_info_.size() <= capacity_threshold) { // No need to perform test if below capacity. return true; } @@ -451,9 +423,9 @@ bool UsageTableHeader::CapacityCheck(CryptoSession* const crypto_session) { return false; } - uint32_t temporary_entry_number; + uint32_t temporary_usage_entry_number; status = AddEntry(local_crypto_session, kDummyKeySetId, kEmptyString, - &temporary_entry_number); + &temporary_usage_entry_number); if (status != NO_ERROR) { LOGE("Failed to add entry for capacity test: sts = %d", static_cast(status)); @@ -461,14 +433,14 @@ bool UsageTableHeader::CapacityCheck(CryptoSession* const crypto_session) { } status = - InvalidateEntry(temporary_entry_number, + InvalidateEntry(temporary_usage_entry_number, /* defrag_table = */ true, device_files_.get(), metrics); if (status != NO_ERROR) { LOGE("Failed to invalidate entry for capacity test: sts = %d", static_cast(status)); return false; } - if (entry_info_list_.size() > temporary_entry_number) { + if (usage_entry_info_.size() > temporary_usage_entry_number) { // The entry should have been deleted from the usage table, // not just marked as type unknown. Failure to call // Shrink() may be an indicator of other issues. @@ -503,39 +475,40 @@ bool UsageTableHeader::DetermineTableCapacity(CryptoSession* crypto_session) { } CdmResponseType UsageTableHeader::CreateEntry( - CryptoSession* const crypto_session, uint32_t* entry_number) { - const CdmResponseType status = crypto_session->CreateUsageEntry(entry_number); + CryptoSession* const crypto_session, uint32_t* usage_entry_number) { + const CdmResponseType status = + crypto_session->CreateUsageEntry(usage_entry_number); if (status != NO_ERROR) return status; // If the new entry number is smaller than expected, then the usage // table may be out of sync or OEMCrypto has been rolled back. // Not safe to continue. - if (*entry_number < entry_info_list_.size()) { + if (*usage_entry_number < usage_entry_info_.size()) { LOGE( "New entry number is smaller than table size: " "entry_info_number = %u, table_size = %zu", - *entry_number, entry_info_list_.size()); + *usage_entry_number, usage_entry_info_.size()); return USAGE_INVALID_NEW_ENTRY; } - LOGI("entry_number = %u", *entry_number); - const size_t previous_size = entry_info_list_.size(); - entry_info_list_.resize(*entry_number + 1); - if (*entry_number > previous_size) { + LOGI("usage_entry_number = %u", *usage_entry_number); + const size_t previous_size = usage_entry_info_.size(); + usage_entry_info_.resize(*usage_entry_number + 1); + if (*usage_entry_number > previous_size) { LOGW( "New entry number is larger than table size, resizing: " "entry_info_number = %u, table_size = %zu", - *entry_number, previous_size); - for (size_t i = previous_size; i < entry_info_list_.size() - 1; ++i) { - entry_info_list_[i].Clear(); + *usage_entry_number, previous_size); + for (size_t i = previous_size; i < usage_entry_info_.size() - 1; ++i) { + usage_entry_info_[i].Clear(); } } - entry_info_list_[*entry_number].Clear(); + usage_entry_info_[*usage_entry_number].Clear(); return NO_ERROR; } CdmResponseType UsageTableHeader::RelocateNewEntry( - CryptoSession* const crypto_session, uint32_t* entry_number) { + CryptoSession* const crypto_session, uint32_t* usage_entry_number) { static constexpr uint32_t kMinimumEntryNumber = 0; - const uint32_t initial_entry_number = *entry_number; + const uint32_t initial_entry_number = *usage_entry_number; if (initial_entry_number == kMinimumEntryNumber) { // First entry in the table. return NO_ERROR; @@ -562,72 +535,86 @@ CdmResponseType UsageTableHeader::RelocateNewEntry( if (status != NO_ERROR) return status; LOGI("Entry moved: from_index = %u, to_index = %u", initial_entry_number, unoccupied_entry_number); - *entry_number = unoccupied_entry_number; - entry_info_list_[unoccupied_entry_number] = - std::move(entry_info_list_[initial_entry_number]); - entry_info_list_[initial_entry_number].Clear(); + *usage_entry_number = unoccupied_entry_number; + usage_entry_info_[unoccupied_entry_number] = + std::move(usage_entry_info_[initial_entry_number]); + usage_entry_info_[initial_entry_number].Clear(); return NO_ERROR; } -bool UsageTableHeader::IsEntryUnoccupied(const uint32_t entry_number) const { - if (entry_info_list_[entry_number].HasKeySetId()) { +bool UsageTableHeader::IsEntryUnoccupied( + const uint32_t usage_entry_number) const { + if (usage_entry_info_[usage_entry_number].storage_type != + kStorageTypeUnknown) { return false; } // TODO(sigquit): Check that entry is not in use by another session. - // NOTE: The check will protect the integrity of the entry. - // Attempting to use an entry index that is used by another + // NOTE: The |storage_type| check will protect the integrity of the + // entry. Attempting to use an entry index that is used by another // session is recoverable and will not affect any opened sessions. return true; } void UsageTableHeader::SetOfflineEntryInfo( - const uint32_t entry_number, const std::string& key_set_id, + const uint32_t usage_entry_number, const std::string& key_set_id, const CdmKeyResponse& license_message) { - CdmUsageEntryInfo& entry_info = entry_info_list_[entry_number]; - const int64_t current_time = GetCurrentTime(); + CdmUsageEntryInfo& entry_info = usage_entry_info_[usage_entry_number]; entry_info.Clear(); - entry_info.SetKeySetId(key_set_id); - entry_info.SetLastUseTime(current_time); - entry_info.SetLicenseExpiryTime( - CalculateOfflineLicenseExpiryTime(license_message, current_time)); + entry_info.storage_type = kStorageLicense; + entry_info.key_set_id = key_set_id; + entry_info.last_use_time = GetCurrentTime(); + // Need to determine the expire time for offline licenses. + video_widevine::License license; + if (!license_message.empty() && + ParseLicenseFromLicenseMessage(license_message, &license)) { + const video_widevine::License::Policy& policy = license.policy(); + entry_info.offline_license_expiry_time = license.license_start_time() + + policy.rental_duration_seconds() + + policy.playback_duration_seconds(); + } else { + // If the license duration cannot be determined for any reason, it + // is assumed to last at most 33 days. + entry_info.offline_license_expiry_time = + entry_info.last_use_time + kDefaultExpireDuration; + } } CdmResponseType UsageTableHeader::RefitTable( CryptoSession* const crypto_session) { // Remove all unoccupied entries at end of the table. uint32_t entries_to_remove = 0; - const uint32_t old_size = static_cast(entry_info_list_.size()); + const uint32_t old_size = static_cast(usage_entry_info_.size()); for (uint32_t i = 0; i < old_size; i++) { - const uint32_t entry_number = old_size - i - 1; - if (!IsEntryUnoccupied(entry_number)) break; + const uint32_t usage_entry_number = old_size - i - 1; + if (!IsEntryUnoccupied(usage_entry_number)) break; ++entries_to_remove; } if (entries_to_remove == 0) return NO_ERROR; const uint32_t new_size = old_size - entries_to_remove; const CdmResponseType status = crypto_session->ShrinkUsageTableHeader( - requested_security_level_, new_size, &table_header_); + requested_security_level_, new_size, &usage_table_header_); if (status == SHRINK_USAGE_TABLE_HEADER_ENTRY_IN_USE) { // This error likely indicates that another session has released // its entry via a call to InvalidateEntry(), but has yet to close // its OEMCrypto session. // Safe to assume table state is not invalidated. LOGW("Unexpected entry in use: range = [%u, %zu]", new_size, - entry_info_list_.size() - 1); + usage_entry_info_.size() - 1); return NO_ERROR; } if (status != NO_ERROR) return status; - LOGD("Table shrunk: old_size = %zu, new_size = %u", entry_info_list_.size(), + LOGD("Table shrunk: old_size = %zu, new_size = %u", usage_entry_info_.size(), new_size); - entry_info_list_.resize(new_size); + usage_entry_info_.resize(new_size); return NO_ERROR; } CdmResponseType UsageTableHeader::MoveEntry( - uint32_t from_entry_number, const CdmUsageEntry& from_usage_entry, - uint32_t to_entry_number, DeviceFiles* device_files, + uint32_t from_usage_entry_number, const CdmUsageEntry& from_usage_entry, + uint32_t to_usage_entry_number, DeviceFiles* device_files, metrics::CryptoMetrics* metrics) { - LOGD("from_entry_number = %u, to_entry_number = %u", from_entry_number, - to_entry_number); + LOGD("from_usage_entry_number = %u, to_usage_entry_number = %u", + from_usage_entry_number, to_usage_entry_number); // crypto_session points to an object whose scope is this method or a test // object whose scope is the lifetime of this class @@ -640,78 +627,87 @@ CdmResponseType UsageTableHeader::MoveEntry( CdmResponseType status = crypto_session->Open(requested_security_level_); if (status != NO_ERROR) { - LOGE("Cannot open session for move: entry_number = %u", from_entry_number); + LOGE("Cannot open session for move: usage_entry_number = %u", + from_usage_entry_number); return status; } - status = crypto_session->LoadUsageEntry(from_entry_number, from_usage_entry); + status = + crypto_session->LoadUsageEntry(from_usage_entry_number, from_usage_entry); if (status != NO_ERROR) { - LOGE("Failed to load usage entry: entry_number = %u", from_entry_number); + LOGE("Failed to load usage entry: usage_entry_number = %u", + from_usage_entry_number); return status; } - status = crypto_session->MoveUsageEntry(to_entry_number); + status = crypto_session->MoveUsageEntry(to_usage_entry_number); if (status != NO_ERROR) { LOGE( "Failed to move usage entry: " - "from_entry_number = %u, to_entry_number = %u", - from_entry_number, to_entry_number); + "from_usage_entry_number = %u, to_usage_entry_number = %u", + from_usage_entry_number, to_usage_entry_number); return status; } - entry_info_list_[to_entry_number] = entry_info_list_[from_entry_number]; - entry_info_list_[from_entry_number].Clear(); + usage_entry_info_[to_usage_entry_number] = + usage_entry_info_[from_usage_entry_number]; + usage_entry_info_[from_usage_entry_number].Clear(); CdmUsageEntry usage_entry; - status = crypto_session->UpdateUsageEntry(&table_header_, &usage_entry); + status = crypto_session->UpdateUsageEntry(&usage_table_header_, &usage_entry); if (status != NO_ERROR) { - LOGE("Failed to update usage entry: entry_number = %u", to_entry_number); + LOGE("Failed to update usage entry: usage_entry_number = %u", + to_usage_entry_number); return status; } // Store the usage table and usage entry after successful move. StoreTable(); - StoreEntry(to_entry_number, device_files, usage_entry); + StoreEntry(to_usage_entry_number, device_files, usage_entry); return NO_ERROR; } -CdmResponseType UsageTableHeader::GetEntry(uint32_t entry_number, +CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number, DeviceFiles* device_files, CdmUsageEntry* usage_entry) { - LOGD("entry_number = %u, entry_state = %s", entry_number, - GetEntryStateString(entry_number, entry_info_list_)); - if (entry_number >= entry_info_list_.size()) { - LOGE("Entry out of bounds: entry_number = %u, table_size = %zu", - entry_number, entry_info_list_.size()); + LOGD("Getting usage_entry_number = %u, storage_type = %s", usage_entry_number, + CdmUsageEntryStorageTypeToString( + usage_entry_number < usage_entry_info_.size() + ? usage_entry_info_[usage_entry_number].storage_type + : kStorageTypeUnknown)); + if (usage_entry_number >= usage_entry_info_.size()) { + LOGE("Entry out of bounds: usage_entry_number = %u, table_size = %zu", + usage_entry_number, usage_entry_info_.size()); return USAGE_GET_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE; } - const CdmUsageEntryInfo& entry_info = entry_info_list_[entry_number]; - if (!entry_info.HasKeySetId()) { + CdmUsageEntryInfo& entry_info = usage_entry_info_[usage_entry_number]; + if (entry_info.storage_type != kStorageLicense) { LOGE( - "Cannot retrieve information not associated without a key set ID: " - "entry_number = %u", - entry_number); + "Cannot retrieve information not associated without a license: " + "usage_entry_number = %u", + usage_entry_number); return USAGE_GET_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE; } // Retrieve license. DeviceFiles::CdmLicenseData license_data; DeviceFiles::ResponseType sub_error_code = DeviceFiles::kNoError; - if (!device_files->RetrieveLicense(entry_info.key_set_id(), &license_data, - &sub_error_code)) { + if (!device_files->RetrieveLicense( + usage_entry_info_[usage_entry_number].key_set_id, &license_data, + &sub_error_code)) { LOGE("Failed to retrieve license: status = %d", static_cast(sub_error_code)); return USAGE_GET_ENTRY_RETRIEVE_LICENSE_FAILED; } // Validate entry number. - if (entry_number != license_data.usage_entry_number) { + if (usage_entry_number != license_data.usage_entry_number) { LOGE( - "Usage entry number mismatch: expected_entry_number = %u, " - "retrieved_entry_number = %u", - entry_number, license_data.usage_entry_number); + "Usage entry number mismatch: expected_usage_entry_number = %u, " + "retrieved_usage_entry_number = %u", + usage_entry_number, license_data.usage_entry_number); return USAGE_ENTRY_NUMBER_MISMATCH; } @@ -719,36 +715,40 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t entry_number, return NO_ERROR; } -CdmResponseType UsageTableHeader::StoreEntry(uint32_t entry_number, +CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number, DeviceFiles* device_files, const CdmUsageEntry& usage_entry) { - LOGD("entry_number = %u, entry_state = %s", entry_number, - GetEntryStateString(entry_number, entry_info_list_)); - if (entry_number >= entry_info_list_.size()) { - LOGE("Entry out of bounds: entry_number = %u, table_size = %zu", - entry_number, entry_info_list_.size()); + LOGD("usage_entry_number = %u, storage_type = %s", usage_entry_number, + CdmUsageEntryStorageTypeToString( + usage_entry_number < usage_entry_info_.size() + ? usage_entry_info_[usage_entry_number].storage_type + : kStorageTypeUnknown)); + if (usage_entry_number >= usage_entry_info_.size()) { + LOGE("Entry out of bounds: usage_entry_number = %u, table_size = %zu", + usage_entry_number, usage_entry_info_.size()); return USAGE_STORE_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE; } - CdmUsageEntryInfo& entry_info = entry_info_list_[entry_number]; - if (!entry_info.HasKeySetId()) { + CdmUsageEntryInfo& entry_info = usage_entry_info_[usage_entry_number]; + if (entry_info.storage_type != kStorageLicense) { LOGE( - "Cannot store information not associated without a key set ID: " - "entry_number = %u", - entry_number); + "Cannot store information not associated without a license: " + "usage_entry_number = %u", + usage_entry_number); return USAGE_STORE_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE; } // Retrieve existing. DeviceFiles::CdmLicenseData license_data; DeviceFiles::ResponseType sub_error_code = DeviceFiles::kNoError; - if (!device_files->RetrieveLicense(entry_info.key_set_id(), &license_data, - &sub_error_code)) { + if (!device_files->RetrieveLicense( + usage_entry_info_[usage_entry_number].key_set_id, &license_data, + &sub_error_code)) { LOGE("Failed to retrieve license: status = %s", DeviceFiles::ResponseTypeToString(sub_error_code)); return USAGE_STORE_ENTRY_RETRIEVE_LICENSE_FAILED; } // Update. license_data.usage_entry = usage_entry; - license_data.usage_entry_number = entry_number; + license_data.usage_entry_number = usage_entry_number; if (!device_files->StoreLicense(license_data, &sub_error_code)) { LOGE("Failed to store license: status = %s", @@ -760,8 +760,8 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t entry_number, bool UsageTableHeader::StoreTable() { LOGV("Storing usage table information"); - const bool result = - device_files_->StoreUsageTableInfo(table_header_, entry_info_list_); + const bool result = device_files_->StoreUsageTableInfo(usage_table_header_, + usage_entry_info_); if (result) { ++store_table_counter_; } else { @@ -770,25 +770,26 @@ bool UsageTableHeader::StoreTable() { return result; } -CdmResponseType UsageTableHeader::Shrink(metrics::CryptoMetrics* metrics, - uint32_t number_of_entries_to_delete) { - LOGD("table_size = %zu, number_to_delete = %u", entry_info_list_.size(), - number_of_entries_to_delete); - if (entry_info_list_.empty()) { +CdmResponseType UsageTableHeader::Shrink( + metrics::CryptoMetrics* metrics, + uint32_t number_of_usage_entries_to_delete) { + LOGD("table_size = %zu, number_to_delete = %u", usage_entry_info_.size(), + number_of_usage_entries_to_delete); + if (usage_entry_info_.empty()) { LOGE("Usage entry info table unexpectedly empty"); return NO_USAGE_ENTRIES; } - if (entry_info_list_.size() < number_of_entries_to_delete) { + if (usage_entry_info_.size() < number_of_usage_entries_to_delete) { LOGW( "Cannot delete more entries than the table size, reducing to current " "table size: table_size = %zu, number_to_delete = %u", - entry_info_list_.size(), number_of_entries_to_delete); - number_of_entries_to_delete = - static_cast(entry_info_list_.size()); + usage_entry_info_.size(), number_of_usage_entries_to_delete); + number_of_usage_entries_to_delete = + static_cast(usage_entry_info_.size()); } - if (number_of_entries_to_delete == 0) return NO_ERROR; + if (number_of_usage_entries_to_delete == 0) return NO_ERROR; // crypto_session points to an object whose scope is this method or a test // object whose scope is the lifetime of this class @@ -799,13 +800,13 @@ CdmResponseType UsageTableHeader::Shrink(metrics::CryptoMetrics* metrics, crypto_session = scoped_crypto_session.get(); } - const uint32_t new_size = static_cast(entry_info_list_.size()) - - number_of_entries_to_delete; + const uint32_t new_size = static_cast(usage_entry_info_.size()) - + number_of_usage_entries_to_delete; const CdmResponseType status = crypto_session->ShrinkUsageTableHeader( - requested_security_level_, new_size, &table_header_); + requested_security_level_, new_size, &usage_table_header_); if (status == NO_ERROR) { - entry_info_list_.resize(new_size); + usage_entry_info_.resize(new_size); StoreTable(); } return status; @@ -813,7 +814,7 @@ CdmResponseType UsageTableHeader::Shrink(metrics::CryptoMetrics* metrics, CdmResponseType UsageTableHeader::DefragTable(DeviceFiles* device_files, metrics::CryptoMetrics* metrics) { - LOGV("current_size = %zu", entry_info_list_.size()); + LOGV("current_size = %zu", usage_entry_info_.size()); // Defragging the usage table involves moving valid entries near the // end of the usage table to the position of invalid entries near the // front of the table. After the entries are moved, the CDM shrinks @@ -821,7 +822,7 @@ CdmResponseType UsageTableHeader::DefragTable(DeviceFiles* device_files, // the table. // Special case 0: Empty table, do nothing. - if (entry_info_list_.empty()) { + if (usage_entry_info_.empty()) { LOGD("Table empty, nothing to defrag"); return NO_ERROR; } @@ -831,10 +832,10 @@ CdmResponseType UsageTableHeader::DefragTable(DeviceFiles* device_files, // To avoid large delays from the swapping process, we limit the // quantity of entries to remove to |kMaxDefragEntryMoves| or fewer. std::vector entries_to_remove; - for (uint32_t i = 0; i < entry_info_list_.size() && + for (uint32_t i = 0; i < usage_entry_info_.size() && entries_to_remove.size() < kMaxDefragEntryMoves; ++i) { - if (entry_info_list_[i].IsEmpty()) { + if (usage_entry_info_[i].storage_type == kStorageTypeUnknown) { entries_to_remove.push_back(i); } } @@ -849,13 +850,13 @@ CdmResponseType UsageTableHeader::DefragTable(DeviceFiles* device_files, // Step 2: Create a list of entries to be moved from the end of the // table to the positions identified for removal. std::vector entries_to_move; - for (uint32_t i = 0; i < entry_info_list_.size() && + for (uint32_t i = 0; i < usage_entry_info_.size() && entries_to_move.size() < entries_to_remove.size(); ++i) { // Search from the end of the table. const uint32_t entry_index = - static_cast(entry_info_list_.size()) - i - 1; - if (entry_info_list_[entry_index].HasKeySetId()) { + static_cast(usage_entry_info_.size()) - i - 1; + if (usage_entry_info_[entry_index].storage_type != kStorageTypeUnknown) { entries_to_move.push_back(entry_index); } } @@ -864,8 +865,8 @@ CdmResponseType UsageTableHeader::DefragTable(DeviceFiles* device_files, // the whole table can be removed. if (entries_to_move.empty()) { LOGD("No valid entries found, shrinking entire table: size = %zu", - entry_info_list_.size()); - return Shrink(metrics, static_cast(entry_info_list_.size())); + usage_entry_info_.size()); + return Shrink(metrics, static_cast(usage_entry_info_.size())); } // Step 3: Ignore invalid entries that are after the last valid @@ -885,7 +886,7 @@ CdmResponseType UsageTableHeader::DefragTable(DeviceFiles* device_files, // be shrunk to the last valid entry. if (entries_to_remove.empty()) { const uint32_t to_remove = - static_cast(entry_info_list_.size()) - last_valid_entry - 1; + static_cast(usage_entry_info_.size()) - last_valid_entry - 1; LOGD("Removing all entries after the last valid entry: count = %u", to_remove); return Shrink(metrics, to_remove); @@ -920,7 +921,7 @@ CdmResponseType UsageTableHeader::DefragTable(DeviceFiles* device_files, LOGW("Could not get entry: entry_number = %u", from_entry_number); // It is unlikely that an unretrievable entry will suddenly // become retrievable later on when it is needed. - entry_info_list_[from_entry_number].Clear(); + usage_entry_info_[from_entry_number].Clear(); entries_to_move.pop_back(); continue; } @@ -950,7 +951,7 @@ CdmResponseType UsageTableHeader::DefragTable(DeviceFiles* device_files, // can no longer be used. Safe to continue loop. // TODO(b/152256186): Remove local files associated with this // entry. - entry_info_list_[from_entry_number].Clear(); + usage_entry_info_[from_entry_number].Clear(); LOGW("From entry was corrupted: from_entry_number = %u", from_entry_number); entries_to_move.pop_back(); @@ -960,8 +961,8 @@ CdmResponseType UsageTableHeader::DefragTable(DeviceFiles* device_files, case MOVE_USAGE_ENTRY_DESTINATION_IN_USE: { // The usage entry specified by |to_entry_number| is currently // being used by another session. This is unlikely, but still - // possible. Given that this entry is already cleared, it will - // likely be removed at a later time. + // possible. Given that this entry is already marked as unknown + // storage type, it will likely be removed at a later time. LOGD("To entry already in use: to_entry_number = %u", to_entry_number); entries_to_remove.pop_back(); break; @@ -999,11 +1000,11 @@ CdmResponseType UsageTableHeader::DefragTable(DeviceFiles* device_files, // Step 5: Find the new last valid entry. uint32_t new_last_valid_entry = - static_cast(entry_info_list_.size()); - for (uint32_t i = 0; i < entry_info_list_.size(); ++i) { + static_cast(usage_entry_info_.size()); + for (uint32_t i = 0; i < usage_entry_info_.size(); ++i) { const uint32_t entry_index = - static_cast(entry_info_list_.size()) - i - 1; - if (entry_info_list_[entry_index].HasKeySetId()) { + static_cast(usage_entry_info_.size()) - i - 1; + if (usage_entry_info_[entry_index].storage_type != kStorageTypeUnknown) { new_last_valid_entry = entry_index; break; } @@ -1012,15 +1013,15 @@ CdmResponseType UsageTableHeader::DefragTable(DeviceFiles* device_files, // Special case 5: No entries in the table are valid. This could // have occurred if entries during the move process were found to be // invalid. In this case, remove the whole table. - if (new_last_valid_entry == entry_info_list_.size()) { + if (new_last_valid_entry == usage_entry_info_.size()) { LOGD( "All entries have been invalidated, shrinking entire table: size = %zu", - entry_info_list_.size()); - return Shrink(metrics, static_cast(entry_info_list_.size())); + usage_entry_info_.size()); + return Shrink(metrics, static_cast(usage_entry_info_.size())); } - const uint32_t to_remove = - static_cast(entry_info_list_.size()) - new_last_valid_entry - 1; + const uint32_t to_remove = static_cast(usage_entry_info_.size()) - + new_last_valid_entry - 1; // Special case 6: It is possible that the last entry in the table // is valid and currently loaded in the table by another session. @@ -1045,13 +1046,13 @@ CdmResponseType UsageTableHeader::ReleaseOldestEntry( LOGE("Could not determine which license to remove"); return UNKNOWN_ERROR; } - const CdmUsageEntryInfo& entry_info = - entry_info_list_[entry_number_to_delete]; + const CdmUsageEntryInfo& usage_entry_info = + usage_entry_info_[entry_number_to_delete]; const int64_t current_time = GetCurrentTime(); - // Capture metric values now, as the |entry_info| reference will + // Capture metric values now, as the |usage_entry_info| reference will // change after the call to invalidate. - const int64_t staleness = current_time - entry_info.last_use_time(); + const int64_t staleness = current_time - usage_entry_info.last_use_time; const CdmResponseType status = InvalidateEntryInternal(entry_number_to_delete, /* defrag_table = */ true, @@ -1069,96 +1070,99 @@ CdmResponseType UsageTableHeader::ReleaseOldestEntry( } // Test only method. -void UsageTableHeader::InvalidateEntryForTest(uint32_t entry_number) { - LOGD("entry_number = %u", entry_number); - if (entry_number >= entry_info_list_.size()) { +void UsageTableHeader::InvalidateEntryForTest(uint32_t usage_entry_number) { + LOGD("usage_entry_number = %u", usage_entry_number); + if (usage_entry_number >= usage_entry_info_.size()) { LOGE( "Requested usage entry number is larger than table size: " - "entry_number = %u, table_size = %zu", - entry_number, entry_info_list_.size()); + "usage_entry_number = %u, table_size = %zu", + usage_entry_number, usage_entry_info_.size()); return; } // Move last entry into invalidated entry location and shrink usage // entries. - entry_info_list_[entry_number] = - entry_info_list_[entry_info_list_.size() - 1]; - entry_info_list_.resize(entry_info_list_.size() - 1); + usage_entry_info_[usage_entry_number] = + usage_entry_info_[usage_entry_info_.size() - 1]; + usage_entry_info_.resize(usage_entry_info_.size() - 1); } bool UsageTableHeader::LruUpgradeAllUsageEntries() { LOGV("Upgrading all usage entries with LRU information"); - if (entry_info_list_.size() == 0) return true; // Nothing to upgrade. + if (usage_entry_info_.size() == 0) return true; // Nothing to upgrade. // For each entry, the status upgrading that entry is stored. At the // end, all problematic licenses will be marked as invalid. std::vector bad_license_file_entries; - for (uint32_t entry_number = 0; entry_number < entry_info_list_.size(); - ++entry_number) { - CdmUsageEntryInfo& entry_info = entry_info_list_[entry_number]; + for (uint32_t usage_entry_number = 0; + usage_entry_number < usage_entry_info_.size(); ++usage_entry_number) { + CdmUsageEntryInfo& usage_entry_info = usage_entry_info_[usage_entry_number]; - if (entry_info.IsEmpty()) { - bad_license_file_entries.push_back(entry_number); + if (usage_entry_info.storage_type != kStorageLicense) { + bad_license_file_entries.push_back(usage_entry_number); continue; } uint32_t retrieved_entry_number; CdmKeyResponse license_message; const bool retrieve_response = - RetrieveOfflineLicense(device_files_.get(), entry_info.key_set_id(), + RetrieveOfflineLicense(device_files_.get(), usage_entry_info.key_set_id, &license_message, &retrieved_entry_number); if (!retrieve_response) { - LOGW("Could not retrieve license message: entry_number = %u", - entry_number); - bad_license_file_entries.push_back(entry_number); + LOGW("Could not retrieve license message: usage_entry_number = %u", + usage_entry_number); + bad_license_file_entries.push_back(usage_entry_number); continue; } - if (retrieved_entry_number != entry_number) { + if (retrieved_entry_number != usage_entry_number) { LOGW( - "Usage entry number mismatched: entry_number = %u, " + "Usage entry number mismatched: usage_entry_number = %u, " "retrieved_entry_number = %u", - entry_number, retrieved_entry_number); - bad_license_file_entries.push_back(entry_number); + usage_entry_number, retrieved_entry_number); + bad_license_file_entries.push_back(usage_entry_number); continue; } video_widevine::License license; if (!ParseLicenseFromLicenseMessage(license_message, &license)) { - LOGW("Could not parse license: entry_number = %u", entry_number); - bad_license_file_entries.push_back(entry_number); + LOGW("Could not parse license: usage_entry_number = %u", + usage_entry_number); + bad_license_file_entries.push_back(usage_entry_number); continue; } // If |license_start_time| is 0, then this entry will be considered // for replacement above all others. - entry_info.SetLastUseTime(license.license_start_time()); + usage_entry_info.last_use_time = license.license_start_time(); + + // Only offline licenses need |offline_license_expiry_time| set. const video_widevine::License::Policy& policy = license.policy(); // TODO(b/139372190): Change how these fields are set once feature is // implemented. if (policy.license_duration_seconds() == 0) { // Zero implies unlimited license duration. - entry_info.SetLicenseExpiryTime(license.license_start_time() + - policy.rental_duration_seconds() + - policy.playback_duration_seconds()); + usage_entry_info.offline_license_expiry_time = + license.license_start_time() + policy.rental_duration_seconds() + + policy.playback_duration_seconds(); } else { - entry_info.SetLicenseExpiryTime(license.license_start_time() + - policy.license_duration_seconds()); + usage_entry_info.offline_license_expiry_time = + license.license_start_time() + policy.license_duration_seconds(); } } // End for loop. - if (bad_license_file_entries.size() == entry_info_list_.size()) { + if (bad_license_file_entries.size() == usage_entry_info_.size()) { LOGE("Failed to perform LRU upgrade for every entry: count = %zu", - entry_info_list_.size()); + usage_entry_info_.size()); return false; } - for (size_t entry_number : bad_license_file_entries) { - CdmUsageEntryInfo& entry_info = entry_info_list_[entry_number]; - if (entry_info.HasKeySetId()) { - device_files_->DeleteLicense(entry_info.key_set_id()); + for (size_t usage_entry_number : bad_license_file_entries) { + CdmUsageEntryInfo& usage_entry_info = usage_entry_info_[usage_entry_number]; + if (usage_entry_info.storage_type == kStorageLicense) { + device_files_->DeleteLicense(usage_entry_info.key_set_id); } - entry_info.Clear(); + usage_entry_info.Clear(); } return true; @@ -1169,7 +1173,7 @@ bool UsageTableHeader::GetRemovalCandidate(uint32_t* entry_to_remove) { HasUnlimitedTableCapacity() ? kLruUnexpiredThresholdFraction * size() : kLruUnexpiredThresholdFraction * potential_table_capacity(); - return DetermineLicenseToRemove(entry_info_list_, GetCurrentTime(), + return DetermineLicenseToRemove(usage_entry_info_, GetCurrentTime(), lru_unexpired_threshold, entry_to_remove); } @@ -1178,9 +1182,8 @@ void UsageTableHeader::RecordLruEventMetrics(metrics::CryptoMetrics* metrics, if (metrics == nullptr) return; // Usage info are deprecated, always record 0. metrics->usage_table_header_lru_usage_info_count_.Record(0); - // All occupied entries are assumed to be offline licenses. metrics->usage_table_header_lru_offline_license_count_.Record( - OccupiedEntryCount()); + OfflineEntryCount()); metrics->usage_table_header_lru_evicted_entry_staleness_.Record(staleness); // Can be assumed that only offline licenses are removed. constexpr int kDefaultEntryType = 0; @@ -1190,41 +1193,44 @@ void UsageTableHeader::RecordLruEventMetrics(metrics::CryptoMetrics* metrics, // Static. bool UsageTableHeader::DetermineLicenseToRemove( - const std::vector& entry_info_list, int64_t current_time, - size_t unexpired_threshold, uint32_t* entry_to_remove) { + const std::vector& usage_entry_info_list, + int64_t current_time, size_t unexpired_threshold, + uint32_t* entry_to_remove) { if (entry_to_remove == nullptr) { LOGE("Output parameter |entry_to_remove| is null"); return false; } - if (entry_info_list.empty()) { + if (usage_entry_info_list.empty()) { return false; } // Returns true if entry of first index is more stale than the // entry of the second index. const auto is_more_stale = [&](uint32_t i, uint32_t j) -> bool { - return entry_info_list[i].last_use_time() < - entry_info_list[j].last_use_time(); + return usage_entry_info_list[i].last_use_time < + usage_entry_info_list[j].last_use_time; }; // Find the most stale expired offline license and the // most stale unexpired offline entry. Count the number of unexpired - // entries. If any entry is empty, then it should be removed. + // entries. If any entry is not of storage type license, then it should + // be removed. constexpr uint32_t kNoEntry = std::numeric_limits::max(); uint32_t stalest_expired_offline_license = kNoEntry; uint32_t stalest_unexpired_offline_license = kNoEntry; size_t unexpired_license_count = 0; - for (uint32_t entry_number = 0; entry_number < entry_info_list.size(); + for (uint32_t entry_number = 0; entry_number < usage_entry_info_list.size(); ++entry_number) { - const CdmUsageEntryInfo& entry_info = entry_info_list[entry_number]; + const CdmUsageEntryInfo& usage_entry_info = + usage_entry_info_list[entry_number]; - if (entry_info.IsEmpty()) { - // Remove empty entry. + if (usage_entry_info.storage_type != kStorageLicense) { + // Non-license storage type entries. Remove this entry. *entry_to_remove = entry_number; return true; } - if (entry_info.license_expiry_time() > current_time) { + if (usage_entry_info.offline_license_expiry_time > current_time) { // Unexpired offline. ++unexpired_license_count; if (stalest_unexpired_offline_license == kNoEntry || @@ -1246,7 +1252,8 @@ bool UsageTableHeader::DetermineLicenseToRemove( LOGW( "Table only contains unexpired offline licenses, " "but threshold not met: size = %zu, count = %zu, threshold = %zu", - entry_info_list.size(), unexpired_license_count, unexpired_threshold); + usage_entry_info_list.size(), unexpired_license_count, + unexpired_threshold); *entry_to_remove = stalest_unexpired_offline_license; return true; } @@ -1267,9 +1274,9 @@ bool UsageTableHeader::DetermineLicenseToRemove( if (*entry_to_remove == kNoEntry) { // Illegal state check. The loop above should have found at least - // one entry given that |entry_info_list| is not empty. + // one entry given that |usage_entry_info_list| is not empty. LOGE("No entry could be used for removal: size = %zu", - entry_info_list.size()); + usage_entry_info_list.size()); return false; } return true; diff --git a/libwvdrmengine/cdm/core/src/wv_cdm_types.cpp b/libwvdrmengine/cdm/core/src/wv_cdm_types.cpp index bea2d17a..ccf57b36 100644 --- a/libwvdrmengine/cdm/core/src/wv_cdm_types.cpp +++ b/libwvdrmengine/cdm/core/src/wv_cdm_types.cpp @@ -95,6 +95,19 @@ const char* CdmOfflineLicenseStateToString( return UnknownValueRep(license_state); } +const char* CdmUsageEntryStorageTypeToString(CdmUsageEntryStorageType type) { + switch (type) { + case kStorageLicense: + return "License"; + case kStorageUsageInfo: + return "UsageInfo"; + case kStorageTypeUnknown: + // Special value used to indicate an empty entry. + return "None"; + } + return UnknownValueRep(type); +} + const char* RequestedSecurityLevelToString( RequestedSecurityLevel security_level) { switch (security_level) { diff --git a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp index ca9ec8a8..4458766c 100644 --- a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp @@ -2920,17 +2920,17 @@ constexpr size_t kNumberOfHlsAttributes = ArraySize(kHlsAttributesTestData); // kUsageTableInfoTestData are equal. const std::vector kUsageEntriesTestData = { // usage entry 0 - {"ksid0", 1318402800, 1321254000}, + {kStorageLicense, "ksid0", "", 1318402800, 1321254000}, // usage entry 1 - {"ksid1", 1050649200, 1053500400}, + {kStorageLicense, "ksid1", "", 1050649200, 1053500400}, // usage entry 2 - {"", 0, 0}, + {kStorageTypeUnknown, "", "", 0, 0}, // usage entry 3 - {"", 0, 0}, + {kStorageTypeUnknown, "", "", 0, 0}, // usage entry 4 - {"ksid4", 316166400, 319017600}, + {kStorageLicense, "ksid4", "", 316166400, 319017600}, // usage entry 5 - {"ksid5", 316166400, 319017600}, + {kStorageLicense, "ksid5", "", 316166400, 319017600}, }; struct UsageTableTestInfo { @@ -3008,8 +3008,8 @@ const UsageTableTestInfo kUsageTableInfoTestData[] = { "ce072f3d2ef52febcaddff3040246a638deee994a0862142")}, }; -const CdmUsageEntryInfo kUsageEntriesWithoutLruData[] = {{"ksid0", 0, 0}, - {"", 0, 0}}; +const CdmUsageEntryInfo kUsageEntriesWithoutLruData[] = { + {kStorageLicense, "ksid0", "", 0, 0}, {kStorageTypeUnknown, "", "", 0, 0}}; const std::string kUsageTableWithoutLruData = a2bs_hex( "0A1F080510013A191209080112056B73696430120C08021A086170705F69645F" @@ -3030,7 +3030,9 @@ const UsageTableTestInfo kUsageTableInfoWithUsageInfoType = { // Expected entries after removal of USAGE_INFO. const std::vector kUsageEntriesWithoutUsageInfoType = { - {"ksid0", 1318402800, 1321254000}, {"", 0, 0}, {"", 0, 0}}; + {kStorageLicense, "ksid0", "", 1318402800, 1321254000}, + {kStorageTypeUnknown, "", "", 0, 0}, + {kStorageTypeUnknown, "", "", 0, 0}}; // Contains kOemCertificate and kCryptoWrappedKey const std::string kFakeOemCertificateFile = a2bs_hex( @@ -4387,11 +4389,11 @@ TEST_P(DeviceFilesUsageTableTest, Store) { const int entry_count = GetParam(); std::vector entry_data; - const std::vector usage_entry_info_list( + const std::vector usage_entry_info( kUsageEntriesTestData.begin(), kUsageEntriesTestData.begin() + entry_count); for (int i = 0; i < entry_count; ++i) { - entry_data.push_back(kUsageEntriesTestData[i].key_set_id()); + entry_data.push_back(kUsageEntriesTestData[i].key_set_id); } entry_data.push_back(kUsageTableInfoTestData[entry_count].usage_table_header); @@ -4409,7 +4411,7 @@ TEST_P(DeviceFilesUsageTableTest, Store) { EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); ASSERT_TRUE(device_files.StoreUsageTableInfo( kUsageTableInfoTestData[entry_count].usage_table_header, - usage_entry_info_list)); + usage_entry_info)); } TEST_P(DeviceFilesUsageTableTest, Read) { @@ -4435,20 +4437,20 @@ TEST_P(DeviceFilesUsageTableTest, Read) { DeviceFiles device_files(&file_system); EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); - std::vector usage_entry_info_list; + std::vector usage_entry_info; CdmUsageTableHeader usage_table_header; bool lru_upgrade; bool has_usage_info_entries; ASSERT_TRUE(device_files.RetrieveUsageTableInfo( - &usage_table_header, &usage_entry_info_list, &lru_upgrade, + &usage_table_header, &usage_entry_info, &lru_upgrade, &has_usage_info_entries)); EXPECT_EQ(kUsageTableInfoTestData[entry_count].usage_table_header, usage_table_header); - EXPECT_EQ(entry_count, usage_entry_info_list.size()); + EXPECT_EQ(entry_count, usage_entry_info.size()); for (size_t i = 0; i < entry_count; ++i) { // TODO(b/242289743): Update test data to exclude usage info files. - EXPECT_EQ(usage_entry_info_list[i], kUsageEntriesTestData[i]); + EXPECT_EQ(usage_entry_info[i], kUsageEntriesTestData[i]); } EXPECT_FALSE(lru_upgrade); } @@ -4476,20 +4478,19 @@ TEST_F(DeviceFilesUsageTableTest, ReadWithoutLruData) { DeviceFiles device_files(&file_system); EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); - std::vector usage_entry_info_list; + std::vector usage_entry_info; CdmUsageTableHeader usage_table_header; bool lru_upgrade; bool has_usage_info_entries; ASSERT_TRUE(device_files.RetrieveUsageTableInfo( - &usage_table_header, &usage_entry_info_list, &lru_upgrade, + &usage_table_header, &usage_entry_info, &lru_upgrade, &has_usage_info_entries)); - EXPECT_EQ(ArraySize(kUsageEntriesWithoutLruData), - usage_entry_info_list.size()); + EXPECT_EQ(ArraySize(kUsageEntriesWithoutLruData), usage_entry_info.size()); for (size_t i = 0; i < ArraySize(kUsageEntriesWithoutLruData); ++i) { const CdmUsageEntryInfo& expected_entry = kUsageEntriesWithoutLruData[i]; - const CdmUsageEntryInfo& retrieved_entry = usage_entry_info_list[i]; + const CdmUsageEntryInfo& retrieved_entry = usage_entry_info[i]; EXPECT_EQ(expected_entry, retrieved_entry); } @@ -4519,21 +4520,20 @@ TEST_F(DeviceFilesUsageTableTest, ReadWithUsageInfoType) { DeviceFiles device_files(&file_system); EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); - std::vector usage_entry_info_list; + std::vector usage_entry_info; CdmUsageTableHeader usage_table_header; bool lru_upgrade; bool has_usage_info_entries; ASSERT_TRUE(device_files.RetrieveUsageTableInfo( - &usage_table_header, &usage_entry_info_list, &lru_upgrade, + &usage_table_header, &usage_entry_info, &lru_upgrade, &has_usage_info_entries)); - EXPECT_EQ(kUsageEntriesWithoutUsageInfoType.size(), - usage_entry_info_list.size()); + EXPECT_EQ(kUsageEntriesWithoutUsageInfoType.size(), usage_entry_info.size()); for (size_t i = 0; i < kUsageEntriesWithoutUsageInfoType.size(); ++i) { const CdmUsageEntryInfo& expected_entry = kUsageEntriesWithoutUsageInfoType[i]; - const CdmUsageEntryInfo& retrieved_entry = usage_entry_info_list[i]; + const CdmUsageEntryInfo& retrieved_entry = usage_entry_info[i]; EXPECT_EQ(expected_entry, retrieved_entry); } diff --git a/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp b/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp index 66f94031..da402682 100644 --- a/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp @@ -71,48 +71,155 @@ const std::string kWrappedPrivateKey = "a wrapped private key"; const CryptoWrappedKey kCryptoWrappedKey(CryptoWrappedKey::kRsa, kWrappedPrivateKey); const CdmUsageEntryInfo kUsageEntryInfoOfflineLicense1 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_1", + /* usage_info_file_name = */ "", /* last_use_time = */ 0, /* offline_license_expiry_time = */ kDefaultExpireDuration}; const CdmUsageEntryInfo kUsageEntryInfoOfflineLicense2 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_2", + /* usage_info_file_name = */ "", /* last_use_time = */ 0, /* offline_license_expiry_time = */ kDefaultExpireDuration}; const CdmUsageEntryInfo kUsageEntryInfoOfflineLicense3 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_3", + /* usage_info_file_name = */ "", /* last_use_time = */ 0, /* offline_license_expiry_time = */ kDefaultExpireDuration}; const CdmUsageEntryInfo kUsageEntryInfoOfflineLicense4 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_4", + /* usage_info_file_name = */ "", /* last_use_time = */ 0, /* offline_license_expiry_time = */ kDefaultExpireDuration}; const CdmUsageEntryInfo kUsageEntryInfoOfflineLicense5 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_5", + /* usage_info_file_name = */ "", /* last_use_time = */ 0, /* offline_license_expiry_time = */ kDefaultExpireDuration}; const CdmUsageEntryInfo kUsageEntryInfoOfflineLicense6 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_6", + /* usage_info_file_name = */ "", /* last_use_time = */ 0, /* offline_license_expiry_time = */ kDefaultExpireDuration}; -const CdmUsageEntryInfo kUsageEntryInfoEmpty = { +const CdmUsageEntryInfo kUsageEntryInfoSecureStop1 = { + /* storage_type = */ kStorageUsageInfo, + /* key_set_id = */ "secure_stop_key_set_1", + /* usage_info_file_name = */ "usage_info_file_1", + /* last_use_time = */ 0, + /* offline_license_expiry_time = */ 0}; +const CdmUsageEntryInfo kUsageEntryInfoSecureStop2 = { + /* storage_type = */ kStorageUsageInfo, + /* key_set_id = */ "secure_stop_key_set_2", + /* usage_info_file_name = */ "usage_info_file_2", + /* last_use_time = */ 0, + /* offline_license_expiry_time = */ 0}; +const CdmUsageEntryInfo kUsageEntryInfoSecureStop3 = { + /* storage_type = */ kStorageUsageInfo, + /* key_set_id = */ "secure_stop_key_set_3", + /* usage_info_file_name = */ "usage_info_file_3", + /* last_use_time = */ 0, + /* offline_license_expiry_time = */ 0}; +const CdmUsageEntryInfo kUsageEntryInfoSecureStop4 = { + /* storage_type = */ kStorageUsageInfo, + /* key_set_id = */ "secure_stop_key_set_4", + /* usage_info_file_name = */ "usage_info_file_4", + /* last_use_time = */ 0, + /* offline_license_expiry_time = */ 0}; +const CdmUsageEntryInfo kUsageEntryInfoSecureStop5 = { + /* storage_type = */ kStorageUsageInfo, + /* key_set_id = */ "secure_stop_key_set_5", + /* usage_info_file_name = */ "usage_info_file_5", + /* last_use_time = */ 0, + /* offline_license_expiry_time = */ 0}; +const CdmUsageEntryInfo kUsageEntryInfoStorageTypeUnknown = { + /* storage_type = */ kStorageTypeUnknown, /* key_set_id = */ "", + /* usage_info_file_name = */ "", /* last_use_time = */ 0, /* offline_license_expiry_time = */ 0}; const CdmUsageEntryInfo kDummyUsageEntryInfo = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "DummyKsid", + /* usage_info_file_name = */ "", /* last_use_time = */ 0, /* offline_license_expiry_time = */ kDefaultExpireDuration}; +const std::vector kEmptyLicenseList; + +const std::string kLicenseArray[] = { + kUsageEntryInfoOfflineLicense1.key_set_id, + kUsageEntryInfoOfflineLicense2.key_set_id, + kUsageEntryInfoOfflineLicense3.key_set_id, +}; +const size_t kLicenseArraySize = wvutil::ArraySize(kLicenseArray); +std::vector kLicenseList; + +const std::vector kEmptyUsageInfoFilesList; + +const std::string kUsageInfoFileArray[] = { + kUsageEntryInfoSecureStop1.usage_info_file_name, + kUsageEntryInfoSecureStop2.usage_info_file_name, + kUsageEntryInfoSecureStop3.usage_info_file_name, +}; +const size_t kUsageInfoFileArraySize = wvutil::ArraySize(kUsageInfoFileArray); +std::vector kUsageInfoFileList; + +const DeviceFiles::CdmUsageData kCdmUsageData1 = { + /* provider_session_token = */ "provider_session_token_1", + /* license_request = */ "license_request_1", + /* license = */ "license_1", + /* key_set_id = */ "key_set_id_1", + /* usage_entry = */ "usage_entry_1", + /* usage_entry_number = */ 0, + /* drm_certificate = */ kDrmCertificate, + /* wrapped_private_key = */ kCryptoWrappedKey, +}; +const DeviceFiles::CdmUsageData kCdmUsageData2 = { + /* provider_session_token = */ "provider_session_token_2", + /* license_request = */ "license_request_2", + /* license = */ "license_2", + /* key_set_id = */ "key_set_id_2", + /* usage_entry = */ "usage_entry_2", + /* usage_entry_number = */ 0, + /* drm_certificate = */ kDrmCertificate, + /* wrapped_private_key = */ kCryptoWrappedKey, +}; +const DeviceFiles::CdmUsageData kCdmUsageData3 = { + /* provider_session_token = */ "provider_session_token_3", + /* license_request = */ "license_request_3", + /* license = */ "license_3", + /* key_set_id = */ "key_set_id_3", + /* usage_entry = */ "usage_entry_3", + /* usage_entry_number = */ 0, + /* drm_certificate = */ kDrmCertificate, + /* wrapped_private_key = */ kCryptoWrappedKey, +}; +const std::vector kEmptyUsageInfoUsageDataList; + const std::vector kEmptyUsageEntryInfoVector; const std::vector kUsageEntryInfoVector = { - kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, - kUsageEntryInfoEmpty}; + kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1, + kUsageEntryInfoStorageTypeUnknown}; +const std::vector k10UsageEntryInfoVector = { + kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1, + kUsageEntryInfoOfflineLicense2, kUsageEntryInfoSecureStop2, + kUsageEntryInfoOfflineLicense3, kUsageEntryInfoSecureStop3, + kUsageEntryInfoOfflineLicense4, kUsageEntryInfoSecureStop4, + kUsageEntryInfoOfflineLicense5, kUsageEntryInfoSecureStop5, +}; const std::vector k5UsageEntryInfoVector = { kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, kUsageEntryInfoOfflineLicense3, kUsageEntryInfoOfflineLicense4, kUsageEntryInfoOfflineLicense5, }; +std::vector kOverFullUsageEntryInfoVector; + const CdmOfflineLicenseState kActiveLicenseState = kLicenseStateActive; const CdmInitData kPsshData = "pssh data"; const CdmKeyMessage kKeyRequest = "key request"; @@ -132,15 +239,21 @@ const CdmUsageTableHeader kUpgradableUsageTableHeader = // Usage entries. const CdmUsageEntryInfo kUpgradableUsageEntryInfo1 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_1", + /* usage_info_file_name = */ "", /* last_use_time = */ 0, /* offline_license_expiry_time = */ 0}; const CdmUsageEntryInfo kUpgradableUsageEntryInfo2 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_2", + /* usage_info_file_name = */ "", /* last_use_time = */ 0, /* offline_license_expiry_time = */ 0}; const CdmUsageEntryInfo kUpgradableUsageEntryInfo3 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_3", + /* usage_info_file_name = */ "", /* last_use_time = */ 0, /* offline_license_expiry_time = */ 0}; const std::vector kUpgradableUsageEntryInfoList{ @@ -189,15 +302,21 @@ const int64_t kUpgradedUsageEntryInfo3ExpireTime = kLruBaseTime + 604800 + 86400; const CdmUsageTableHeader kUpgradedUsageTableHeader = "Upgraded Table Header"; const CdmUsageEntryInfo kUpgradedUsageEntryInfo1 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_1", + /* usage_info_file_name = */ "", /* last_use_time = */ kUpgradedUsageEntryInfo1LastUsedTime, /* offline_license_expiry_time = */ kUpgradedUsageEntryInfo1ExpireTime}; const CdmUsageEntryInfo kUpgradedUsageEntryInfo2 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_2", + /* usage_info_file_name = */ "", /* last_use_time = */ kUpgradedUsageEntryInfo2LastUsedTime, /* offline_license_expiry_time = */ kUpgradedUsageEntryInfo2ExpireTime}; const CdmUsageEntryInfo kUpgradedUsageEntryInfo3 = { + /* storage_type = */ kStorageLicense, /* key_set_id = */ "offline_key_set_3", + /* usage_info_file_name = */ "", /* last_use_time = */ kUpgradedUsageEntryInfo3LastUsedTime, /* offline_license_expiry_time = */ kUpgradedUsageEntryInfo3ExpireTime}; @@ -205,36 +324,11 @@ const std::vector kUpgradedUsageEntryInfoList = { kUpgradedUsageEntryInfo1, kUpgradedUsageEntryInfo2, kUpgradedUsageEntryInfo3}; -std::vector CreateOverFullUsageEntryInfoVector() { - std::vector usage_entry_info_vector; - usage_entry_info_vector.reserve(kDefaultTableCapacity + 1); - for (size_t i = 0; i < (kDefaultTableCapacity + 1); ++i) { - switch (i % 4) { - case 0: - usage_entry_info_vector.push_back(kUsageEntryInfoOfflineLicense1); - break; - case 1: - usage_entry_info_vector.push_back(kUsageEntryInfoOfflineLicense2); - break; - case 2: - usage_entry_info_vector.push_back(kUsageEntryInfoOfflineLicense3); - break; - case 3: - usage_entry_info_vector.push_back(kUsageEntryInfoOfflineLicense4); - break; - default: - usage_entry_info_vector.push_back(kUsageEntryInfoEmpty); - break; - } - } - return usage_entry_info_vector; -} - std::vector CreateUpgradableLicenseInfoList() { std::vector license_data_list; for (size_t i = 0; i < kUpgradableLicenseInfoList.size(); ++i) { DeviceFiles::CdmLicenseData license_data; - license_data.key_set_id = kUpgradableUsageEntryInfoList[i].key_set_id(); + license_data.key_set_id = kUpgradableUsageEntryInfoList[i].key_set_id; license_data.state = kActiveLicenseState; license_data.license = kUpgradableLicenseInfoList[i]; license_data.usage_entry_number = static_cast(i); @@ -243,6 +337,49 @@ std::vector CreateUpgradableLicenseInfoList() { return license_data_list; } +void InitVectorConstants() { + kOverFullUsageEntryInfoVector.clear(); + for (size_t i = 0; i < (kDefaultTableCapacity + 1); ++i) { + switch (i % 4) { + case 0: + kOverFullUsageEntryInfoVector.push_back(kUsageEntryInfoOfflineLicense1); + break; + case 1: + kOverFullUsageEntryInfoVector.push_back(kUsageEntryInfoSecureStop1); + break; + case 2: + kOverFullUsageEntryInfoVector.push_back(kUsageEntryInfoOfflineLicense2); + break; + case 3: + kOverFullUsageEntryInfoVector.push_back(kUsageEntryInfoSecureStop2); + break; + default: + kOverFullUsageEntryInfoVector.push_back( + kUsageEntryInfoStorageTypeUnknown); + break; + } + } + + kUsageInfoFileList.clear(); + for (size_t i = 0; i < kUsageInfoFileArraySize; i++) { + kUsageInfoFileList.push_back(kUsageInfoFileArray[i]); + } + + kLicenseList.clear(); + for (size_t i = 0; i < kLicenseArraySize; i++) { + kLicenseList.push_back(kLicenseArray[i]); + } +} + +void ToVector(std::vector& vec, const CdmUsageEntryInfo* arr, + size_t total_size) { + size_t max = total_size / sizeof(CdmUsageEntryInfo); + vec.clear(); + for (size_t i = 0; i < max; i++) { + vec.push_back(arr[i]); + } +} + class MockDeviceFiles : public DeviceFiles { public: MockDeviceFiles() : DeviceFiles(&file_system_) { Init(kSecurityLevelL1); } @@ -353,6 +490,8 @@ class MockUsageTableHeader : public UsageTableHeader { class UsageTableHeaderTest : public WvCdmTestBase { public: + static void SetUpTestCase() { InitVectorConstants(); } + // Useful when UsageTableHeader is mocked void InvalidateEntry(uint32_t usage_entry_number, bool, DeviceFiles*, metrics::CryptoMetrics*) { @@ -449,13 +588,15 @@ TEST_F(UsageTableHeaderTest, InitError) { EXPECT_FALSE( usage_table_header_->Init(kSecurityLevelUnknown, crypto_session_)); EXPECT_FALSE(usage_table_header_->Init(kSecurityLevelL1, nullptr)); - EXPECT_FALSE(usage_table_header_->Init(kSecurityLevelL3, nullptr)); + EXPECT_FALSE(usage_table_header_->Init(kSecurityLevelL2, nullptr)); } class UsageTableHeaderInitializationTest : public UsageTableHeaderTest, public ::testing::WithParamInterface { public: + static void SetUpTestCase() { InitVectorConstants(); } + RequestedSecurityLevel GetSecurityLevel() const { return (GetParam() == kSecurityLevelL3) ? kLevel3 : kLevelDefault; } @@ -634,8 +775,7 @@ TEST_P(UsageTableHeaderInitializationTest, // Restoring table succeeds, and the current table is at capacity. // No special action needs to be taken. TEST_P(UsageTableHeaderInitializationTest, RestoreUsageTable_AtCapacity) { - std::vector usage_entries = - CreateOverFullUsageEntryInfoVector(); + std::vector usage_entries = kOverFullUsageEntryInfoVector; usage_entries.resize(kDefaultTableCapacity); const RequestedSecurityLevel security_level = GetSecurityLevel(); // Expectations for restore: @@ -661,10 +801,9 @@ TEST_P(UsageTableHeaderInitializationTest, RestoreUsageTable_AtCapacity) { TEST_P(UsageTableHeaderInitializationTest, RestoreUsageTable_NoCapacity_UnderMinimum) { crypto_session_->SetMaximumUsageTableEntries(0); // Unlimited. - std::vector usage_entries = - CreateOverFullUsageEntryInfoVector(); + std::vector usage_entries = kOverFullUsageEntryInfoVector; constexpr size_t kHalfMinCapacity = kDefaultTableCapacity / 2; - usage_entries.resize(kHalfMinCapacity); // Trim to half capacity. + usage_entries.resize(kHalfMinCapacity); const RequestedSecurityLevel security_level = GetSecurityLevel(); // Expectations for restore: // 1) Existing table file is retrieved @@ -691,10 +830,9 @@ TEST_P(UsageTableHeaderInitializationTest, TEST_P(UsageTableHeaderInitializationTest, RestoreUsageTable_NoCapacity_AboveMinimum) { crypto_session_->SetMaximumUsageTableEntries(0); // Unlimited. - const std::vector usage_entries = - CreateOverFullUsageEntryInfoVector(); - ASSERT_LT(kDefaultTableCapacity, usage_entries.size()); - const uint32_t table_start_size = static_cast(usage_entries.size()); + ASSERT_LT(kDefaultTableCapacity, kOverFullUsageEntryInfoVector.size()); + const uint32_t table_start_size = + static_cast(kOverFullUsageEntryInfoVector.size()); const RequestedSecurityLevel security_level = GetSecurityLevel(); // Expectations for restore: @@ -706,8 +844,9 @@ TEST_P(UsageTableHeaderInitializationTest, EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull(), NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<0>(kUsageTableHeader), - SetArgPointee<1>(usage_entries), SetArgPointee<2>(false), - SetArgPointee<3>(false), Return(true))); + SetArgPointee<1>(kOverFullUsageEntryInfoVector), + SetArgPointee<2>(false), SetArgPointee<3>(false), + Return(true))); EXPECT_CALL(*crypto_session_, LoadUsageTableHeader(security_level, kUsageTableHeader)) .WillOnce(Return(NO_ERROR)); @@ -751,9 +890,7 @@ TEST_P(UsageTableHeaderInitializationTest, // The result is a new usage table. TEST_P(UsageTableHeaderInitializationTest, RestoreUsageTable_AboveCapacity_AddEntryFails) { - const std::vector usage_entries = - CreateOverFullUsageEntryInfoVector(); - ASSERT_LT(kDefaultTableCapacity, usage_entries.size()); + ASSERT_LT(kDefaultTableCapacity, kOverFullUsageEntryInfoVector.size()); const RequestedSecurityLevel security_level = GetSecurityLevel(); // Expectations for restore: @@ -765,8 +902,9 @@ TEST_P(UsageTableHeaderInitializationTest, EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull(), NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<0>(kUsageTableHeader), - SetArgPointee<1>(usage_entries), SetArgPointee<2>(false), - SetArgPointee<3>(false), Return(true))); + SetArgPointee<1>(kOverFullUsageEntryInfoVector), + SetArgPointee<2>(false), SetArgPointee<3>(false), + Return(true))); EXPECT_CALL(*crypto_session_, LoadUsageTableHeader(security_level, kUsageTableHeader)) .WillOnce(Return(NO_ERROR)); @@ -803,10 +941,9 @@ TEST_P(UsageTableHeaderInitializationTest, TEST_P(UsageTableHeaderInitializationTest, RestoreUsageTable_NoCapacity_AboveMinimum_InvalidateEntryFails) { crypto_session_->SetMaximumUsageTableEntries(0); // Unlimited. - const std::vector usage_entries = - CreateOverFullUsageEntryInfoVector(); - ASSERT_LT(kDefaultTableCapacity, usage_entries.size()); - const uint32_t table_start_size = static_cast(usage_entries.size()); + ASSERT_LT(kDefaultTableCapacity, kOverFullUsageEntryInfoVector.size()); + const uint32_t table_start_size = + static_cast(kOverFullUsageEntryInfoVector.size()); const RequestedSecurityLevel security_level = GetSecurityLevel(); // Expectations for restore: @@ -818,8 +955,9 @@ TEST_P(UsageTableHeaderInitializationTest, EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull(), NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<0>(kUsageTableHeader), - SetArgPointee<1>(usage_entries), SetArgPointee<2>(false), - SetArgPointee<3>(false), Return(true))); + SetArgPointee<1>(kOverFullUsageEntryInfoVector), + SetArgPointee<2>(false), SetArgPointee<3>(false), + Return(true))); EXPECT_CALL(*crypto_session_, LoadUsageTableHeader(security_level, kUsageTableHeader)) .WillOnce(Return(NO_ERROR)); @@ -905,16 +1043,11 @@ TEST_F(UsageTableHeaderTest, AddEntry_CreateUsageEntryFailed_UnknownError) { uint32_t usage_entry_number = 0; EXPECT_NE(NO_ERROR, usage_table_header_->AddEntry( - crypto_session_, kUsageEntryInfoOfflineLicense1.key_set_id(), + crypto_session_, kUsageEntryInfoOfflineLicense1.key_set_id, kEmptyString /* license */, &usage_entry_number)); } -// Attempt to create a new entry; however, OEMCrypto returns a usage -// entry number that is smaller than the current table size. -// -// The CDM policy is to drop the new entry. If a later issue arises -// from the entry in that spot, that failure will be handled separately. -TEST_F(UsageTableHeaderTest, AddEntry_UsageEntryNumberTooSmall) { +TEST_F(UsageTableHeaderTest, AddEntry_UsageEntryTooSmall) { Init(kSecurityLevelL1, kUsageTableHeader, kUsageEntryInfoVector); const uint32_t expect_usage_entry_number = static_cast(kUsageEntryInfoVector.size()) - 1; @@ -925,7 +1058,7 @@ TEST_F(UsageTableHeaderTest, AddEntry_UsageEntryNumberTooSmall) { uint32_t usage_entry_number = 0; EXPECT_NE(NO_ERROR, usage_table_header_->AddEntry( - crypto_session_, kUsageEntryInfoOfflineLicense1.key_set_id(), + crypto_session_, kUsageEntryInfoOfflineLicense1.key_set_id, kEmptyString /* license */, &usage_entry_number)); } @@ -940,18 +1073,18 @@ TEST_F(UsageTableHeaderTest, AddEntry_UsageEntryNumberTooSmall) { // c. Shrink table to remove the now empty entry slot created in (a) // d. Storing the new updated usage table // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== // Offline License 1 0 0 -// Offline License 2 1 1 -// Clear entry 2 Replaced -// Offline License 3 DNE 2 +// Secure Stop 1 1 1 +// Storage Type Unknown 2 Replaced +// Offline License 2 DNE 2 // // DNE = Does Not Exist // // # of usage entries 3 3 -TEST_F(UsageTableHeaderTest, AddEntry_NextConsecutiveUsageEntry) { +TEST_F(UsageTableHeaderTest, AddEntry_NextConsecutiveOfflineUsageEntry) { Init(kSecurityLevelL1, kUsageTableHeader, kUsageEntryInfoVector); const uint32_t initial_usage_entry_number = static_cast(kUsageEntryInfoVector.size()); @@ -960,15 +1093,12 @@ TEST_F(UsageTableHeaderTest, AddEntry_NextConsecutiveUsageEntry) { std::vector expect_usage_entry_info_vector = kUsageEntryInfoVector; expect_usage_entry_info_vector[final_usage_entry_number] = - kUsageEntryInfoOfflineLicense3; - // Expectations for new creating entry. + kUsageEntryInfoOfflineLicense2; EXPECT_CALL(*crypto_session_, CreateUsageEntry(NotNull())) .WillOnce(DoAll(SetArgPointee<0>(initial_usage_entry_number), Return(NO_ERROR))); - // Expectations for moving the new entry into slot 2. EXPECT_CALL(*crypto_session_, MoveUsageEntry(final_usage_entry_number)) .WillOnce(Return(NO_ERROR)); - // Expectations for resizing the table. EXPECT_CALL(*crypto_session_, ShrinkUsageTableHeader( kLevelDefault, @@ -987,7 +1117,7 @@ TEST_F(UsageTableHeaderTest, AddEntry_NextConsecutiveUsageEntry) { uint32_t usage_entry_number = 0; EXPECT_EQ(NO_ERROR, usage_table_header_->AddEntry( - crypto_session_, kUsageEntryInfoOfflineLicense3.key_set_id(), + crypto_session_, kUsageEntryInfoOfflineLicense2.key_set_id, kEmptyString /* license */, &usage_entry_number)); EXPECT_EQ(final_usage_entry_number, usage_entry_number); } @@ -1006,16 +1136,16 @@ TEST_F(UsageTableHeaderTest, AddEntry_NextConsecutiveUsageEntry) { // and the filler gap entries created in (b) // e. Storing the new updated usage table // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== // Offline License 1 0 0 -// Offline License 2 1 1 -// Clear entry 2 Replaced -// Non-existing entry DNE Removed (never stored) -// Non-existing entry DNE Removed (never stored) -// Non-existing entry DNE Removed (never stored) -// Offline License 3 DNE 2 +// Secure Stop 1 1 1 +// Storage Type Unknown 2 Replaced +// Storage Type Unknown DNE Removed (never stored) +// Storage Type Unknown DNE Removed (never stored) +// Storage Type Unknown DNE Removed (never stored) +// Offline License 2 DNE 2 // // DNE = Does Not Exist // @@ -1032,16 +1162,11 @@ TEST_F(UsageTableHeaderTest, AddEntry_SkipUsageEntries) { std::vector expect_usage_entry_info_vector = kUsageEntryInfoVector; expect_usage_entry_info_vector[final_usage_entry_number] = - kUsageEntryInfoOfflineLicense3; + kUsageEntryInfoOfflineLicense2; - // Expectations for creating new entry. The returned entry number - // is much larger than what is normally expected (one past the end - // of the table). EXPECT_CALL(*crypto_session_, CreateUsageEntry(NotNull())) .WillOnce(DoAll(SetArgPointee<0>(initial_usage_entry_number), Return(NO_ERROR))); - // Expectation that the table will attempt to move the new entry - // to available clear entry at the end of the table. EXPECT_CALL(*crypto_session_, MoveUsageEntry(final_usage_entry_number)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*crypto_session_, @@ -1062,7 +1187,7 @@ TEST_F(UsageTableHeaderTest, AddEntry_SkipUsageEntries) { uint32_t usage_entry_number = 0; EXPECT_EQ(NO_ERROR, usage_table_header_->AddEntry( - crypto_session_, kUsageEntryInfoOfflineLicense3.key_set_id(), + crypto_session_, kUsageEntryInfoOfflineLicense2.key_set_id, kEmptyString /* license */, &usage_entry_number)); EXPECT_EQ(final_usage_entry_number, usage_entry_number); } @@ -1078,13 +1203,13 @@ TEST_F(UsageTableHeaderTest, AddEntry_SkipUsageEntries) { // due to entry being in use (according to OEMCrypto) // c. Storing the new updated usage table // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== // Offline License 1 0 0 -// Offline License 2 1 1 -// Clear entry 2 2 -// Offline License 3 DNE 3 +// Secure Stop 1 1 1 +// Storage Type Unknown 2 2 +// Offline License 2 DNE 3 // // DNE = Does Not Exist // @@ -1097,13 +1222,11 @@ TEST_F(UsageTableHeaderTest, AddEntry_CannotMoveNewEntry) { static_cast(kUsageEntryInfoVector.size()) - 1; std::vector expect_usage_entry_info_vector = kUsageEntryInfoVector; - expect_usage_entry_info_vector.push_back(kUsageEntryInfoOfflineLicense3); + expect_usage_entry_info_vector.push_back(kUsageEntryInfoOfflineLicense2); EXPECT_CALL(*crypto_session_, CreateUsageEntry(NotNull())) .WillOnce( DoAll(SetArgPointee<0>(final_usage_entry_number), Return(NO_ERROR))); - // Expectations for table attempting the move new entry into the - // clear entry slot. However, this move will fail. EXPECT_CALL(*crypto_session_, MoveUsageEntry(attempted_usage_entry_number)) .WillOnce(Return(MOVE_USAGE_ENTRY_DESTINATION_IN_USE)); EXPECT_CALL(*crypto_session_, UpdateUsageEntry(NotNull(), NotNull())) @@ -1117,7 +1240,7 @@ TEST_F(UsageTableHeaderTest, AddEntry_CannotMoveNewEntry) { uint32_t usage_entry_number = 0; EXPECT_EQ(NO_ERROR, usage_table_header_->AddEntry( - crypto_session_, kUsageEntryInfoOfflineLicense3.key_set_id(), + crypto_session_, kUsageEntryInfoOfflineLicense2.key_set_id, kEmptyString /* license */, &usage_entry_number)); EXPECT_EQ(final_usage_entry_number, usage_entry_number); } @@ -1133,14 +1256,14 @@ TEST_F(UsageTableHeaderTest, AddEntry_CannotMoveNewEntry) { // c. Fail to shrink table due to occupied entry // d. Storing the new updated usage table // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== // Offline License 1 0 0 -// Offline License 2 1 1 -// Clear entry 2 Replaced -// Offline License 3 DNE 2 -// Clear entry DNE 3 (created when new entry moved) +// Secure Stop 1 1 1 +// Storage Type Unknown 2 Replaced +// Offline License 2 DNE 2 +// Storage Type Unknown DNE 3 (created when new entry moved) // // DNE = Does Not Exist // @@ -1154,17 +1277,14 @@ TEST_F(UsageTableHeaderTest, AddEntry_CannotShinkAfterMove) { std::vector expect_usage_entry_info_vector = kUsageEntryInfoVector; expect_usage_entry_info_vector[final_usage_entry_number] = - kUsageEntryInfoOfflineLicense3; - expect_usage_entry_info_vector.push_back(kUsageEntryInfoEmpty); + kUsageEntryInfoOfflineLicense2; + expect_usage_entry_info_vector.push_back(kUsageEntryInfoStorageTypeUnknown); EXPECT_CALL(*crypto_session_, CreateUsageEntry(NotNull())) .WillOnce(DoAll(SetArgPointee<0>(initial_usage_entry_number), Return(NO_ERROR))); - // Expectation for moving new entry into empty entry slot. EXPECT_CALL(*crypto_session_, MoveUsageEntry(final_usage_entry_number)) .WillOnce(Return(NO_ERROR)); - // Expectations that shrinking the table will fail. UsageTableHeader - // will keep an empty entry at the end of the table. EXPECT_CALL( *crypto_session_, ShrinkUsageTableHeader( @@ -1183,7 +1303,7 @@ TEST_F(UsageTableHeaderTest, AddEntry_CannotShinkAfterMove) { uint32_t usage_entry_number = 0; EXPECT_EQ(NO_ERROR, usage_table_header_->AddEntry( - crypto_session_, kUsageEntryInfoOfflineLicense3.key_set_id(), + crypto_session_, kUsageEntryInfoOfflineLicense2.key_set_id, kEmptyString /* license */, &usage_entry_number)); EXPECT_EQ(final_usage_entry_number, usage_entry_number); } @@ -1204,12 +1324,14 @@ TEST_F(UsageTableHeaderTest, AddEntry_CreateUsageEntryFailsOnce_SucceedsSecondTime) { // Initialize and setup MockUsageTableHeader* mock_usage_table_header = SetUpMock(); - Init(kSecurityLevelL1, kUsageTableHeader, k5UsageEntryInfoVector); + Init(kSecurityLevelL1, kUsageTableHeader, k10UsageEntryInfoVector); + std::vector usage_entry_info_vector_at_start = + k10UsageEntryInfoVector; uint32_t invalidated_entry = 0; // Randomly chosen by UsageTableHeader const uint32_t expected_usage_entry_number = - static_cast(k5UsageEntryInfoVector.size()) - 1; + static_cast(k10UsageEntryInfoVector.size()) - 1; EXPECT_CALL(*crypto_session_, CreateUsageEntry(NotNull())) // First call fails @@ -1235,17 +1357,17 @@ TEST_F(UsageTableHeaderTest, uint32_t usage_entry_number = 0; EXPECT_EQ(NO_ERROR, mock_usage_table_header->SuperAddEntry( - crypto_session_, kUsageEntryInfoOfflineLicense6.key_set_id(), + crypto_session_, kUsageEntryInfoOfflineLicense6.key_set_id, kEmptyString /* license */, &usage_entry_number)); // Verify added/deleted usage entry number and entries EXPECT_EQ(expected_usage_entry_number, usage_entry_number); EXPECT_LE(0u, invalidated_entry); - EXPECT_LE(invalidated_entry, k5UsageEntryInfoVector.size() - 1); + EXPECT_LE(invalidated_entry, k10UsageEntryInfoVector.size() - 1); std::vector expected_usage_entries = - k5UsageEntryInfoVector; + k10UsageEntryInfoVector; expected_usage_entries[invalidated_entry] = expected_usage_entries.back(); expected_usage_entries.pop_back(); @@ -1258,7 +1380,7 @@ TEST_F(UsageTableHeaderTest, TEST_F(UsageTableHeaderTest, AddEntry_CreateUsageEntryFailsEveryTime) { // Initialize and setup MockUsageTableHeader* mock_usage_table_header = SetUpMock(); - Init(kSecurityLevelL1, kUsageTableHeader, k5UsageEntryInfoVector); + Init(kSecurityLevelL1, kUsageTableHeader, k10UsageEntryInfoVector); // Setup expectations EXPECT_CALL(*mock_usage_table_header, @@ -1274,17 +1396,17 @@ TEST_F(UsageTableHeaderTest, AddEntry_CreateUsageEntryFailsEveryTime) { uint32_t usage_entry_number; EXPECT_EQ(INSUFFICIENT_CRYPTO_RESOURCES, mock_usage_table_header->SuperAddEntry( - crypto_session_, kUsageEntryInfoOfflineLicense6.key_set_id(), + crypto_session_, kUsageEntryInfoOfflineLicense6.key_set_id, kEmptyString /* license */, &usage_entry_number)); // Verify the number of entries deleted. constexpr uint32_t kExpectedEntriesDeleted = 1; const std::vector& final_usage_entries = - mock_usage_table_header->entry_info_list(); + mock_usage_table_header->usage_entry_info(); uint32_t invalid_entries = 0; for (const CdmUsageEntryInfo& usage_entry_info : final_usage_entries) { - if (usage_entry_info.IsEmpty()) { + if (usage_entry_info.storage_type == kStorageTypeUnknown) { ++invalid_entries; } } @@ -1292,7 +1414,7 @@ TEST_F(UsageTableHeaderTest, AddEntry_CreateUsageEntryFailsEveryTime) { // marked as invalid plus the number of fewer entries in the table // at the end of the call. const uint32_t entries_deleted = - invalid_entries + static_cast(k5UsageEntryInfoVector.size() - + invalid_entries + static_cast(k10UsageEntryInfoVector.size() - final_usage_entries.size()); EXPECT_EQ(kExpectedEntriesDeleted, entries_deleted); } @@ -1375,45 +1497,46 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_InvalidUsageEntryNumber) { // will occur. // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. The usage table will be requested to shrink both the last entry // and the unknown entry before it. // c. OEMCrypto error will cause the internal entries to remain the // same. -// d. InvalidateEntry() will return NO_ERROR as the entry was cleared. +// d. InvalidateEntry() will return NO_ERROR as the storage type is +// changed. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== // Offline License 1 0 0 -// Offline License 2 1 1 -// Clear entry 2 2 -// Offline License 3 3 3 (Cleared) +// Secure Stop 1 1 1 +// Storage Type Unknown 2 2 +// Offline License 2 3 3 (Storage Type Unknown) // // # of usage entries 4 4 TEST_F(UsageTableHeaderTest, InvalidateEntry_CryptoSessionError) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, - kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense3}; + kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1, + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense2}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = - 3; // kUsageEntryInfoOfflineLicense3 + 3; // kUsageEntryInfoOfflineLicense2 metrics::CryptoMetrics metrics; - // Error when shrinking the table. EXPECT_CALL(*crypto_session_, ShrinkUsageTableHeader(kLevelDefault, 2, NotNull())) .WillOnce(Return(SHRINK_USAGE_TABLE_HEADER_UNKNOWN_ERROR)); // Regardless, the usage table should be updated to reflect the changes - // to the usage entry that was cleared. - EXPECT_CALL(*device_files_, - StoreUsageTableInfo( - kUsageTableHeader, - ElementsAre(kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoOfflineLicense2, - kUsageEntryInfoEmpty, kUsageEntryInfoEmpty))) + // to the usage entry marked as storage type unknown. + EXPECT_CALL( + *device_files_, + StoreUsageTableInfo(kUsageTableHeader, + ElementsAre(kUsageEntryInfoOfflineLicense1, + kUsageEntryInfoSecureStop1, + kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown))) .WillOnce(Return(true)); EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry( @@ -1421,35 +1544,35 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_CryptoSessionError) { &metrics)); // Check that the list is unchanged. constexpr size_t expected_size = 4; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } // Initial Test state: // 1. Entry to be deleted is the last entry and is an offline license. // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. Usage table will be resized to remove the last two entries. // c. Updated table will be saved. // d. InvalidateEntry() will return NO_ERROR. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== // Offline License 1 0 0 -// Offline License 2 1 1 -// Clear entry 2 Deleted -// Offline License 3 3 Deleted +// Secure Stop 1 1 1 +// Storage Type Unknown 2 Deleted +// Offline License 2 3 Deleted // // # of usage entries 4 2 -TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntry) { +TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntry_OfflineEntry) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, - kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense3}; + kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1, + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense2}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = - 3; // kUsageEntryInfoOfflineLicense3 + 3; // kUsageEntryInfoOfflineLicense2 metrics::CryptoMetrics metrics; // Expectations for call to shrink. @@ -1461,7 +1584,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntry) { EXPECT_CALL(*device_files_, StoreUsageTableInfo(kAnotherUsageTableHeader, ElementsAre(kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoOfflineLicense2))) + kUsageEntryInfoSecureStop1))) .WillOnce(Return(true)); EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry( @@ -1469,7 +1592,55 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntry) { &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 2; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); +} + +// Initial Test state: +// 1. Entry to be deleted is the last entry and is a secure stop. +// +// Attempting to delete the entry in (1) will result in: +// a. The entry will be marked as kStorageTypeUnknown. +// b. Usage table will be resized to remove the last two entries. +// c. Updated table will be saved. +// d. InvalidateEntry() will return NO_ERROR. +// +// Storage type Usage entries +// at start at end +// ============= ======== ====== +// Offline License 1 0 0 +// Secure Stop 1 1 1 +// Storage Type Unknown 2 Deleted +// Secure Stop 2 3 Deleted +// +// # of usage entries 4 2 +TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntry_SecureStopEntry) { + const std::vector usage_entry_info_vector = { + kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1, + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoSecureStop2}; + + Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); + const uint32_t usage_entry_number_to_be_deleted = + 3; // kUsageEntryInfoSecureStop2 + metrics::CryptoMetrics metrics; + + // Expectation when shrinking table. + EXPECT_CALL(*crypto_session_, + ShrinkUsageTableHeader(kLevelDefault, 2, NotNull())) + .WillOnce( + DoAll(SetArgPointee<2>(kAnotherUsageTableHeader), Return(NO_ERROR))); + + EXPECT_CALL(*device_files_, + StoreUsageTableInfo(kAnotherUsageTableHeader, + ElementsAre(kUsageEntryInfoOfflineLicense1, + kUsageEntryInfoSecureStop1))) + .WillOnce(Return(true)); + + EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry( + usage_entry_number_to_be_deleted, true, device_files_, + &metrics)); + // Check the end state of the usage table. + constexpr size_t expected_size = 2; + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } // Initial Test state: @@ -1478,21 +1649,21 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntry) { // 2. Usage entry to be deleted precedes those in (1). // // Attempting to delete the entry in (2) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. While defragging, the last two entries will be selected to // move. // c. Getting the usage entry for the selected entries will fail and -// result in them being cleared. +// result in them being set as kStorageTypeUnknown. // d. No entries will be moved due to (c). // e. Usage table will be resized to have only one entry. // f. Updated table will be saved. // g. InvalidateEntry() will return NO_ERROR. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== -// Offline License 4 0 0 -// Clear entry 1 Deleted +// Secure Stop 1 0 0 +// Storage Type Unknown 1 Deleted // Offline License 1 2 Deleted // Offline License 2 3 Deleted (because missing) // Offline License 3 4 Deleted (because missing) @@ -1501,7 +1672,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntry) { TEST_F(UsageTableHeaderTest, InvalidateEntry_LastOfflineEntriesHaveMissingLicenses) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoOfflineLicense4, kUsageEntryInfoEmpty, + kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, kUsageEntryInfoOfflineLicense3}; @@ -1512,11 +1683,11 @@ TEST_F(UsageTableHeaderTest, // Offline license 2 and 3 cannot be retrieved. EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id, NotNull(), NotNull())) .WillOnce(Return(false)); EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id, NotNull(), NotNull())) .WillOnce(Return(false)); @@ -1528,7 +1699,7 @@ TEST_F(UsageTableHeaderTest, EXPECT_CALL(*device_files_, StoreUsageTableInfo(kAnotherUsageTableHeader, - ElementsAre(kUsageEntryInfoOfflineLicense4))) + ElementsAre(kUsageEntryInfoSecureStop1))) .WillOnce(Return(true)); EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry( @@ -1536,7 +1707,7 @@ TEST_F(UsageTableHeaderTest, &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 1; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } // Initial Test state: @@ -1545,31 +1716,31 @@ TEST_F(UsageTableHeaderTest, // 2. Usage entry to be deleted precedes those in (1). // // Attempting to delete the entry in (2) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. While defragging, the last two entries will be selected to // move. // c. Getting the usage entry for the selected entries will fail due -// to a mismatch in usage entry number and result in them being -// cleared. +// to a mismatch in usage entry number and result in them being set +// as kStorageTypeUnknown. // d. No entries will be moved due to (c). // e. Usage table will be resized to have only one entry. // f. Updated table will be saved. // g. InvalidateEntry() will return NO_ERROR. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== -// Offline License 4 0 0 -// Clear entry 1 Deleted +// Secure Stop 1 0 0 +// Storage Type Unknown 1 Deleted // Offline License 1 2 Deleted // Offline License 2 3 Deleted (because incorrect #) // Offline License 3 4 Deleted (because incorrect #) // // # of usage entries 5 1 TEST_F(UsageTableHeaderTest, - InvalidateEntry_LastEntriesHaveIncorrectUsageEntryNumber) { + InvalidateEntry_LastOfflineEntriesHaveIncorrectUsageEntryNumber) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoOfflineLicense4, kUsageEntryInfoEmpty, + kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, kUsageEntryInfoOfflineLicense3}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); @@ -1579,7 +1750,7 @@ TEST_F(UsageTableHeaderTest, // Set offline license file data with mismatched usage entry numbers. const DeviceFiles::CdmLicenseData offline_license_3_data{ - kUsageEntryInfoOfflineLicense3.key_set_id(), + kUsageEntryInfoOfflineLicense3.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -1596,12 +1767,12 @@ TEST_F(UsageTableHeaderTest, kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id, NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<1>(offline_license_3_data), Return(true))); const DeviceFiles::CdmLicenseData offline_license_2_data{ - kUsageEntryInfoOfflineLicense2.key_set_id(), + kUsageEntryInfoOfflineLicense2.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -1618,7 +1789,7 @@ TEST_F(UsageTableHeaderTest, kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id, NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<1>(offline_license_2_data), Return(true))); @@ -1629,7 +1800,7 @@ TEST_F(UsageTableHeaderTest, DoAll(SetArgPointee<2>(kAnotherUsageTableHeader), Return(NO_ERROR))); EXPECT_CALL(*device_files_, StoreUsageTableInfo(kAnotherUsageTableHeader, - ElementsAre(kUsageEntryInfoOfflineLicense4))) + ElementsAre(kUsageEntryInfoSecureStop1))) .WillOnce(Return(true)); EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry( @@ -1637,15 +1808,15 @@ TEST_F(UsageTableHeaderTest, &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 1; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } // Initial Test state: -// 1. Last few entries are clear. +// 1. Last few entries are of storage type unknown. // 2. Usage entry to be deleted precedes those in (1). // // Attempting to delete the entry in (2) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. While defragging, offline license 2 will be selected to be // moved. // c. The selected entry will have the usage entry loaded from device @@ -1657,27 +1828,24 @@ TEST_F(UsageTableHeaderTest, // g. Updated table will be saved. // h. InvalidateEntry() will return NO_ERROR. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== -// Offline License 4 0 0 -// Clear entry 1 Deleted +// Secure Stop 1 0 0 +// Storage Type Unknown 1 Deleted // Offline License 1 2 2 // Offline License 2 3 1 (Moved) // Offline License 3 4 Deleted -// Clear entry 5 Deleted -// Clear entry 6 Deleted +// Storage Type Unknown 5 Deleted +// Storage Type Unknown 6 Deleted // // # of usage entries 7 3 -TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreClear) { +TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreStorageTypeUnknown) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoOfflineLicense4, - kUsageEntryInfoEmpty, - kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoOfflineLicense2, - kUsageEntryInfoOfflineLicense3, - kUsageEntryInfoEmpty, - kUsageEntryInfoEmpty}; + kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, + kUsageEntryInfoOfflineLicense3, kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = @@ -1686,7 +1854,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreClear) { // Expect calls for moving offline license 2 (position 3) to position 1. const DeviceFiles::CdmLicenseData offline_license_2_data{ - kUsageEntryInfoOfflineLicense2.key_set_id(), + kUsageEntryInfoOfflineLicense2.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -1703,7 +1871,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreClear) { kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id, NotNull(), NotNull())) .Times(2) // First to get entry, then again to update. .WillRepeatedly( @@ -1729,7 +1897,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreClear) { EXPECT_CALL(*device_files_, StoreUsageTableInfo(kAnotherUsageTableHeader, - ElementsAre(kUsageEntryInfoOfflineLicense4, + ElementsAre(kUsageEntryInfoSecureStop1, kUsageEntryInfoOfflineLicense2, kUsageEntryInfoOfflineLicense1))) .WillOnce(Return(true)); @@ -1739,7 +1907,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreClear) { &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 3; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } // Initial Test state: @@ -1748,7 +1916,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreClear) { // OEMCrypto_MoveUsageEntry on it will fail. // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. While defragging, offline license 3 will be selected to be // moved. // c. The selected entry will have the usage entry loaded from device @@ -1759,12 +1927,12 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreClear) { // f. Updated table will be saved. // g. InvalidateEntry() will return NO_ERROR. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== -// Offline License 4 0 0 -// Offline License 5 1 1 -// Offline License 1 2 2 (cleared) +// Secure Stop 1 0 0 +// Secure Stop 2 1 1 +// Offline License 1 2 2 (storage type unknown) // Offline License 2 3 3 // Offline License 3 4 4 // @@ -1772,7 +1940,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreClear) { TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntryIsOffline_MoveOfflineEntryFailed) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoOfflineLicense4, kUsageEntryInfoOfflineLicense5, + kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2, kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, kUsageEntryInfoOfflineLicense3}; @@ -1784,7 +1952,7 @@ TEST_F(UsageTableHeaderTest, // Expect calls for moving offline license 3 (position 4), but // failure to move will not result in any calls for updating. const DeviceFiles::CdmLicenseData offline_license_3_data{ - kUsageEntryInfoOfflineLicense3.key_set_id(), + kUsageEntryInfoOfflineLicense3.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -1801,7 +1969,7 @@ TEST_F(UsageTableHeaderTest, kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id, NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<1>(offline_license_3_data), Return(true))); @@ -1813,12 +1981,12 @@ TEST_F(UsageTableHeaderTest, // No calls to shrink are expected. // Regardless, the usage table should be updated to reflect the changes - // to the usage entry cleared. + // to the usage entry marked as storage type unknown. EXPECT_CALL(*device_files_, StoreUsageTableInfo(kUsageTableHeader, - ElementsAre(kUsageEntryInfoOfflineLicense4, - kUsageEntryInfoOfflineLicense5, - kUsageEntryInfoEmpty, + ElementsAre(kUsageEntryInfoSecureStop1, + kUsageEntryInfoSecureStop2, + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense2, kUsageEntryInfoOfflineLicense3))) .WillOnce(Return(true)); @@ -1828,17 +1996,17 @@ TEST_F(UsageTableHeaderTest, &metrics)); // Check that the table has been updated as expected. constexpr size_t expected_size = 5; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } // Initial Test state: // 1. Usage entry to be deleted is not last (Offline license 1) -// 2. Last few entries are clear. +// 2. Last few entries are of storage type unknown. // 3. Entry that precedes those in (2) are offline license and calling // OEMCrypto_LoadUsageEntry on it will fail. // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. While defragging, offline licenses 2 and 3 will be selected to be // moved. // c. The selected entry will have the usage entry loaded from device @@ -1849,28 +2017,25 @@ TEST_F(UsageTableHeaderTest, // f. Updated table will be saved. // g. InvalidateEntry() will return NO_ERROR. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== -// Offline License 4 0 0 -// Clear entry 1 1 -// Offline License 1 2 2 (cleared) +// Secure Stop 1 0 0 +// Storage Type Unknown 1 1 +// Offline License 1 2 2 (storage type unknown) // Offline License 2 3 3 // Offline License 3 4 4 -// Clear entry 5 Deleted -// Clear entry 6 Deleted +// Storage Type Unknown 5 Deleted +// Storage Type Unknown 6 Deleted // // # of usage entries 7 5 TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreOfflineAndUnknown_MoveOfflineEntryFailed) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoOfflineLicense4, - kUsageEntryInfoEmpty, - kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoOfflineLicense2, - kUsageEntryInfoOfflineLicense3, - kUsageEntryInfoEmpty, - kUsageEntryInfoEmpty}; + kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, + kUsageEntryInfoOfflineLicense3, kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = @@ -1884,7 +2049,7 @@ TEST_F(UsageTableHeaderTest, // Expect calls for moving offline license 3 (position 4), but // failure to move will not result in any calls for updating. const DeviceFiles::CdmLicenseData offline_license_3_data{ - kUsageEntryInfoOfflineLicense3.key_set_id(), + kUsageEntryInfoOfflineLicense3.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -1901,7 +2066,7 @@ TEST_F(UsageTableHeaderTest, kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id, NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<1>(offline_license_3_data), Return(true))); EXPECT_CALL(*crypto_session_, LoadUsageEntry(4, kUsageEntry)) @@ -1910,7 +2075,7 @@ TEST_F(UsageTableHeaderTest, // Expect calls for moving offline license 2 (position 3), but // failure to move will not result in any calls for updating. const DeviceFiles::CdmLicenseData offline_license_2_data{ - kUsageEntryInfoOfflineLicense2.key_set_id(), + kUsageEntryInfoOfflineLicense2.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -1927,28 +2092,28 @@ TEST_F(UsageTableHeaderTest, kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id, NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<1>(offline_license_2_data), Return(true))); EXPECT_CALL(*crypto_session_, LoadUsageEntry(3, kUsageEntry)) .WillOnce(Return(LOAD_USAGE_ENTRY_INVALID_SESSION)); - // Expect a call to shrink table to cut off only the clear entries + // Expect a call to shrink table to cut off only the unknown entries // at the end of the table. EXPECT_CALL(*crypto_session_, ShrinkUsageTableHeader(kLevelDefault, 5, NotNull())) .WillOnce( DoAll(SetArgPointee<2>(kAnotherUsageTableHeader), Return(NO_ERROR))); - // Update table for the entry now cleared and the entries that - // were cut off. - EXPECT_CALL( - *device_files_, - StoreUsageTableInfo( - kAnotherUsageTableHeader, - ElementsAre(kUsageEntryInfoOfflineLicense4, kUsageEntryInfoEmpty, - kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense2, - kUsageEntryInfoOfflineLicense3))) + // Update table for the entry now marked storage type unknown and + // the entries that were cut off. + EXPECT_CALL(*device_files_, + StoreUsageTableInfo(kAnotherUsageTableHeader, + ElementsAre(kUsageEntryInfoSecureStop1, + kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoOfflineLicense2, + kUsageEntryInfoOfflineLicense3))) .WillOnce(Return(true)); EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry( @@ -1956,7 +2121,7 @@ TEST_F(UsageTableHeaderTest, &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 5; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } // Initial Test state: @@ -1964,7 +2129,7 @@ TEST_F(UsageTableHeaderTest, // 2. Last entries are valid offline licenses. // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. While defragging, offline licenses 2 and 3 will be selected to be // moved. // c. The selected entries will be moved. @@ -1972,11 +2137,11 @@ TEST_F(UsageTableHeaderTest, // e. Updated table will be saved. // f. InvalidateEntry() will return NO_ERROR. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== -// Offline License 4 0 0 -// Clear entry 1 Deleted +// Secure Stop 1 0 0 +// Storage Type unknown 1 Deleted // Offline License 1 2 Deleted // Offline License 2 3 2 (moved) // Offline License 3 4 1 (moved) @@ -1984,7 +2149,7 @@ TEST_F(UsageTableHeaderTest, // # of usage entries 5 3 TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntryIsOffline) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoOfflineLicense4, kUsageEntryInfoEmpty, + kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, kUsageEntryInfoOfflineLicense3}; @@ -1995,7 +2160,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntryIsOffline) { // Expect calls for moving offline license 3 (position 4) to position 1. const DeviceFiles::CdmLicenseData offline_license_3_data{ - kUsageEntryInfoOfflineLicense3.key_set_id(), + kUsageEntryInfoOfflineLicense3.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -2012,7 +2177,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntryIsOffline) { kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id, NotNull(), NotNull())) .Times(2) // First to get entry, then again to update. .WillRepeatedly( @@ -2023,7 +2188,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntryIsOffline) { // Expect calls for moving offline license 2 (position 3) to position 2. const DeviceFiles::CdmLicenseData offline_license_2_data{ - kUsageEntryInfoOfflineLicense2.key_set_id(), + kUsageEntryInfoOfflineLicense2.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -2040,7 +2205,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntryIsOffline) { kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id, NotNull(), NotNull())) .Times(2) // First to get entry, then again to update. .WillRepeatedly( @@ -2072,7 +2237,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntryIsOffline) { DoAll(SetArgPointee<2>(kYetAnotherUsageEntry), Return(NO_ERROR))); EXPECT_CALL(*device_files_, StoreUsageTableInfo(kYetAnotherUsageEntry, - ElementsAre(kUsageEntryInfoOfflineLicense4, + ElementsAre(kUsageEntryInfoSecureStop1, kUsageEntryInfoOfflineLicense3, kUsageEntryInfoOfflineLicense2))) .WillOnce(Return(true)); @@ -2082,16 +2247,16 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntryIsOffline) { &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 3; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } // Initial Test state: // 1. Usage entry to be deleted is not last. -// 2. Last few entries are clear. +// 2. Last few entries are of storage type unknown. // 3. Entry that precedes those in (2) is an offline license. // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. While defragging, offline licenses 2 and 3 will be selected to be // moved. // c. The selected entries will be moved. @@ -2099,27 +2264,25 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntryIsOffline) { // e. Updated table will be saved. // f. InvalidateEntry() will return NO_ERROR. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== -// Offline License 4 0 0 -// Clear entry 1 Deleted +// Secure Stop 1 0 0 +// Storage Type Unknown 1 Deleted // Offline License 1 2 Deleted // Offline License 2 3 2 (moved) // Offline License 3 4 1 (moved) -// Clear entry 5 Deleted -// Clear entry 6 Deleted +// Storage Type Unknown 5 Deleted +// Storage Type Unknown 6 Deleted // // # of usage entries 7 4 -TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreOfflineAndClear) { +TEST_F(UsageTableHeaderTest, + InvalidateEntry_LastEntriesAreOfflineAndUnknknown) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoOfflineLicense4, - kUsageEntryInfoEmpty, - kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoOfflineLicense2, - kUsageEntryInfoOfflineLicense3, - kUsageEntryInfoEmpty, - kUsageEntryInfoEmpty}; + kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, + kUsageEntryInfoOfflineLicense3, kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = @@ -2128,7 +2291,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreOfflineAndClear) { // Expect calls for moving offline license 3 (position 4) to position 1. const DeviceFiles::CdmLicenseData offline_license_3_data{ - kUsageEntryInfoOfflineLicense3.key_set_id(), + kUsageEntryInfoOfflineLicense3.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -2145,7 +2308,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreOfflineAndClear) { kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense3.key_set_id, NotNull(), NotNull())) .Times(2) // First to get entry, then again to update. .WillRepeatedly( @@ -2156,7 +2319,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreOfflineAndClear) { // Expect calls for moving offline license 2 (position 3) to position 2. const DeviceFiles::CdmLicenseData offline_license_2_data{ - kUsageEntryInfoOfflineLicense2.key_set_id(), + kUsageEntryInfoOfflineLicense2.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -2173,7 +2336,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreOfflineAndClear) { kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id, NotNull(), NotNull())) .Times(2) // First to get entry, then again to update. .WillRepeatedly( @@ -2205,7 +2368,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreOfflineAndClear) { DoAll(SetArgPointee<2>(kYetAnotherUsageEntry), Return(NO_ERROR))); EXPECT_CALL(*device_files_, StoreUsageTableInfo(kYetAnotherUsageEntry, - ElementsAre(kUsageEntryInfoOfflineLicense4, + ElementsAre(kUsageEntryInfoSecureStop1, kUsageEntryInfoOfflineLicense3, kUsageEntryInfoOfflineLicense2))) .WillOnce(Return(true)); @@ -2215,42 +2378,42 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreOfflineAndClear) { &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 3; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } // Initial Test state: -// 1. Usage entry to be deleted is not last (Offline License 1) +// 1. Usage entry to be deleted is not last (Secure stop 1) // 2. All other entries are invalid. // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. Defrag is skipped (no calls to Move()). // c. Usage table will be resized. // e. Updated table will be saved. // f. InvalidateEntry() will return NO_ERROR. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== -// Clear entry 0 Deleted -// Clear entry 1 Deleted -// Clear entry 2 Deleted -// Offline License 1 3 Deleted -// Clear entry 4 Deleted -// Clear entry 5 Deleted -// Clear entry 6 Deleted +// Storage Type Unknown 0 Deleted +// Storage Type Unknown 1 Deleted +// Storage Type Unknown 2 Deleted +// Secure stop 1 3 Deleted +// Storage Type Unknown 4 Deleted +// Storage Type Unknown 5 Deleted +// Storage Type Unknown 6 Deleted // // # of usage entries 7 0 TEST_F(UsageTableHeaderTest, InvalidateEntry_NoValidSessionsAfter) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoEmpty, kUsageEntryInfoEmpty, - kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoEmpty, kUsageEntryInfoEmpty, - kUsageEntryInfoEmpty}; + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoSecureStop1, + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = - 3; // kUsageEntryInfoOfflineLicense1 + 3; // kUsageEntryInfoSecureStop1 metrics::CryptoMetrics metrics; // No calls related to defragging, just shrinking the table and save. @@ -2266,16 +2429,16 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_NoValidSessionsAfter) { EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry( usage_entry_number_to_be_deleted, true, device_files_, &metrics)); - EXPECT_TRUE(usage_table_header_->entry_info_list().empty()); + EXPECT_TRUE(usage_table_header_->usage_entry_info().empty()); } -// 1. Usage entry to be deleted is last valid entry (Offline License 2) +// 1. Usage entry to be deleted is last valid entry (Secure stop 1) // 2. There exists an entry to be moved (Offline License 1) // 3. OEMCrypto is at max sessions, and any attempt to open a new session // will fail with INSUFFICIENT_CRYPTO_RESOURCES. // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. Only remaining entry is selected for move (Offline license 1) // c. Opening session for move will fail. // d. Defrag is aborted; but shrink is still made up to last valid. @@ -2283,29 +2446,29 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_NoValidSessionsAfter) { // f. Updated table will be saved. // g. InvalidateEntry() will return NO_ERROR. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== -// Clear entry 0 0 +// Storage Type Unknown 0 0 // Offline License 1 1 1 -// Offline License 2 2 Deleted -// Clear entry 3 Deleted +// Secure Stop 1 2 Deleted +// Storage Type Unknown 3 Deleted // // # of usage entries 4 2 TEST_F(UsageTableHeaderTest, InvalidateEntry_MaxSessionReached) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoOfflineLicense2, kUsageEntryInfoEmpty}; + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1, + kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = - 2; // kUsageEntryInfoOfflineLicense2 + 2; // kUsageEntryInfoSecureStop1 metrics::CryptoMetrics metrics; // Expected calls for moving offline license 1 (position 1) to position 0. // But will fail when opening a crypto session. const DeviceFiles::CdmLicenseData offline_license_1_data{ - kUsageEntryInfoOfflineLicense1.key_set_id(), + kUsageEntryInfoOfflineLicense1.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -2322,7 +2485,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_MaxSessionReached) { kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id, NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<1>(offline_license_1_data), Return(true))); EXPECT_CALL(*crypto_session_, Open(kLevelDefault)) @@ -2336,7 +2499,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_MaxSessionReached) { DoAll(SetArgPointee<2>(kAnotherUsageTableHeader), Return(NO_ERROR))); EXPECT_CALL(*device_files_, StoreUsageTableInfo(kAnotherUsageTableHeader, - ElementsAre(kUsageEntryInfoEmpty, + ElementsAre(kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1))) .WillOnce(Return(true)); @@ -2345,46 +2508,46 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_MaxSessionReached) { &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 2; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } -// 1. Usage entry to be deleted is first valid entry (Offline License 1) -// 2. There exists an entry to be moved (Offline License 2) +// 1. Usage entry to be deleted is first valid entry (Secure stop 1) +// 2. There exists an entry to be moved (Offline License 1) // 3. OEMCrypto is at max sessions, and any attempt to open a new session // will fail with INSUFFICIENT_CRYPTO_RESOURCES. // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. -// b. Only remaining entry is selected for move (Offline license 2) +// a. The entry will be marked as kStorageTypeUnknown. +// b. Only remaining entry is selected for move (Offline license 1) // c. Opening session for move will fail. // d. Defrag is aborted; but shrink is still made up to last valid. // e. Usage table will be resized. // f. Updated table will be saved. // g. InvalidateEntry() will return NO_ERROR. // -// Entry type Usage entries +// Storage type Usage entries // at start at end // ============= ======== ====== -// Offline License 1 0 0 (cleared) -// Offline License 2 1 1 (Failed to move) -// Clear entry 2 Deleted -// Clear entry 3 Deleted +// Secure Stop 1 0 0 (Storage type unknown) +// Offline License 1 1 1 (Failed to move) +// Storage Type Unknown 2 Deleted +// Storage Type Unknown 3 Deleted // // # of usage entries 4 2 TEST_F(UsageTableHeaderTest, InvalidateEntry_FirstEntry_MaxSessionReached) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, - kUsageEntryInfoEmpty, kUsageEntryInfoEmpty}; + kUsageEntryInfoSecureStop1, kUsageEntryInfoOfflineLicense1, + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoStorageTypeUnknown}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = - 0; // kUsageEntryInfoOfflineLicense1 + 0; // kUsageEntryInfoSecureStop1 metrics::CryptoMetrics metrics; - // Expected calls for moving offline license 2 (position 2) to position 0. + // Expected calls for moving offline license 1 (position 1) to position 0. // But will fail when opening a crypto session. - const DeviceFiles::CdmLicenseData offline_license_2_data{ - kUsageEntryInfoOfflineLicense2.key_set_id(), + const DeviceFiles::CdmLicenseData offline_license_1_data{ + kUsageEntryInfoOfflineLicense1.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -2401,9 +2564,9 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_FirstEntry_MaxSessionReached) { kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense2.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id, NotNull(), NotNull())) - .WillOnce(DoAll(SetArgPointee<1>(offline_license_2_data), Return(true))); + .WillOnce(DoAll(SetArgPointee<1>(offline_license_1_data), Return(true))); EXPECT_CALL(*crypto_session_, Open(kLevelDefault)) .WillRepeatedly(Return(INSUFFICIENT_CRYPTO_RESOURCES)); @@ -2415,8 +2578,8 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_FirstEntry_MaxSessionReached) { DoAll(SetArgPointee<2>(kAnotherUsageTableHeader), Return(NO_ERROR))); EXPECT_CALL(*device_files_, StoreUsageTableInfo(kAnotherUsageTableHeader, - ElementsAre(kUsageEntryInfoEmpty, - kUsageEntryInfoOfflineLicense2))) + ElementsAre(kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoOfflineLicense1))) .WillOnce(Return(true)); EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry( @@ -2424,15 +2587,15 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_FirstEntry_MaxSessionReached) { &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 2; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } -// 1. Usage entry to be deleted is last valid entry (Offline License 2) +// 1. Usage entry to be deleted is last valid entry (Secure stop 1) // 2. There exists an entry to be moved (Offline License 1) // 3. Moving entry will result in a system invalidation error. // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. Only remaining entry is selected for move (Offline license 1) // c. Moving entry will result in system invalidation. // d. Defrag is aborted; no call to Shrink() @@ -2442,26 +2605,26 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_FirstEntry_MaxSessionReached) { // Storage type Usage entries // at start at end // ============= ======== ====== -// Clear entry 0 0 +// Storage Type Unknown 0 0 // Offline License 1 1 1 -// Offline License 2 2 2 (cleared) -// Clear entry 3 3 +// Secure Stop 1 2 2 (Storage Type Unknown) +// Storage Type Unknown 3 3 // // # of usage entries 4 4 TEST_F(UsageTableHeaderTest, InvalidateEntry_SystemInvalidation_OnMove) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoOfflineLicense2, kUsageEntryInfoEmpty}; + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1, + kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = - 2; // kUsageEntryInfoOfflineLicense2 + 2; // kUsageEntryInfoSecureStop1 metrics::CryptoMetrics metrics; // Expected calls for moving offline license 1 (position 1) to position 0. // But will fail when moving. const DeviceFiles::CdmLicenseData offline_license_1_data{ - kUsageEntryInfoOfflineLicense1.key_set_id(), + kUsageEntryInfoOfflineLicense1.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -2478,7 +2641,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_SystemInvalidation_OnMove) { kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id, NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<1>(offline_license_1_data), Return(true))); EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); @@ -2489,10 +2652,11 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_SystemInvalidation_OnMove) { // Defrag is aborted, and table is saved, but no call to shrink(). EXPECT_CALL( *device_files_, - StoreUsageTableInfo( - kUsageTableHeader, - ElementsAre(kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoEmpty, kUsageEntryInfoEmpty))) + StoreUsageTableInfo(kUsageTableHeader, + ElementsAre(kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoOfflineLicense1, + kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown))) .WillOnce(Return(true)); EXPECT_EQ(SYSTEM_INVALIDATED_ERROR, usage_table_header_->InvalidateEntry( @@ -2500,10 +2664,10 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_SystemInvalidation_OnMove) { true, device_files_, &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 4; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } -// 1. Usage entry to be deleted is last valid entry (Offline License 2) +// 1. Usage entry to be deleted is last valid entry (Secure stop 1) // 2. There exists an entry to be moved (Offline License 1) // 3. Moving entry will result in a session invalidation error. // @@ -2512,7 +2676,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_SystemInvalidation_OnMove) { // session and is ignored (NO_ERROR returned). // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. Only remaining entry is selected for move (Offline license 1) // c. Moving entry will result in session invalidation. // d. Defrag is aborted; no call to Shrink() @@ -2522,26 +2686,26 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_SystemInvalidation_OnMove) { // Storage type Usage entries // at start at end // ============= ======== ====== -// Clear entry 0 0 +// Storage Type Unknown 0 0 // Offline License 1 1 1 -// Offline License 2 2 2 (cleared) -// Clear entry 3 3 +// Secure Stop 1 2 2 (Storage Type Unknown) +// Storage Type Unknown 3 3 // // # of usage entries 4 4 TEST_F(UsageTableHeaderTest, InvalidateEntry_SessionInvalidation_OnMove) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoOfflineLicense2, kUsageEntryInfoEmpty}; + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1, + kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = - 2; // kUsageEntryInfoOfflineLicense2 + 2; // kUsageEntryInfoSecureStop1 metrics::CryptoMetrics metrics; // Expected calls for moving offline license 1 (position 1) to position 0. // But will fail when moving. const DeviceFiles::CdmLicenseData offline_license_1_data{ - kUsageEntryInfoOfflineLicense1.key_set_id(), + kUsageEntryInfoOfflineLicense1.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -2558,7 +2722,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_SessionInvalidation_OnMove) { kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id, NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<1>(offline_license_1_data), Return(true))); EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); @@ -2569,10 +2733,11 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_SessionInvalidation_OnMove) { // Defrag is aborted, and table is saved, but no call to shrink(). EXPECT_CALL( *device_files_, - StoreUsageTableInfo( - kUsageTableHeader, - ElementsAre(kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoEmpty, kUsageEntryInfoEmpty))) + StoreUsageTableInfo(kUsageTableHeader, + ElementsAre(kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoOfflineLicense1, + kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown))) .WillOnce(Return(true)); // The underlying error should not be returned to the caller. @@ -2581,15 +2746,15 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_SessionInvalidation_OnMove) { &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 4; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } -// 1. Usage entry to be deleted is last valid entry (Offline License 2) +// 1. Usage entry to be deleted is last valid entry (Secure stop 1) // 2. There exists an entry to be moved (Offline License 1) // 3. Shrinking table will fail due to an unspecified entry being in use. // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. Only remaining entry is selected for move (Offline license 1) // c. Entry will be moved successfully. // d. Shrinking table fill fail with SHRINK_USAGE_TABLE_HEADER_ENTRY_IN_USE. @@ -2599,25 +2764,25 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_SessionInvalidation_OnMove) { // Storage type Usage entries // at start at end // ============= ======== ====== -// Clear entry 0 1 (swapped with Offline License 1) +// Storage Type Unknown 0 1 (swapped Offline License 1) // Offline License 1 1 0 (moved) -// Offline License 2 2 2 (cleared) -// Clear entry 3 3 +// Secure Stop 1 2 2 (Storage Type Unknown) +// Storage Type Unknown 3 3 // // # of usage entries 4 4 TEST_F(UsageTableHeaderTest, InvalidateEntry_ShrinkFails) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoOfflineLicense2, kUsageEntryInfoEmpty}; + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1, + kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = - 2; // kUsageEntryInfoOfflineLicense2 + 2; // kUsageEntryInfoSecureStop1 metrics::CryptoMetrics metrics; // Expected calls for moving offline license 1 (position 1) to position 0. const DeviceFiles::CdmLicenseData offline_license_1_data{ - kUsageEntryInfoOfflineLicense1.key_set_id(), + kUsageEntryInfoOfflineLicense1.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -2634,7 +2799,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_ShrinkFails) { kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id, NotNull(), NotNull())) .Times(2) // First to get entry, then again to update. .WillRepeatedly( @@ -2647,10 +2812,11 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_ShrinkFails) { SetArgPointee<1>(kUsageEntry), Return(NO_ERROR))); EXPECT_CALL( *device_files_, - StoreUsageTableInfo( - kAnotherUsageTableHeader, - ElementsAre(kUsageEntryInfoOfflineLicense1, kUsageEntryInfoEmpty, - kUsageEntryInfoEmpty, kUsageEntryInfoEmpty))) + StoreUsageTableInfo(kAnotherUsageTableHeader, + ElementsAre(kUsageEntryInfoOfflineLicense1, + kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown))) .WillOnce(Return(true)); EXPECT_CALL(*device_files_, StoreLicense(_, NotNull())) .WillOnce(Return(true)); @@ -2666,16 +2832,16 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_ShrinkFails) { &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 4; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } -// 1. Usage entry to be deleted is last valid entry (Offline License 2) +// 1. Usage entry to be deleted is last valid entry (Secure stop 1) // 2. There exists an entry to be moved (Offline License 1) // 3. Moving entry cannot be done as the destination is in use. // (this is unexpected but possible in normal operation) // // Attempting to delete the entry in (1) will result in: -// a. The entry will be cleared. +// a. The entry will be marked as kStorageTypeUnknown. // b. Only remaining entry is selected for move (Offline license 1) // c. Call to move will fail with MOVE_USAGE_ENTRY_DESTINATION_IN_USE. // d. Usage table will be resized. @@ -2685,26 +2851,26 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_ShrinkFails) { // Storage type Usage entries // at start at end // ============= ======== ====== -// Clear entry 0 0 +// Storage Type Unknown 0 0 // Offline License 1 1 1 (unable to move) -// Offline License 2 2 Deleted -// Clear entry 3 Deleted +// Secure Stop 1 2 Deleted +// Storage Type Unknown 3 Deleted // // # of usage entries 4 2 TEST_F(UsageTableHeaderTest, InvalidateEntry_DestinationInUse_OnMove) { const std::vector usage_entry_info_vector = { - kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense1, - kUsageEntryInfoOfflineLicense2, kUsageEntryInfoEmpty}; + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1, + kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown}; Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector); const uint32_t usage_entry_number_to_be_deleted = - 2; // kUsageEntryInfoOfflineLicense2 + 2; // kUsageEntryInfoSecureStop1 metrics::CryptoMetrics metrics; // Expected calls for moving offline license 1 (position 1) to position 0. // But will fail due to the destination being in use. const DeviceFiles::CdmLicenseData offline_license_1_data{ - kUsageEntryInfoOfflineLicense1.key_set_id(), + kUsageEntryInfoOfflineLicense1.key_set_id, kActiveLicenseState, kPsshData, kKeyRequest, @@ -2721,7 +2887,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_DestinationInUse_OnMove) { kDrmCertificate, kCryptoWrappedKey}; EXPECT_CALL(*device_files_, - RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id(), + RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id, NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<1>(offline_license_1_data), Return(true))); EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); @@ -2737,7 +2903,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_DestinationInUse_OnMove) { .WillOnce(DoAll(SetArgPointee<2>(kAnotherUsageEntry), Return(NO_ERROR))); EXPECT_CALL(*device_files_, StoreUsageTableInfo(kAnotherUsageEntry, - ElementsAre(kUsageEntryInfoEmpty, + ElementsAre(kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1))) .WillOnce(Return(true)); @@ -2746,18 +2912,18 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_DestinationInUse_OnMove) { &metrics)); // Check the end state of the usage table. constexpr size_t expected_size = 2; - EXPECT_EQ(expected_size, usage_table_header_->entry_info_list().size()); + EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size()); } -// If the crypto session says the usage table header is stale -// (generation skew), restoring table should fail. Table will created -// a new usage table / header. +// If the crypto session says the usage table header is stale, init should fail. TEST_F(UsageTableHeaderTest, StaleHeader) { - const std::vector usage_entry_info_vector = { - kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2, - kUsageEntryInfoEmpty, kUsageEntryInfoOfflineLicense3}; + std::vector usage_entry_info_vector; + const CdmUsageEntryInfo usage_entry_info_array[] = { + kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1, + kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense2}; + ToVector(usage_entry_info_vector, usage_entry_info_array, + sizeof(usage_entry_info_array)); - // Expectations for initial checks. EXPECT_CALL(*crypto_session_, GetNumberOfOpenSessions(kLevelDefault, NotNull())) .WillRepeatedly(DoAll(SetArgPointee<1>(0), Return(NO_ERROR))); @@ -2770,7 +2936,6 @@ TEST_F(UsageTableHeaderTest, StaleHeader) { EXPECT_CALL(*crypto_session_, LoadUsageTableHeader(kLevelDefault, kUsageTableHeader)) .WillOnce(Return(LOAD_USAGE_HEADER_GENERATION_SKEW)); - // Expectations for clear old table data and creating new table. ExpectToDeleteUsageTableFiles(); EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(kLevelDefault, NotNull())) @@ -2786,7 +2951,7 @@ TEST_F(UsageTableHeaderTest, StaleHeader) { // Testing of the private function UsageTableHeader::Shrink. // Don't shrink any entries. TEST_F(UsageTableHeaderTest, Shrink_NoneOfTable) { - Init(kSecurityLevelL1, kUsageTableHeader, k5UsageEntryInfoVector); + Init(kSecurityLevelL1, kUsageTableHeader, k10UsageEntryInfoVector); metrics::CryptoMetrics metrics; // These calls are "expensive" and should be avoided if possible. @@ -2801,11 +2966,11 @@ TEST_F(UsageTableHeaderTest, Shrink_NoneOfTable) { // Shrink some of the table, but not all of it. TEST_F(UsageTableHeaderTest, Shrink_PartOfTable) { - Init(kSecurityLevelL1, kUsageTableHeader, k5UsageEntryInfoVector); + Init(kSecurityLevelL1, kUsageTableHeader, k10UsageEntryInfoVector); const uint32_t to_shink = 5; const std::vector shrunken_entries( - k5UsageEntryInfoVector.cbegin(), - k5UsageEntryInfoVector.cend() - to_shink); + k10UsageEntryInfoVector.cbegin(), + k10UsageEntryInfoVector.cend() - to_shink); metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, @@ -2822,7 +2987,7 @@ TEST_F(UsageTableHeaderTest, Shrink_PartOfTable) { // Shrink all of the table, no entries left. TEST_F(UsageTableHeaderTest, Shrink_AllOfTable) { - Init(kSecurityLevelL1, kUsageTableHeader, k5UsageEntryInfoVector); + Init(kSecurityLevelL1, kUsageTableHeader, k10UsageEntryInfoVector); metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, @@ -2832,15 +2997,16 @@ TEST_F(UsageTableHeaderTest, Shrink_AllOfTable) { kEmptyUsageEntryInfoVector)) .WillOnce(Return(true)); - EXPECT_EQ(usage_table_header_->Shrink( - &metrics, static_cast(k5UsageEntryInfoVector.size())), - NO_ERROR); + EXPECT_EQ( + usage_table_header_->Shrink( + &metrics, static_cast(k10UsageEntryInfoVector.size())), + NO_ERROR); } // Request to shrink more entries than there are in the table; should remove // all entries, but log a warning. TEST_F(UsageTableHeaderTest, Shrink_MoreThanTable) { - Init(kSecurityLevelL1, kUsageTableHeader, k5UsageEntryInfoVector); + Init(kSecurityLevelL1, kUsageTableHeader, k10UsageEntryInfoVector); metrics::CryptoMetrics metrics; EXPECT_CALL(*crypto_session_, ShrinkUsageTableHeader(kLevelDefault, 0, NotNull())) @@ -2851,7 +3017,7 @@ TEST_F(UsageTableHeaderTest, Shrink_MoreThanTable) { EXPECT_EQ( usage_table_header_->Shrink( - &metrics, static_cast(k5UsageEntryInfoVector.size()) + 10), + &metrics, static_cast(k10UsageEntryInfoVector.size()) + 10), NO_ERROR); } @@ -2879,7 +3045,7 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_NoAction) { EXPECT_CALL(*device_files_, RetrieveLicense(_, _, _)).Times(0); EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_)); - EXPECT_EQ(usage_table_header_->entry_info_list(), + EXPECT_EQ(usage_table_header_->usage_entry_info(), kUpgradableUsageEntryInfoList); } @@ -2908,17 +3074,17 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_Succeed) { for (size_t i = 0; i < kUpgradableUsageEntryInfoList.size(); ++i) { const CdmUsageEntryInfo& info = kUpgradableUsageEntryInfoList[i]; - if (info.HasKeySetId()) { - // Only entries with a key set ID will be retrieved. + if (info.storage_type == kStorageLicense) { + // Only offline licenses are supported. EXPECT_CALL(*device_files_, - RetrieveLicense(info.key_set_id(), NotNull(), NotNull())) + RetrieveLicense(info.key_set_id, NotNull(), NotNull())) .WillOnce( DoAll(SetArgPointee<1>(license_info_list[i]), Return(true))); } } EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_)); - EXPECT_EQ(usage_table_header_->entry_info_list(), + EXPECT_EQ(usage_table_header_->usage_entry_info(), kUpgradedUsageEntryInfoList); } @@ -2926,17 +3092,19 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_Succeed) { // Table info is load from device files and must be upgraded. // A few entries have the unknown storage type value. // -// Entry# Entry type Result info +// Entry# Storage type Result info // ====== ============ =========== // 0 Offline Upgraded -// 1 Clear Cleared -// 2 Clear Cleared +// 1 Unknown Cleared +// 2 Unknown Cleared TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_PartialSucceedWithUnknownStorageTypes) { const std::vector upgradable_usage_entry_info_list = { - kUpgradableUsageEntryInfo1, kUsageEntryInfoEmpty, kUsageEntryInfoEmpty}; + kUpgradableUsageEntryInfo1, kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown}; const std::vector upgraded_usage_entry_info_list = { - kUpgradedUsageEntryInfo1, kUsageEntryInfoEmpty, kUsageEntryInfoEmpty}; + kUpgradedUsageEntryInfo1, kUsageEntryInfoStorageTypeUnknown, + kUsageEntryInfoStorageTypeUnknown}; // Load table expectations. EXPECT_CALL(*crypto_session_, @@ -2956,13 +3124,13 @@ TEST_F(UsageTableHeaderTest, const std::vector license_info_list = CreateUpgradableLicenseInfoList(); EXPECT_CALL(*device_files_, - RetrieveLicense(upgradable_usage_entry_info_list[0].key_set_id(), + RetrieveLicense(upgradable_usage_entry_info_list[0].key_set_id, NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<1>(license_info_list[0]), Return(true))); EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_)); EXPECT_EQ(upgraded_usage_entry_info_list, - usage_table_header_->entry_info_list()); + usage_table_header_->usage_entry_info()); } // Initial Test state: @@ -2971,10 +3139,10 @@ TEST_F(UsageTableHeaderTest, // 2. During the LRU upgrade process, any license that cannot be // validated are cleared, and marked to be deleted. // -// Entry# Entry type License Issue Result info +// Entry# Storage type License Issue Result info // ====== ============ ============= =========== // 0 Offline No signature Cleared -// 1 Clear Clear entry Cleared +// 1 Unknown Clear entry Cleared // 2 Offline Upgraded TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_PartialSucceedWithLicenseParseIssues) { @@ -3011,9 +3179,9 @@ TEST_F(UsageTableHeaderTest, for (size_t i = 0; i < upgradable_usage_entry_info_list.size(); ++i) { const CdmUsageEntryInfo& info = upgradable_usage_entry_info_list[i]; - if (info.HasKeySetId()) { + if (info.storage_type == kStorageLicense) { EXPECT_CALL(*device_files_, - RetrieveLicense(info.key_set_id(), NotNull(), NotNull())) + RetrieveLicense(info.key_set_id, NotNull(), NotNull())) .WillOnce( DoAll(SetArgPointee<1>(license_data_list[i]), Return(true))); } @@ -3022,12 +3190,12 @@ TEST_F(UsageTableHeaderTest, // For the entries which failed, there should be an attempt to delete the // files associated with them. EXPECT_CALL(*device_files_, - DeleteLicense(upgradable_usage_entry_info_list[0].key_set_id())) + DeleteLicense(upgradable_usage_entry_info_list[0].key_set_id)) .WillOnce(Return(true)); EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_)); EXPECT_EQ(upgraded_usage_entry_info_list, - usage_table_header_->entry_info_list()); + usage_table_header_->usage_entry_info()); } // Initial Test state: @@ -3051,9 +3219,9 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_AllFailure) { for (size_t i = 0; i < kUpgradableUsageEntryInfoList.size(); ++i) { const CdmUsageEntryInfo& info = kUpgradableUsageEntryInfoList[i]; - if (info.HasKeySetId()) { + if (info.storage_type == kStorageLicense) { EXPECT_CALL(*device_files_, - RetrieveLicense(info.key_set_id(), NotNull(), NotNull())) + RetrieveLicense(info.key_set_id, NotNull(), NotNull())) .WillOnce(Return(false)); } } @@ -3078,11 +3246,12 @@ TEST_F(UsageTableHeaderTest, LruLastUsedTime_CreateLicenseEntry) { // Expected values. const uint32_t expected_usage_entry_number = static_cast(kUpgradedUsageEntryInfoList.size()); - const CdmUsageEntryInfo expected_new_entry( - "offline_key_set_4", kLruBaseTime, kLruBaseTime + kDefaultExpireDuration); - std::vector expected_entry_info_list = + const CdmUsageEntryInfo expected_new_entry = { + kStorageLicense, "offline_key_set_4", "", kLruBaseTime, + kLruBaseTime + kDefaultExpireDuration}; + std::vector expected_usage_info_list = kUpgradedUsageEntryInfoList; - expected_entry_info_list.push_back(expected_new_entry); + expected_usage_info_list.push_back(expected_new_entry); // AddKey expectations EXPECT_CALL(*crypto_session_, CreateUsageEntry(NotNull())) @@ -3099,29 +3268,29 @@ TEST_F(UsageTableHeaderTest, LruLastUsedTime_CreateLicenseEntry) { // The Call. uint32_t usage_entry_number = 0; EXPECT_EQ(NO_ERROR, usage_table_header_->AddEntry( - crypto_session_, expected_new_entry.key_set_id(), + crypto_session_, expected_new_entry.key_set_id, kEmptyString, &usage_entry_number)); EXPECT_EQ(expected_usage_entry_number, usage_entry_number); - EXPECT_EQ(expected_entry_info_list, usage_table_header_->entry_info_list()); + EXPECT_EQ(expected_usage_info_list, usage_table_header_->usage_entry_info()); } TEST_F(UsageTableHeaderTest, LruLastUsedTime_UpdateEntry) { Init(kSecurityLevelL1, kUpgradedUsageTableHeader, kUpgradedUsageEntryInfoList); - std::vector expected_entry_info_list = + std::vector expected_usage_info_list = kUpgradedUsageEntryInfoList; MockClock mock_clock; usage_table_header_->SetClock(&mock_clock); const int64_t expected_update_time = kLruBaseTime + 60 * 60; // Any value larger than the original works. for (uint32_t usage_entry_number = 0; - usage_entry_number < expected_entry_info_list.size(); + usage_entry_number < expected_usage_info_list.size(); ++usage_entry_number) { // Update expected values. - expected_entry_info_list[usage_entry_number].SetLastUseTime( - expected_update_time); + expected_usage_info_list[usage_entry_number].last_use_time = + expected_update_time; // Update expectations EXPECT_CALL(*crypto_session_, UpdateUsageEntry(NotNull(), NotNull())) @@ -3135,7 +3304,8 @@ TEST_F(UsageTableHeaderTest, LruLastUsedTime_UpdateEntry) { CdmUsageEntry usage_entry; EXPECT_EQ(NO_ERROR, usage_table_header_->UpdateEntry( usage_entry_number, crypto_session_, &usage_entry)); - EXPECT_EQ(expected_entry_info_list, usage_table_header_->entry_info_list()); + EXPECT_EQ(expected_usage_info_list, + usage_table_header_->usage_entry_info()); } } @@ -3143,18 +3313,18 @@ TEST_F(UsageTableHeaderTest, LruLastUsedTime_LoadEntry) { Init(kSecurityLevelL1, kUpgradedUsageTableHeader, kUpgradedUsageEntryInfoList); - std::vector expected_entry_info_list = + std::vector expected_usage_info_list = kUpgradedUsageEntryInfoList; MockClock mock_clock; usage_table_header_->SetClock(&mock_clock); const int64_t expected_update_time = kLruBaseTime + 60 * 60; // Any value larger than the original works. for (uint32_t usage_entry_number = 0; - usage_entry_number < expected_entry_info_list.size(); + usage_entry_number < expected_usage_info_list.size(); ++usage_entry_number) { // Update expected values. - expected_entry_info_list[usage_entry_number].SetLastUseTime( - expected_update_time); + expected_usage_info_list[usage_entry_number].last_use_time = + expected_update_time; // Update expectations EXPECT_CALL(*crypto_session_, LoadUsageEntry(usage_entry_number, _)) @@ -3166,7 +3336,8 @@ TEST_F(UsageTableHeaderTest, LruLastUsedTime_LoadEntry) { CdmUsageEntry usage_entry; EXPECT_EQ(NO_ERROR, usage_table_header_->LoadEntry( crypto_session_, kEmptyString, usage_entry_number)); - EXPECT_EQ(expected_entry_info_list, usage_table_header_->entry_info_list()); + EXPECT_EQ(expected_usage_info_list, + usage_table_header_->usage_entry_info()); } } @@ -3190,7 +3361,7 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_InvalidInput) { } // Check that the major priority buckets are respected. -// Expects that clear entries to be chosen above all others. +// Expects that unknown entries to be chosen above all others. // Unexpired licenses should only be considered if the threshold // is met. TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) { @@ -3200,22 +3371,30 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) { std::vector usage_entry_info_list; // Unexpired offline license. - const CdmUsageEntryInfo unexpired_entry_info( - "unexpired_key_set_id", /* last_use_time */ kLruBaseTime, - /* license_expiry_time */ kLruBaseTime + 2 * kOneDay); + CdmUsageEntryInfo unexpired_entry_info; + unexpired_entry_info.storage_type = kStorageLicense; + unexpired_entry_info.key_set_id = "unexpired_key_set_id"; + unexpired_entry_info.last_use_time = kLruBaseTime; + unexpired_entry_info.offline_license_expiry_time = kLruBaseTime + 2 * kOneDay; usage_entry_info_list.push_back(unexpired_entry_info); constexpr uint32_t unexpired_entry_number = 0; // Expired offline license. - const CdmUsageEntryInfo expired_entry_info( - "expired_key_set_id", /* last_use_time */ kLruBaseTime, - /* license_expiry_time */ kLruBaseTime); + CdmUsageEntryInfo expired_entry_info; + expired_entry_info.storage_type = kStorageLicense; + expired_entry_info.key_set_id = "expired_key_set_id"; + expired_entry_info.last_use_time = kLruBaseTime; + expired_entry_info.offline_license_expiry_time = kLruBaseTime; usage_entry_info_list.push_back(expired_entry_info); constexpr uint32_t expired_entry_number = 1; - // Clear entry. - usage_entry_info_list.push_back(kUsageEntryInfoEmpty); - constexpr uint32_t clear_entry_number = 2; + // Unknown entry. + CdmUsageEntryInfo unknown_entry_info; + unknown_entry_info.storage_type = kStorageTypeUnknown; + // Should be chosen regardless of |last_use_time|. + unknown_entry_info.last_use_time = kCurrentTime; + usage_entry_info_list.push_back(unknown_entry_info); + constexpr uint32_t unknown_entry_number = 2; // Case 1: If there is a clear entry, it should be selected above // any other entry. @@ -3225,7 +3404,7 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) { EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting( usage_entry_info_list, kCurrentTime, /* unexpired_threshold = */ 3, &entry_to_remove)); - EXPECT_EQ(clear_entry_number, entry_to_remove); + EXPECT_EQ(unknown_entry_number, entry_to_remove); usage_entry_info_list.pop_back(); // Removing clear entry. // |usage_entry_info_list| only contains 1 expired and 1 unexpired offline @@ -3249,7 +3428,7 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) { // Case 3a: Threshold not met, expired entry is the most stale. entry_to_remove = kInvalidEntry; - usage_entry_info_list[expired_entry_number].DecLastUseTime(); + usage_entry_info_list[expired_entry_number].last_use_time--; EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting( usage_entry_info_list, kCurrentTime, /* unexpired_threshold = */ 3, &entry_to_remove)); @@ -3257,8 +3436,8 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) { // Case 3b: Threshold not met, unexpired entry is the most stale. entry_to_remove = kInvalidEntry; - usage_entry_info_list[expired_entry_number].IncLastUseTime(); - usage_entry_info_list[unexpired_entry_number].DecLastUseTime(); + usage_entry_info_list[expired_entry_number].last_use_time++; + usage_entry_info_list[unexpired_entry_number].last_use_time--; EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting( usage_entry_info_list, kCurrentTime, /* unexpired_threshold = */ 3, &entry_to_remove)); @@ -3273,8 +3452,8 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) { // Case 3d: Threshold met, expired entry is the most stale. entry_to_remove = kInvalidEntry; - usage_entry_info_list[expired_entry_number].DecLastUseTime(); - usage_entry_info_list[unexpired_entry_number].IncLastUseTime(); + usage_entry_info_list[expired_entry_number].last_use_time--; + usage_entry_info_list[unexpired_entry_number].last_use_time++; EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting( usage_entry_info_list, kCurrentTime, /* unexpired_threshold = */ 0, &entry_to_remove)); @@ -3320,10 +3499,11 @@ TEST_F(UsageTableHeaderTest, // Create a set of all offline licenses. for (uint32_t i = 0; i < kSetSize; ++i) { CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[i]; - usage_entry_info.SetKeySetId("unexpired_offline"); - usage_entry_info.SetLastUseTime(kLruBaseTime); - usage_entry_info.SetLicenseExpiryTime(kCurrentTime + - kDefaultExpireDuration); + usage_entry_info.storage_type = kStorageLicense; + usage_entry_info.key_set_id = "unexpired_offline"; + usage_entry_info.last_use_time = kLruBaseTime; + usage_entry_info.offline_license_expiry_time = + kCurrentTime + kDefaultExpireDuration; } // Mark three licenses as expired. @@ -3333,11 +3513,11 @@ TEST_F(UsageTableHeaderTest, static_cast(wvutil::CdmRandom::RandomInRange(kSetSize - 1)); CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[i]; // Skip already expired ones - if (usage_entry_info.key_set_id() != "unexpired_offline") continue; + if (usage_entry_info.key_set_id != "unexpired_offline") continue; // Make these less stale than the unexpired licenses. - usage_entry_info.SetKeySetId("expired_offline"); - usage_entry_info.SetLastUseTime(kLruBaseTime + kOneDay); - usage_entry_info.SetLicenseExpiryTime(kCurrentTime - kOneDay); + usage_entry_info.last_use_time = kLruBaseTime + kOneDay; + usage_entry_info.offline_license_expiry_time = kCurrentTime - kOneDay; + usage_entry_info.key_set_id = "expired_offline"; expired_license_numbers.push_back(i); } @@ -3385,10 +3565,11 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_LargeMixedSet) { // Create a set of unexpired license entries. for (uint32_t i = 0; i < kLargeSetSize; ++i) { CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[i]; - usage_entry_info.SetKeySetId("unexpired_offline"); - usage_entry_info.SetLastUseTime(kLruBaseTime + kOneDay); - usage_entry_info.SetLicenseExpiryTime(kCurrentTime + - kDefaultExpireDuration); + usage_entry_info.storage_type = kStorageLicense; + usage_entry_info.key_set_id = "unexpired_offline"; + usage_entry_info.last_use_time = kLruBaseTime + kOneDay; + usage_entry_info.offline_license_expiry_time = + kCurrentTime + kDefaultExpireDuration; } // Select a offline license to be even more stale, but unexpired. @@ -3396,8 +3577,8 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_LargeMixedSet) { wvutil::CdmRandom::RandomInRange(kLargeSetSize - 1)); CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[most_stale_offline_license_number]; - usage_entry_info.SetKeySetId("stale_offline"); - usage_entry_info.SetLastUseTime(kLruBaseTime); + usage_entry_info.last_use_time = kLruBaseTime; + usage_entry_info.key_set_id = "stale_offline"; // Case 1: Most stale license is selected. uint32_t entry_to_remove = kInvalidEntry; @@ -3420,8 +3601,8 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_LargeMixedSet) { const uint32_t i = static_cast( wvutil::CdmRandom::RandomInRange(kLargeSetSize - 1)); // Don't modify the stale offline license. - if (usage_entry_info_list[i].key_set_id() != "unexpired_offline") continue; - usage_entry_info_list[i].SetLicenseExpiryTime(kLruBaseTime); + if (usage_entry_info_list[i].key_set_id != "unexpired_offline") continue; + usage_entry_info_list[i].offline_license_expiry_time = kLruBaseTime; expired_offline_license_number = i; } diff --git a/libwvdrmengine/cdm/metrics/test/metrics_collections_unittest.cpp b/libwvdrmengine/cdm/metrics/test/metrics_collections_unittest.cpp index fbfb100c..b3931e60 100644 --- a/libwvdrmengine/cdm/metrics/test/metrics_collections_unittest.cpp +++ b/libwvdrmengine/cdm/metrics/test/metrics_collections_unittest.cpp @@ -358,7 +358,8 @@ TEST_F(CryptoMetricsTest, AllCryptoMetrics) { crypto_metrics.usage_table_header_lru_usage_info_count_.Record(150); crypto_metrics.usage_table_header_lru_offline_license_count_.Record(50); crypto_metrics.usage_table_header_lru_evicted_entry_staleness_.Record(259200); - crypto_metrics.usage_table_header_lru_evicted_entry_type_.Record(1); + crypto_metrics.usage_table_header_lru_evicted_entry_type_.Record( + kStorageUsageInfo); // Oem crypto metrics. crypto_metrics.oemcrypto_api_version_.Record(123); @@ -481,7 +482,8 @@ TEST_F(CryptoMetricsTest, AllCryptoMetrics) { EXPECT_EQ( 259200, actual.usage_table_header_lru_evicted_entry_staleness_s().int_value()); - EXPECT_EQ(1, actual.usage_table_header_lru_evicted_entry_type().int_value()); + EXPECT_EQ(kStorageUsageInfo, + actual.usage_table_header_lru_evicted_entry_type().int_value()); // Oem crypto metrics. EXPECT_EQ(123, actual.oemcrypto_api_version().int_value());