Merge CDM LRU change to Android.

[ Merge of http://go/wvgerrit/81903 ]
[ Merge of http://go/wvgerrit/87473 ]
[ Merge of http://go/wvgerrit/82568 ]
[ Merge of http://go/wvgerrit/87266 ]
[ Merge of http://go/wvgerrit/87474 ]
[ Merge of http://go/wvgerrit/87475 ]

Bug: 135046978
Test: GTS and Android unit tests
Change-Id: Iff2ff62cea21eeb36d7b56c8bb852fce8447ff89
This commit is contained in:
Alex Dale
2019-11-12 18:23:17 -08:00
parent e24b1ef824
commit 061b0e7caf
15 changed files with 2159 additions and 174 deletions

View File

@@ -110,6 +110,7 @@ class DeviceFiles {
virtual bool RetrieveLicense(const std::string& key_set_id,
CdmLicenseData* license_data,
ResponseType* result);
virtual bool DeleteLicense(const std::string& key_set_id);
virtual bool ListLicenses(std::vector<std::string>* key_set_ids);
virtual bool DeleteAllFiles();
@@ -153,6 +154,27 @@ class DeviceFiles {
virtual bool DeleteUsageInfo(const std::string& usage_info_file_name,
const std::string& provider_session_token);
// Deletes a set of provider sessions from the specified usage info.
// Sessions removed are based on the provided |key_set_ids|. If
// there are no remaining sessions associated with the usage info
// then the file will be deleted; otherwise, the remaining sessions
// are written back to the usage info file.
//
// Args:
// usage_info_file_name: name of the file containing the usage info
// message. This name should _not_ be the complete path, just
// the file name.
// key_set_ids: The list of key set IDs to be removed from the
// usage info. Note that any key set ids that are not present
// in the usage info are silently ignored.
// Returns:
// `true` if the file existed, and operations were completed as
// expected. `false` if the file does not exist or if there is an
// issue writing the result back to file.
virtual bool DeleteMultipleUsageInfoByKeySetIds(
const std::string& usage_info_file_name,
const std::vector<std::string>& key_set_ids);
// Delete usage information from the file system. Puts a list of all the
// psts that were deleted from the file into |provider_session_tokens|.
virtual bool DeleteAllUsageInfoForApp(
@@ -211,9 +233,12 @@ class DeviceFiles {
const CdmUsageTableHeader& usage_table_header,
const std::vector<CdmUsageEntryInfo>& 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
// indicated by |lru_upgrade|.
virtual bool RetrieveUsageTableInfo(
CdmUsageTableHeader* usage_table_header,
std::vector<CdmUsageEntryInfo>* usage_entry_info);
std::vector<CdmUsageEntryInfo>* usage_entry_info, bool* lru_upgrade);
virtual bool DeleteUsageTableInfo();
@@ -258,6 +283,7 @@ class DeviceFiles {
FRIEND_TEST(DeviceFilesUsageInfoTest, Store);
FRIEND_TEST(DeviceFilesUsageTableTest, Read);
FRIEND_TEST(DeviceFilesUsageTableTest, Store);
FRIEND_TEST(DeviceFilesUsageTableTest, ReadWithoutLruData);
FRIEND_TEST(WvCdmRequestLicenseTest, UnprovisionTest);
FRIEND_TEST(WvCdmRequestLicenseTest, ForceL3Test);
FRIEND_TEST(WvCdmRequestLicenseTest, UsageInfoRetryTest);

View File

@@ -10,6 +10,7 @@
#include <string>
#include <vector>
#include "clock.h"
#include "crypto_session.h"
#include "device_files.h"
#include "disallow_copy_and_assign.h"
@@ -61,11 +62,13 @@ class UsageTableHeader {
bool persistent_license,
const CdmKeySetId& key_set_id,
const std::string& usage_info_filename,
const CdmKeyResponse& license_message,
uint32_t* usage_entry_number);
virtual CdmResponseType LoadEntry(CryptoSession* crypto_session,
const CdmUsageEntry& usage_entry,
uint32_t usage_entry_number);
virtual CdmResponseType UpdateEntry(CryptoSession* crypto_session,
virtual CdmResponseType UpdateEntry(uint32_t usage_entry_number,
CryptoSession* crypto_session,
CdmUsageEntry* usage_entry);
// The licenses or usage info records specified by |usage_entry_number|
@@ -85,6 +88,27 @@ class UsageTableHeader {
size_t size() { return usage_entry_info_.size(); }
const std::vector<CdmUsageEntryInfo>& usage_entry_info() const {
return usage_entry_info_;
}
// Set the reference clock used for the method GetCurrentTime().
void SetClock(Clock* clock) {
if (clock != nullptr)
clock_ref_ = clock;
else
clock_ref_ = &clock_;
}
static bool DetermineLicenseToRemoveForTesting(
const std::vector<CdmUsageEntryInfo>& usage_entry_info_list,
int64_t current_time, size_t unexpired_threshold, size_t removal_count,
std::vector<uint32_t>* removal_candidates) {
return DetermineLicenseToRemove(usage_entry_info_list, current_time,
unexpired_threshold, removal_count,
removal_candidates);
}
private:
CdmResponseType MoveEntry(uint32_t from /* usage entry number */,
const CdmUsageEntry& from_usage_entry,
@@ -111,6 +135,59 @@ class UsageTableHeader {
virtual bool CreateDummyOldUsageEntry(CryptoSession* crypto_session);
// Performs and LRU upgrade on all loaded CdmUsageEntryInfo from a
// device file that had not yet been upgraded to use the LRU data.
virtual bool LruUpgradeAllUsageEntries();
virtual bool GetRemovalCandidates(std::vector<uint32_t>* removal_candidates);
int64_t GetCurrentTime() { return clock_ref_->GetCurrentTime(); }
// Uses an LRU-base algorithm to determine which licenses should be
// removed. This is intended to be used if the usage table is full
// and a new entry needs to be added.
//
// Algorithm overview:
// Given the set of all usage entry infos, the entries which are
// of unknown storage type or are the most stale will be returned,
// with some exceptions for offline licenses.
// 1) Expired licenses will always be considered. Expiration is
// determined using the usage entry info's
// |offline_license_expiry| compared to the provided
// |current_time|.
// 2) Unexpired offline licenses will only be considered for
// removal if the number of unexpired offline licenses exceeds
// |unexpired_threshold|.
// The number of licenses to be considered will be less than or
// equal to the requested |removal_count|.
//
// Unknown storage types will be considered above all other entry
// types.
//
// Parameters:
// [in] usage_entry_info_list: The complete list of known usage
// entries.
// [in] current_time: The current time to compare expiration times
// against.
// [in] unexpired_threshold: The maximum number of unexpired
// offline licenses that are present, before offline
// licenses would be considered for removal.
// [in] removal_count: The desired number of removal candidate to
// find. Note that the actual number will be anywhere
// between 1 and |removal_count|. Must be greater than or
// equal to 1.
// [out] removal_candidates: List of usage entry numbers of the
// entries to be removed. Assume to be unaffected if the
// function returns |false|.
//
// Returns:
// |true| if at least one removal candidate can be determined.
// Otherwise returns |false|.
static bool DetermineLicenseToRemove(
const std::vector<CdmUsageEntryInfo>& usage_entry_info_list,
int64_t current_time, size_t unexpired_threshold, size_t removal_count,
std::vector<uint32_t>* removal_candidates);
// This handle and file system is only to be used when accessing
// usage_table_header. Usage entries should use the file system provided
// by CdmSession.
@@ -133,6 +210,14 @@ class UsageTableHeader {
metrics::CryptoMetrics alternate_crypto_metrics_;
// |clock_| represents the system's "wall clock". For the clock's purpose
// we do not need a more secure clock.
Clock clock_;
// |clock_ref_| is a pointer to the clock which is to be used for
// obtaining the current time. By default, this points to the internal
// |clock_| variable, however, it can be overrided for testing purpose.
Clock* clock_ref_;
#if defined(UNIT_TEST)
// Test related declarations
friend class UsageTableHeaderTest;

View File

@@ -400,6 +400,7 @@ enum CdmResponseType {
INVALID_SRM_LIST = 346,
KEYSET_ID_NOT_FOUND_4 = 347,
SESSION_NOT_FOUND_22 = 348,
USAGE_INVALID_PARAMETERS_2 = 349,
// Don't forget to add new values to
// * core/test/test_printers.cpp.
// * android/include/mapErrors-inl.h
@@ -504,11 +505,25 @@ 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 {
return storage_type == other.storage_type &&
key_set_id == other.key_set_id &&
(storage_type != kStorageUsageInfo ||
usage_info_file_name == other.usage_info_file_name);
if (this == &other) {
return true;
}
if (storage_type != other.storage_type || key_set_id != other.key_set_id ||
last_use_time != other.last_use_time) {
return false;
}
// 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;
}
};