Core CDM: Remove secure stop from LRU algorithm.
[ Merge of http://go/wvgerrit/158877 ] The UsageTableHeader's LRU algorithm for determining which entry to evict when full uses special considerations based on the type of entry (offline or secure stop). This CL removes all secure-stop-specific considerations, and instead treats secure stop's the same as an unused entry. Secure stop entries will always be selected for removal before offline licenses (expired or not). Additionally, LRU table upgrading will ignore secure-stop entries. This has no effect in practice as DeviceFiles will not load secure stop usage entries when UsageTableHeader is initialized on a real file system. Bug: 242289743 Test: run_x86_64_tests and request_license_test Change-Id: Ib3f71f191aed94aad62951667426911e4e202068
This commit is contained in:
@@ -261,10 +261,9 @@ class UsageTableHeader {
|
||||
int64_t GetCurrentTime() { return clock_ref_->GetCurrentTime(); }
|
||||
|
||||
// Sets LRU related metrics based on the provided |staleness| (in
|
||||
// seconds) and |storage_type| of the entry removed.
|
||||
// seconds).
|
||||
void RecordLruEventMetrics(metrics::CryptoMetrics* metrics,
|
||||
uint64_t staleness,
|
||||
CdmUsageEntryStorageType storage_type);
|
||||
uint64_t staleness);
|
||||
|
||||
// Uses an LRU-base algorithm to determine which license should be
|
||||
// removed. This is intended to be used if the usage table is full
|
||||
|
||||
@@ -96,41 +96,6 @@ bool RetrieveOfflineLicense(DeviceFiles* device_files,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RetrieveUsageInfoLicense(DeviceFiles* device_files,
|
||||
const std::string& usage_info_file_name,
|
||||
const std::string& key_set_id,
|
||||
CdmKeyResponse* license_message,
|
||||
uint32_t* usage_entry_number) {
|
||||
if (device_files == nullptr) {
|
||||
LOGE("DeviceFiles handle is null");
|
||||
return false;
|
||||
}
|
||||
if (license_message == nullptr) {
|
||||
LOGE("Output parameter |license_message| is null");
|
||||
return false;
|
||||
}
|
||||
if (usage_entry_number == nullptr) {
|
||||
LOGE("Output parameter |usage_entry_number| is null");
|
||||
return false;
|
||||
}
|
||||
CdmUsageEntry usage_entry;
|
||||
std::string provider_session_token;
|
||||
CdmKeyMessage license_request;
|
||||
std::string drm_certificate;
|
||||
CryptoWrappedKey wrapped_private_key;
|
||||
if (!device_files->RetrieveUsageInfoByKeySetId(
|
||||
usage_info_file_name, key_set_id, &provider_session_token,
|
||||
&license_request, license_message, &usage_entry, usage_entry_number,
|
||||
&drm_certificate, &wrapped_private_key)) {
|
||||
LOGW(
|
||||
"Failed to retrieve usage information: "
|
||||
"key_set_id = %s, usage_info_file_name = %s",
|
||||
IdToString(key_set_id), IdToString(usage_info_file_name));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EntryIsUsageInfo(const CdmUsageEntryInfo& info) {
|
||||
// Used for stl filters.
|
||||
return info.storage_type == kStorageUsageInfo;
|
||||
@@ -1163,7 +1128,6 @@ CdmResponseType UsageTableHeader::ReleaseOldestEntry(
|
||||
// Capture metric values now, as the |usage_entry_info| reference will
|
||||
// change after the call to invalidate.
|
||||
const int64_t staleness = current_time - usage_entry_info.last_use_time;
|
||||
const CdmUsageEntryStorageType storage_type = usage_entry_info.storage_type;
|
||||
|
||||
const CdmResponseType status =
|
||||
InvalidateEntryInternal(entry_number_to_delete, /* defrag_table = */ true,
|
||||
@@ -1176,7 +1140,7 @@ CdmResponseType UsageTableHeader::ReleaseOldestEntry(
|
||||
}
|
||||
|
||||
// Record metrics on success.
|
||||
RecordLruEventMetrics(metrics, staleness, storage_type);
|
||||
RecordLruEventMetrics(metrics, staleness);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -1209,34 +1173,16 @@ bool UsageTableHeader::LruUpgradeAllUsageEntries() {
|
||||
usage_entry_number < usage_entry_info_.size(); ++usage_entry_number) {
|
||||
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_[usage_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;
|
||||
bool retrieve_response = false;
|
||||
switch (usage_entry_info.storage_type) {
|
||||
case kStorageLicense: {
|
||||
retrieve_response = RetrieveOfflineLicense(
|
||||
device_files_.get(), usage_entry_info.key_set_id, &license_message,
|
||||
&retrieved_entry_number);
|
||||
break;
|
||||
}
|
||||
case kStorageUsageInfo: {
|
||||
retrieve_response = RetrieveUsageInfoLicense(
|
||||
device_files_.get(), usage_entry_info.usage_info_file_name,
|
||||
usage_entry_info.key_set_id, &license_message,
|
||||
&retrieved_entry_number);
|
||||
break;
|
||||
}
|
||||
case kStorageTypeUnknown:
|
||||
bad_license_file_entries.push_back(usage_entry_number);
|
||||
continue;
|
||||
default: {
|
||||
LOGW("Unknown usage entry storage type: %d, usage_entry_number = %u",
|
||||
static_cast<int>(usage_entry_info.storage_type),
|
||||
usage_entry_number);
|
||||
bad_license_file_entries.push_back(usage_entry_number);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const bool retrieve_response =
|
||||
RetrieveOfflineLicense(device_files_.get(), usage_entry_info.key_set_id,
|
||||
&license_message, &retrieved_entry_number);
|
||||
if (!retrieve_response) {
|
||||
LOGW("Could not retrieve license message: usage_entry_number = %u",
|
||||
usage_entry_number);
|
||||
@@ -1265,22 +1211,18 @@ bool UsageTableHeader::LruUpgradeAllUsageEntries() {
|
||||
// for replacement above all others.
|
||||
usage_entry_info.last_use_time = license.license_start_time();
|
||||
|
||||
if (usage_entry_info.storage_type == kStorageLicense) {
|
||||
// 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.
|
||||
usage_entry_info.offline_license_expiry_time =
|
||||
license.license_start_time() + policy.rental_duration_seconds() +
|
||||
policy.playback_duration_seconds();
|
||||
} else {
|
||||
usage_entry_info.offline_license_expiry_time =
|
||||
license.license_start_time() + policy.license_duration_seconds();
|
||||
}
|
||||
// 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.
|
||||
usage_entry_info.offline_license_expiry_time =
|
||||
license.license_start_time() + policy.rental_duration_seconds() +
|
||||
policy.playback_duration_seconds();
|
||||
} else {
|
||||
usage_entry_info.offline_license_expiry_time = 0;
|
||||
usage_entry_info.offline_license_expiry_time =
|
||||
license.license_start_time() + policy.license_duration_seconds();
|
||||
}
|
||||
} // End for loop.
|
||||
|
||||
@@ -1290,31 +1232,14 @@ bool UsageTableHeader::LruUpgradeAllUsageEntries() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Maps <usage_info_file_name> -> [<key_set_id>].
|
||||
std::map<std::string, std::vector<std::string>> usage_info_clean_up;
|
||||
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);
|
||||
} else if (usage_entry_info.storage_type == kStorageUsageInfo) {
|
||||
// To reduce write cycles, the deletion of usage info will be done
|
||||
// in bulk.
|
||||
auto it = usage_info_clean_up.find(usage_entry_info.usage_info_file_name);
|
||||
if (it == usage_info_clean_up.end()) {
|
||||
it = usage_info_clean_up
|
||||
.emplace(usage_entry_info.usage_info_file_name,
|
||||
std::vector<std::string>())
|
||||
.first;
|
||||
}
|
||||
it->second.push_back(usage_entry_info.key_set_id);
|
||||
} // else kStorageUnknown { Nothing special }.
|
||||
}
|
||||
usage_entry_info.Clear();
|
||||
}
|
||||
|
||||
for (const auto& p : usage_info_clean_up) {
|
||||
device_files_->DeleteMultipleUsageInfoByKeySetIds(p.first, p.second);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1327,16 +1252,18 @@ bool UsageTableHeader::GetRemovalCandidate(uint32_t* entry_to_remove) {
|
||||
lru_unexpired_threshold, entry_to_remove);
|
||||
}
|
||||
|
||||
void UsageTableHeader::RecordLruEventMetrics(
|
||||
metrics::CryptoMetrics* metrics, uint64_t staleness,
|
||||
CdmUsageEntryStorageType storage_type) {
|
||||
void UsageTableHeader::RecordLruEventMetrics(metrics::CryptoMetrics* metrics,
|
||||
uint64_t staleness) {
|
||||
if (metrics == nullptr) return;
|
||||
metrics->usage_table_header_lru_usage_info_count_.Record(UsageInfoCount());
|
||||
// Usage info are deprecated, always record 0.
|
||||
metrics->usage_table_header_lru_usage_info_count_.Record(0);
|
||||
metrics->usage_table_header_lru_offline_license_count_.Record(
|
||||
OfflineEntryCount());
|
||||
metrics->usage_table_header_lru_evicted_entry_staleness_.Record(staleness);
|
||||
// Can be assumed that only offline licenses are removed.
|
||||
constexpr int kDefaultEntryType = 0;
|
||||
metrics->usage_table_header_lru_evicted_entry_type_.Record(
|
||||
static_cast<int>(storage_type));
|
||||
static_cast<int>(kDefaultEntryType));
|
||||
}
|
||||
|
||||
// Static.
|
||||
@@ -1359,14 +1286,13 @@ bool UsageTableHeader::DetermineLicenseToRemove(
|
||||
usage_entry_info_list[j].last_use_time;
|
||||
};
|
||||
|
||||
// Find the most stale expired offline / streaming license and the
|
||||
// Find the most stale expired offline license and the
|
||||
// most stale unexpired offline entry. Count the number of unexpired
|
||||
// entries. If any entry is of storage type unknown, then it should
|
||||
// entries. If any entry is not of storage type license, then it should
|
||||
// be removed.
|
||||
constexpr uint32_t kNoEntry = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t stalest_expired_offline_license = kNoEntry;
|
||||
uint32_t stalest_unexpired_offline_license = kNoEntry;
|
||||
uint32_t stalest_streaming_license = kNoEntry;
|
||||
size_t unexpired_license_count = 0;
|
||||
|
||||
for (uint32_t entry_number = 0; entry_number < usage_entry_info_list.size();
|
||||
@@ -1374,37 +1300,28 @@ bool UsageTableHeader::DetermineLicenseToRemove(
|
||||
const CdmUsageEntryInfo& usage_entry_info =
|
||||
usage_entry_info_list[entry_number];
|
||||
|
||||
if (usage_entry_info.storage_type != kStorageLicense &&
|
||||
usage_entry_info.storage_type != kStorageUsageInfo) {
|
||||
// Unknown storage type entries. Remove this entry.
|
||||
if (usage_entry_info.storage_type != kStorageLicense) {
|
||||
// Non-license storage type entries. Remove this entry.
|
||||
*entry_to_remove = entry_number;
|
||||
return true;
|
||||
}
|
||||
if (usage_entry_info.storage_type == kStorageLicense &&
|
||||
usage_entry_info.offline_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 ||
|
||||
is_more_stale(entry_number, stalest_unexpired_offline_license)) {
|
||||
stalest_unexpired_offline_license = entry_number;
|
||||
}
|
||||
} else if (usage_entry_info.storage_type == kStorageLicense) {
|
||||
} else {
|
||||
// Expired offline.
|
||||
if (stalest_expired_offline_license == kNoEntry ||
|
||||
is_more_stale(entry_number, stalest_expired_offline_license)) {
|
||||
stalest_expired_offline_license = entry_number;
|
||||
}
|
||||
} else {
|
||||
// Streaming.
|
||||
if (stalest_streaming_license == kNoEntry ||
|
||||
is_more_stale(entry_number, stalest_streaming_license)) {
|
||||
stalest_streaming_license = entry_number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stalest_expired_offline_license == kNoEntry &&
|
||||
stalest_streaming_license == kNoEntry &&
|
||||
unexpired_license_count <= unexpired_threshold) {
|
||||
// Unexpected situation, could be an issue with the threshold.
|
||||
LOGW(
|
||||
@@ -1424,12 +1341,10 @@ bool UsageTableHeader::DetermineLicenseToRemove(
|
||||
|
||||
// Only consider an unexpired entry if the threshold is reached.
|
||||
if (unexpired_license_count > unexpired_threshold) {
|
||||
const uint32_t temp = select_most_stale(stalest_unexpired_offline_license,
|
||||
stalest_streaming_license);
|
||||
*entry_to_remove = select_most_stale(temp, stalest_expired_offline_license);
|
||||
} else {
|
||||
*entry_to_remove = select_most_stale(stalest_streaming_license,
|
||||
*entry_to_remove = select_most_stale(stalest_unexpired_offline_license,
|
||||
stalest_expired_offline_license);
|
||||
} else {
|
||||
*entry_to_remove = stalest_expired_offline_license;
|
||||
}
|
||||
|
||||
if (*entry_to_remove == kNoEntry) {
|
||||
|
||||
@@ -229,9 +229,9 @@ const CdmKeyResponse kKeyRenewalResponse = "key renewal response";
|
||||
const std::string kReleaseServerUrl = "some url";
|
||||
const std::string kProviderSessionToken = "provider session token";
|
||||
const CdmAppParameterMap kEmptyAppParameters;
|
||||
int64_t kPlaybackStartTime = 1030005;
|
||||
int64_t kPlaybackDuration = 300;
|
||||
int64_t kGracePeriodEndTime = 60;
|
||||
constexpr int64_t kPlaybackStartTime = 1030005;
|
||||
constexpr int64_t kPlaybackDuration = 300;
|
||||
constexpr int64_t kGracePeriodEndTime = 60;
|
||||
|
||||
// ==== LRU Upgrade Data ====
|
||||
const CdmUsageTableHeader kUpgradableUsageTableHeader =
|
||||
@@ -245,9 +245,9 @@ const CdmUsageEntryInfo kUpgradableUsageEntryInfo1 = {
|
||||
/* last_use_time = */ 0,
|
||||
/* offline_license_expiry_time = */ 0};
|
||||
const CdmUsageEntryInfo kUpgradableUsageEntryInfo2 = {
|
||||
/* storage_type = */ kStorageUsageInfo,
|
||||
/* key_set_id = */ "streaming_key_set_2",
|
||||
/* usage_info_file_name = */ "streaming_license_file_2",
|
||||
/* 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 = {
|
||||
@@ -256,7 +256,11 @@ const CdmUsageEntryInfo kUpgradableUsageEntryInfo3 = {
|
||||
/* usage_info_file_name = */ "",
|
||||
/* last_use_time = */ 0,
|
||||
/* offline_license_expiry_time = */ 0};
|
||||
std::vector<CdmUsageEntryInfo> kUpgradableUsageEntryInfoList;
|
||||
const std::vector<CdmUsageEntryInfo> kUpgradableUsageEntryInfoList{
|
||||
kUpgradableUsageEntryInfo1, kUpgradableUsageEntryInfo2,
|
||||
kUpgradableUsageEntryInfo3};
|
||||
|
||||
const int64_t kLruBaseTime = 1563399000;
|
||||
|
||||
// Offline license 1.
|
||||
// license_start_time = 1563399000
|
||||
@@ -266,11 +270,14 @@ std::vector<CdmUsageEntryInfo> kUpgradableUsageEntryInfoList;
|
||||
const CdmKeyResponse kUpgradableLicenseInfo1 = wvutil::a2bs_hex(
|
||||
"08021214120C2080F5242880A3053080E90F20D8A6BEE9051A20D5F7ACE8D84A166C69BB"
|
||||
"27523C84C019464B90AA9BF06B8332004839119BFD14");
|
||||
// Streaming license 2.
|
||||
// Offline license 2.
|
||||
// license_start_time = 1563399000
|
||||
// license_duration_seconds = 259200 (3 days)
|
||||
// rental_duration_seconds = 0 (unlimited)
|
||||
// playback_duration_seconds = 0 (unlimited)
|
||||
const CdmKeyResponse kUpgradableLicenseInfo2 = wvutil::a2bs_hex(
|
||||
"0802120620D8A6BEE9051A201956F2FD69E5E96DA8C65FDD04A3C294E484F219F2B1A8DD"
|
||||
"C2B0737F6EF5BD22");
|
||||
"080212101208200028003080E90F20D8A6BEE9051A20D0611C4AFEF3EC9C67143ED39B44"
|
||||
"8FAAA67DB6C4DBFDC28A733AF9A2EABDF0B3");
|
||||
// Offline license 3.
|
||||
// license_start_time = 1563399000
|
||||
// license_duration_seconds = 0 (unlimited)
|
||||
@@ -279,26 +286,56 @@ const CdmKeyResponse kUpgradableLicenseInfo2 = wvutil::a2bs_hex(
|
||||
const CdmKeyResponse kUpgradableLicenseInfo3 = wvutil::a2bs_hex(
|
||||
"08021212120A2080F5242880A305300020D8A6BEE9051A207B09896F46C4EE443170E215"
|
||||
"B2D8D5F072951027B152F4758AC3A339D7C7B4CE");
|
||||
std::vector<CdmKeyResponse> kUpgradableLicenseInfoList;
|
||||
std::vector<DeviceFiles::CdmLicenseData> kUpgradableLicenseDataList;
|
||||
const std::vector<CdmKeyResponse> kUpgradableLicenseInfoList = {
|
||||
kUpgradableLicenseInfo1, kUpgradableLicenseInfo2, kUpgradableLicenseInfo3};
|
||||
|
||||
// Same as Offline license 1, but without signature.
|
||||
const CdmKeyResponse kUnsignedUpgradableLicenseInfo1 =
|
||||
wvutil::a2bs_hex("08021214120C2080F5242880A3053080E90F20D8A6BEE905");
|
||||
// Same as streaming license 2, but message type is certificate, not license.
|
||||
const CdmKeyResponse kWrongTypedUpgradableLicenseInfo2 = wvutil::a2bs_hex(
|
||||
"0805120620D8A6BEE9051A201956F2FD69E5E96DA8C65FDD04A3C294E484F219F2B1A8DD"
|
||||
"C2B0737F6EF5BD22");
|
||||
|
||||
const int64_t kLruBaseTime = 1563399000;
|
||||
const int64_t kUpgradedUsageEntryInfo1LastUsedTime = kLruBaseTime;
|
||||
const int64_t kUpgradedUsageEntryInfo1ExpireTime = kLruBaseTime + 259200;
|
||||
const int64_t kUpgradedUsageEntryInfo2LastUsedTime = kLruBaseTime;
|
||||
const int64_t kUpgradedUsageEntryInfo2ExpireTime = 0; // Unset
|
||||
const int64_t kUpgradedUsageEntryInfo2ExpireTime = kLruBaseTime + 259200;
|
||||
const int64_t kUpgradedUsageEntryInfo3LastUsedTime = kLruBaseTime;
|
||||
const int64_t kUpgradedUsageEntryInfo3ExpireTime =
|
||||
kLruBaseTime + 604800 + 86400;
|
||||
const CdmUsageTableHeader kUpgradedUsageTableHeader = "Upgraded Table Header";
|
||||
std::vector<CdmUsageEntryInfo> kUpgradedUsageEntryInfoList;
|
||||
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};
|
||||
|
||||
const std::vector<CdmUsageEntryInfo> kUpgradedUsageEntryInfoList = {
|
||||
kUpgradedUsageEntryInfo1, kUpgradedUsageEntryInfo2,
|
||||
kUpgradedUsageEntryInfo3};
|
||||
|
||||
std::vector<DeviceFiles::CdmLicenseData> CreateUpgradableLicenseInfoList() {
|
||||
std::vector<DeviceFiles::CdmLicenseData> 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.state = kActiveLicenseState;
|
||||
license_data.license = kUpgradableLicenseInfoList[i];
|
||||
license_data.usage_entry_number = static_cast<uint32_t>(i);
|
||||
license_data_list.push_back(license_data);
|
||||
}
|
||||
return license_data_list;
|
||||
}
|
||||
|
||||
void InitVectorConstants() {
|
||||
kOverFullUsageEntryInfoVector.clear();
|
||||
@@ -332,40 +369,6 @@ void InitVectorConstants() {
|
||||
for (size_t i = 0; i < kLicenseArraySize; i++) {
|
||||
kLicenseList.push_back(kLicenseArray[i]);
|
||||
}
|
||||
|
||||
// LRU Data.
|
||||
kUpgradableUsageEntryInfoList.push_back(kUpgradableUsageEntryInfo1);
|
||||
kUpgradableUsageEntryInfoList.push_back(kUpgradableUsageEntryInfo2);
|
||||
kUpgradableUsageEntryInfoList.push_back(kUpgradableUsageEntryInfo3);
|
||||
|
||||
kUpgradableLicenseInfoList.push_back(kUpgradableLicenseInfo1);
|
||||
kUpgradableLicenseInfoList.push_back(kUpgradableLicenseInfo2);
|
||||
kUpgradableLicenseInfoList.push_back(kUpgradableLicenseInfo3);
|
||||
|
||||
kUpgradedUsageEntryInfoList.push_back(kUpgradableUsageEntryInfo1);
|
||||
kUpgradedUsageEntryInfoList.back().last_use_time =
|
||||
kUpgradedUsageEntryInfo1LastUsedTime;
|
||||
kUpgradedUsageEntryInfoList.back().offline_license_expiry_time =
|
||||
kUpgradedUsageEntryInfo1ExpireTime;
|
||||
kUpgradedUsageEntryInfoList.push_back(kUpgradableUsageEntryInfo2);
|
||||
kUpgradedUsageEntryInfoList.back().last_use_time =
|
||||
kUpgradedUsageEntryInfo2LastUsedTime;
|
||||
kUpgradedUsageEntryInfoList.back().offline_license_expiry_time =
|
||||
kUpgradedUsageEntryInfo2ExpireTime;
|
||||
kUpgradedUsageEntryInfoList.push_back(kUpgradableUsageEntryInfo3);
|
||||
kUpgradedUsageEntryInfoList.back().last_use_time =
|
||||
kUpgradedUsageEntryInfo3LastUsedTime;
|
||||
kUpgradedUsageEntryInfoList.back().offline_license_expiry_time =
|
||||
kUpgradedUsageEntryInfo3ExpireTime;
|
||||
|
||||
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.state = kActiveLicenseState;
|
||||
license_data.license = kUpgradableLicenseInfoList[i];
|
||||
license_data.usage_entry_number = static_cast<uint32_t>(i);
|
||||
kUpgradableLicenseDataList.push_back(license_data);
|
||||
}
|
||||
}
|
||||
|
||||
void ToVector(std::vector<CdmUsageEntryInfo>& vec, const CdmUsageEntryInfo* arr,
|
||||
@@ -402,9 +405,6 @@ class MockDeviceFiles : public DeviceFiles {
|
||||
(override));
|
||||
MOCK_METHOD(bool, DeleteUsageInfo, (const std::string&, const std::string&),
|
||||
(override));
|
||||
MOCK_METHOD(bool, DeleteMultipleUsageInfoByKeySetIds,
|
||||
(const std::string&, const std::vector<std::string>&),
|
||||
(override));
|
||||
MOCK_METHOD(bool, RetrieveUsageInfoByKeySetId,
|
||||
(const std::string&, const std::string&, std::string*,
|
||||
CdmKeyMessage*, CdmKeyResponse*, CdmUsageEntry*, uint32_t*,
|
||||
@@ -3728,9 +3728,6 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_NoAction) {
|
||||
|
||||
// These function are called specifically by the LRU upgrading system.
|
||||
EXPECT_CALL(*device_files_, RetrieveLicense(_, _, _)).Times(0);
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveUsageInfoByKeySetId(_, _, _, _, _, _, _, _, _))
|
||||
.Times(0);
|
||||
|
||||
EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_));
|
||||
EXPECT_EQ(usage_table_header_->usage_entry_info(),
|
||||
@@ -3740,8 +3737,8 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_NoAction) {
|
||||
// Initial Test state:
|
||||
// 1. Table info is load from device files; however, device files reports
|
||||
// that the table has not been configured for upgrade.
|
||||
// 2. The usage table header will load license or usage information to
|
||||
// determine appropriate expiry and last_used times.
|
||||
// 2. The usage table header will load offline license to determine
|
||||
// appropriate expiry and last_used times.
|
||||
TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_Succeed) {
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
GetNumberOfOpenSessions(kLevelDefault, NotNull()))
|
||||
@@ -3756,24 +3753,18 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_Succeed) {
|
||||
LoadUsageTableHeader(kLevelDefault, kUpgradableUsageTableHeader))
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
|
||||
const std::vector<DeviceFiles::CdmLicenseData> license_info_list =
|
||||
CreateUpgradableLicenseInfoList();
|
||||
|
||||
for (size_t i = 0; i < kUpgradableUsageEntryInfoList.size(); ++i) {
|
||||
const CdmUsageEntryInfo& info = kUpgradableUsageEntryInfoList[i];
|
||||
|
||||
if (info.storage_type == kStorageLicense) {
|
||||
// Only offline licenses are supported.
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveLicense(info.key_set_id, NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kUpgradableLicenseDataList[i]),
|
||||
Return(true)));
|
||||
} else {
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveUsageInfoByKeySetId(info.usage_info_file_name,
|
||||
info.key_set_id, NotNull(),
|
||||
NotNull(), NotNull(), NotNull(),
|
||||
NotNull(), NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<4>(kUpgradableLicenseInfoList[i]),
|
||||
SetArgPointee<6>(static_cast<uint32_t>(i)),
|
||||
SetArgPointee<7>(kDrmCertificate),
|
||||
SetArgPointee<8>(kCryptoWrappedKey), Return(true)));
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<1>(license_info_list[i]), Return(true)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3783,33 +3774,22 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_Succeed) {
|
||||
}
|
||||
|
||||
// Initial Test state:
|
||||
// 1. Table info is load from device files and must be upgraded.
|
||||
// A few entries have the incorrect storage type value.
|
||||
// 2. During the LRU upgrade process, any license that cannot be
|
||||
// validated are cleared, and marked to be deleted.
|
||||
// Table info is load from device files and must be upgraded.
|
||||
// A few entries have the unknown storage type value.
|
||||
//
|
||||
// Entry# Storage type Result info
|
||||
// ====== ============ ===========
|
||||
// 0 Offline Upgraded
|
||||
// 1 Unknown Cleared
|
||||
// 2 Invalid (99) Cleared
|
||||
// 2 Unknown Cleared
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
LruUsageTableUpgrade_PartialSucceedWithUnknownStorageTypes) {
|
||||
std::vector<CdmUsageEntryInfo> upgradable_usage_entry_info_list =
|
||||
kUpgradableUsageEntryInfoList;
|
||||
std::vector<CdmUsageEntryInfo> upgraded_usage_entry_info_list =
|
||||
kUpgradedUsageEntryInfoList;
|
||||
|
||||
// Set the wrong storage type.
|
||||
upgradable_usage_entry_info_list[1].storage_type = kStorageTypeUnknown;
|
||||
upgradable_usage_entry_info_list[2].storage_type =
|
||||
static_cast<CdmUsageEntryStorageType>(99);
|
||||
|
||||
// Set the expected output.
|
||||
upgraded_usage_entry_info_list[1] = CdmUsageEntryInfo{};
|
||||
upgraded_usage_entry_info_list[1].storage_type = kStorageTypeUnknown;
|
||||
upgraded_usage_entry_info_list[2] = CdmUsageEntryInfo{};
|
||||
upgraded_usage_entry_info_list[2].storage_type = kStorageTypeUnknown;
|
||||
const std::vector<CdmUsageEntryInfo> upgradable_usage_entry_info_list = {
|
||||
kUpgradableUsageEntryInfo1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoStorageTypeUnknown};
|
||||
const std::vector<CdmUsageEntryInfo> upgraded_usage_entry_info_list = {
|
||||
kUpgradedUsageEntryInfo1, kUsageEntryInfoStorageTypeUnknown,
|
||||
kUsageEntryInfoStorageTypeUnknown};
|
||||
|
||||
// Load table expectations.
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
@@ -3826,11 +3806,12 @@ TEST_F(UsageTableHeaderTest,
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
|
||||
// Expectations of the one successful license.
|
||||
const std::vector<DeviceFiles::CdmLicenseData> license_info_list =
|
||||
CreateUpgradableLicenseInfoList();
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveLicense(upgradable_usage_entry_info_list[0].key_set_id,
|
||||
NotNull(), NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<1>(kUpgradableLicenseDataList[0]), Return(true)));
|
||||
.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,
|
||||
@@ -3846,12 +3827,14 @@ TEST_F(UsageTableHeaderTest,
|
||||
// Entry# Storage type License Issue Result info
|
||||
// ====== ============ ============= ===========
|
||||
// 0 Offline No signature Cleared
|
||||
// 1 Streaming Wrong type Cleared
|
||||
// 1 Unknown Clear entry Cleared
|
||||
// 2 Offline Upgraded
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
LruUsageTableUpgrade_PartialSucceedWithLicenseParseIssues) {
|
||||
std::vector<CdmUsageEntryInfo> upgradable_usage_entry_info_list =
|
||||
kUpgradableUsageEntryInfoList;
|
||||
std::vector<DeviceFiles::CdmLicenseData> license_data_list =
|
||||
kUpgradableLicenseDataList;
|
||||
CreateUpgradableLicenseInfoList();
|
||||
std::vector<CdmKeyResponse> upgradable_license_info_list =
|
||||
kUpgradableLicenseInfoList;
|
||||
std::vector<CdmUsageEntryInfo> upgraded_usage_entry_info_list =
|
||||
@@ -3859,21 +3842,12 @@ TEST_F(UsageTableHeaderTest,
|
||||
|
||||
// Modify entry 0 to be invalid.
|
||||
license_data_list[0].license = kUnsignedUpgradableLicenseInfo1;
|
||||
CdmUsageEntryInfo& unsigned_usage_entry_info =
|
||||
upgraded_usage_entry_info_list[0];
|
||||
unsigned_usage_entry_info.storage_type = kStorageTypeUnknown;
|
||||
unsigned_usage_entry_info.key_set_id.clear();
|
||||
unsigned_usage_entry_info.last_use_time = 0;
|
||||
unsigned_usage_entry_info.offline_license_expiry_time = 0;
|
||||
upgraded_usage_entry_info_list[0].Clear();
|
||||
|
||||
// Modify entry 1 to be invalid.
|
||||
upgradable_license_info_list[1] = kWrongTypedUpgradableLicenseInfo2;
|
||||
CdmUsageEntryInfo& wrond_typed_usage_entry_info =
|
||||
upgraded_usage_entry_info_list[1];
|
||||
wrond_typed_usage_entry_info.storage_type = kStorageTypeUnknown;
|
||||
wrond_typed_usage_entry_info.key_set_id.clear();
|
||||
wrond_typed_usage_entry_info.last_use_time = 0;
|
||||
wrond_typed_usage_entry_info.offline_license_expiry_time = 0;
|
||||
// Modify entry 1 to be clear.
|
||||
upgradable_usage_entry_info_list[1].Clear();
|
||||
upgradable_license_info_list[1].clear();
|
||||
upgraded_usage_entry_info_list[1].Clear();
|
||||
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
GetNumberOfOpenSessions(kLevelDefault, NotNull()))
|
||||
@@ -3881,46 +3855,27 @@ TEST_F(UsageTableHeaderTest,
|
||||
EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull(),
|
||||
NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kUpgradableUsageTableHeader),
|
||||
SetArgPointee<1>(kUpgradableUsageEntryInfoList),
|
||||
SetArgPointee<1>(upgradable_usage_entry_info_list),
|
||||
SetArgPointee<2>(/* lru_upgrade = */ true),
|
||||
SetArgPointee<3>(false), Return(true)));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
LoadUsageTableHeader(kLevelDefault, kUpgradableUsageTableHeader))
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
|
||||
for (size_t i = 0; i < kUpgradableUsageEntryInfoList.size(); ++i) {
|
||||
const CdmUsageEntryInfo& info = kUpgradableUsageEntryInfoList[i];
|
||||
for (size_t i = 0; i < upgradable_usage_entry_info_list.size(); ++i) {
|
||||
const CdmUsageEntryInfo& info = upgradable_usage_entry_info_list[i];
|
||||
if (info.storage_type == kStorageLicense) {
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveLicense(info.key_set_id, NotNull(), NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<1>(license_data_list[i]), Return(true)));
|
||||
} else {
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveUsageInfoByKeySetId(info.usage_info_file_name,
|
||||
info.key_set_id, NotNull(),
|
||||
NotNull(), NotNull(), NotNull(),
|
||||
NotNull(), NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<4>(upgradable_license_info_list[i]),
|
||||
SetArgPointee<6>(static_cast<uint32_t>(i)),
|
||||
SetArgPointee<7>(kDrmCertificate),
|
||||
SetArgPointee<8>(kCryptoWrappedKey), Return(true)));
|
||||
}
|
||||
}
|
||||
|
||||
// For the entries which failed, there should be an attempt to delete the
|
||||
// files associated with them.
|
||||
// Offline license.
|
||||
EXPECT_CALL(*device_files_,
|
||||
DeleteLicense(kUpgradableUsageEntryInfoList[0].key_set_id))
|
||||
.WillOnce(Return(true));
|
||||
// Streaming license.
|
||||
const std::vector<std::string> corrupted_usage_info_key_set_ids = {
|
||||
kUpgradableUsageEntryInfoList[1].key_set_id};
|
||||
EXPECT_CALL(*device_files_,
|
||||
DeleteMultipleUsageInfoByKeySetIds(
|
||||
kUpgradableUsageEntryInfoList[1].usage_info_file_name,
|
||||
ContainerEq(corrupted_usage_info_key_set_ids)))
|
||||
DeleteLicense(upgradable_usage_entry_info_list[0].key_set_id))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_));
|
||||
@@ -3953,13 +3908,6 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_AllFailure) {
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveLicense(info.key_set_id, NotNull(), NotNull()))
|
||||
.WillOnce(Return(false));
|
||||
} else {
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveUsageInfoByKeySetId(info.usage_info_file_name,
|
||||
info.key_set_id, NotNull(),
|
||||
NotNull(), NotNull(), NotNull(),
|
||||
NotNull(), NotNull(), NotNull()))
|
||||
.WillOnce(Return(false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4007,46 +3955,7 @@ TEST_F(UsageTableHeaderTest, LruLastUsedTime_CreateLicenseEntry) {
|
||||
EXPECT_EQ(NO_ERROR, usage_table_header_->AddEntry(
|
||||
crypto_session_, true /* persistent_license */,
|
||||
expected_new_entry.key_set_id,
|
||||
expected_new_entry.usage_info_file_name, kEmptyString,
|
||||
&usage_entry_number));
|
||||
|
||||
EXPECT_EQ(expected_usage_entry_number, usage_entry_number);
|
||||
EXPECT_EQ(expected_usage_info_list, usage_table_header_->usage_entry_info());
|
||||
}
|
||||
|
||||
TEST_F(UsageTableHeaderTest, LruLastUsedTime_CreateUsageInfoEntry) {
|
||||
Init(kSecurityLevelL1, kUpgradedUsageTableHeader,
|
||||
kUpgradedUsageEntryInfoList);
|
||||
|
||||
// Expected values.
|
||||
const uint32_t expected_usage_entry_number =
|
||||
static_cast<uint32_t>(kUpgradedUsageEntryInfoList.size());
|
||||
const CdmUsageEntryInfo expected_new_entry = {
|
||||
kStorageUsageInfo, "secure_stop_key_set_5", "streaming_license_file_4",
|
||||
kLruBaseTime, 0 /* No set for streaming license. */
|
||||
};
|
||||
std::vector<CdmUsageEntryInfo> expected_usage_info_list =
|
||||
kUpgradedUsageEntryInfoList;
|
||||
expected_usage_info_list.push_back(expected_new_entry);
|
||||
|
||||
// AddKey expectations
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageEntry(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(expected_usage_entry_number),
|
||||
Return(NO_ERROR)));
|
||||
MockClock mock_clock;
|
||||
usage_table_header_->SetClock(&mock_clock);
|
||||
EXPECT_CALL(mock_clock, GetCurrentTime()).WillOnce(Return(kLruBaseTime));
|
||||
EXPECT_CALL(*crypto_session_, UpdateUsageEntry(NotNull(), NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kAnotherUsageTableHeader), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kAnotherUsageTableHeader, _));
|
||||
|
||||
// The Call.
|
||||
uint32_t usage_entry_number = 0;
|
||||
EXPECT_EQ(NO_ERROR, usage_table_header_->AddEntry(
|
||||
crypto_session_, false /* persistent_license */,
|
||||
expected_new_entry.key_set_id,
|
||||
expected_new_entry.usage_info_file_name, kEmptyString,
|
||||
/* usage_info_file_name */ kEmptyString, kEmptyString,
|
||||
&usage_entry_number));
|
||||
|
||||
EXPECT_EQ(expected_usage_entry_number, usage_entry_number);
|
||||
@@ -4151,6 +4060,7 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) {
|
||||
// Unexpired offline license.
|
||||
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);
|
||||
@@ -4159,59 +4069,43 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) {
|
||||
// Expired offline license.
|
||||
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;
|
||||
|
||||
// Streaming license.
|
||||
CdmUsageEntryInfo streaming_entry_info;
|
||||
streaming_entry_info.storage_type = kStorageUsageInfo;
|
||||
streaming_entry_info.last_use_time = kLruBaseTime;
|
||||
usage_entry_info_list.push_back(streaming_entry_info);
|
||||
constexpr uint32_t streaming_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 = 3;
|
||||
constexpr uint32_t unknown_entry_number = 2;
|
||||
|
||||
// Case 1: If there is an entry with unknown storage type, it should
|
||||
// be selected above any other entry.
|
||||
// Case 1: If there is a clear entry, it should be selected above
|
||||
// any other entry.
|
||||
uint32_t entry_to_remove = kInvalidEntry;
|
||||
|
||||
// Expect the unknown entry.
|
||||
// Expect the clear.
|
||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||
usage_entry_info_list, kCurrentTime,
|
||||
/* unexpired_threshold = */ 3, &entry_to_remove));
|
||||
EXPECT_EQ(unknown_entry_number, entry_to_remove);
|
||||
|
||||
usage_entry_info_list.pop_back(); // Removing unknown.
|
||||
usage_entry_info_list.pop_back(); // Removing clear entry.
|
||||
// |usage_entry_info_list| only contains 1 expired and 1 unexpired offline
|
||||
// license.
|
||||
|
||||
// Case 2a: Threshold not met, all entries are equally stale.
|
||||
// The expired entry should be selected over the streaming license.
|
||||
// The expired entry should be selected over the unexpired entry.
|
||||
entry_to_remove = kInvalidEntry;
|
||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||
usage_entry_info_list, kCurrentTime,
|
||||
/* unexpired_threshold = */ 3, &entry_to_remove));
|
||||
EXPECT_EQ(expired_entry_number, entry_to_remove);
|
||||
|
||||
// Case 2b: Threshold not met, streaming license is most stale.
|
||||
usage_entry_info_list[streaming_entry_number].last_use_time--;
|
||||
entry_to_remove = kInvalidEntry;
|
||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||
usage_entry_info_list, kCurrentTime,
|
||||
/* unexpired_threshold = */ 3, &entry_to_remove));
|
||||
EXPECT_EQ(streaming_entry_number, entry_to_remove);
|
||||
|
||||
usage_entry_info_list.pop_back(); // Removing streaming.
|
||||
// |usage_entry_info_list| only contains 1 expired and 1 unexpired offline
|
||||
// license.
|
||||
|
||||
// Case 2c: Threshold met, equally stale entries. Expect the expired
|
||||
// Case 2b: Threshold met, equally stale entries. Expect the expired
|
||||
// entry over the unexpired.
|
||||
entry_to_remove = kInvalidEntry;
|
||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||
@@ -4273,45 +4167,8 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) {
|
||||
EXPECT_EQ(unexpired_entry_number, entry_to_remove);
|
||||
}
|
||||
|
||||
// Testing algorithm with unexpired offline and streaming license. The
|
||||
// sum of offline licenses is below the threshold for consideration.
|
||||
// Only the streaming license should be considered for removal.
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
DetermineLicenseToRemove_NoExpiredAndBelowThreshold) {
|
||||
constexpr int64_t kOneDay = 24 * 60 * 60;
|
||||
constexpr uint32_t kInvalidEntry = 9999;
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_list =
|
||||
kUpgradedUsageEntryInfoList;
|
||||
const size_t offline_threshold = usage_entry_info_list.size() + 1;
|
||||
|
||||
size_t usage_info_count = 0;
|
||||
for (auto& usage_entry_info : usage_entry_info_list) {
|
||||
if (usage_entry_info.storage_type == kStorageUsageInfo) {
|
||||
// Make usage info entries less stale than offline.
|
||||
usage_entry_info.last_use_time += 100;
|
||||
++usage_info_count;
|
||||
} else {
|
||||
// Make offline licenses unexpired.
|
||||
usage_entry_info.offline_license_expiry_time =
|
||||
kLruBaseTime + kOneDay * 30;
|
||||
}
|
||||
}
|
||||
|
||||
// Must exist at least one streaming license for test to work.
|
||||
ASSERT_LT(0ull, usage_info_count);
|
||||
|
||||
uint32_t entry_to_remove = kInvalidEntry;
|
||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||
usage_entry_info_list, kLruBaseTime, offline_threshold,
|
||||
&entry_to_remove));
|
||||
|
||||
EXPECT_EQ(kStorageUsageInfo,
|
||||
usage_entry_info_list[entry_to_remove].storage_type);
|
||||
}
|
||||
|
||||
// When the number of unexpired offline licenses are below the
|
||||
// threshold, only streaming licenses and expired offline licenses
|
||||
// should be considered.
|
||||
// threshold, only expired offline licenses should be considered.
|
||||
// Providing only offline licenses, only the expired license should be
|
||||
// considered for removal.
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
@@ -4330,20 +4187,20 @@ TEST_F(UsageTableHeaderTest,
|
||||
for (uint32_t i = 0; i < kSetSize; ++i) {
|
||||
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[i];
|
||||
usage_entry_info.storage_type = kStorageLicense;
|
||||
usage_entry_info.key_set_id = "nothing_unusual";
|
||||
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 3 as expired.
|
||||
// Mark three licenses as expired.
|
||||
std::vector<uint32_t> expired_license_numbers;
|
||||
while (expired_license_numbers.size() < 3) {
|
||||
const uint32_t i =
|
||||
static_cast<uint32_t>(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 != "nothing_unusual") continue;
|
||||
if (usage_entry_info.key_set_id != "unexpired_offline") continue;
|
||||
// Make these less stale than the unexpired licenses.
|
||||
usage_entry_info.last_use_time = kLruBaseTime + kOneDay;
|
||||
usage_entry_info.offline_license_expiry_time = kCurrentTime - kOneDay;
|
||||
@@ -4359,16 +4216,31 @@ TEST_F(UsageTableHeaderTest,
|
||||
EXPECT_THAT(expired_license_numbers, Contains(entry_to_remove));
|
||||
}
|
||||
|
||||
// This test primarily tests the robustness of the algorithm for a full
|
||||
// set of entries (200). Creates 1 stale streaming license and 1
|
||||
// offline licenses which are more stale than the streaming.
|
||||
// This primarily tests the robustness of the algorithm for a full
|
||||
// set of entries (200). Creates 1 offline license which are more
|
||||
// stale than the all other licenses.
|
||||
//
|
||||
// First, with the stale offline licenses unexpired, checks that the
|
||||
// streaming are always selected, so long as |unexpired_threshold|
|
||||
// is not met.
|
||||
// All cases: 1 unexpired license is most stale.
|
||||
//
|
||||
// Second, with the stale offline license marked as expired, checks that
|
||||
// offline licenses are selected over the streaming.
|
||||
// Case 1:
|
||||
// - Unexpired threshold met: No
|
||||
// - Exists expired license: No
|
||||
// - Expect most stale license to be selected
|
||||
//
|
||||
// Case 2:
|
||||
// - Unexpired threshold met: Yes
|
||||
// - Exists expired license: No
|
||||
// - Expect most stale license to be selected
|
||||
//
|
||||
// Case 3:
|
||||
// - Unexpired threshold met: No
|
||||
// - Exists expired license: Yes
|
||||
// - Expect expired license to be selected
|
||||
//
|
||||
// Case 4:
|
||||
// - Unexpired threshold met: Yes
|
||||
// - Exists expired license: Yes
|
||||
// - Expect most stale license to be selected
|
||||
TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_LargeMixedSet) {
|
||||
constexpr int64_t kOneDay = 24 * 60 * 60;
|
||||
constexpr size_t kLargeSetSize = 200;
|
||||
@@ -4377,74 +4249,63 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_LargeMixedSet) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_list;
|
||||
usage_entry_info_list.resize(kLargeSetSize);
|
||||
|
||||
// Create a set of usage entries.
|
||||
// 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.key_set_id = "nothing_unusual";
|
||||
usage_entry_info.storage_type = kStorageLicense;
|
||||
usage_entry_info.key_set_id = "unexpired_offline";
|
||||
usage_entry_info.last_use_time = kLruBaseTime + kOneDay;
|
||||
if ((i % 4) == 0) {
|
||||
// Roughly 25% are offline, the rest are streaming.
|
||||
usage_entry_info.storage_type = kStorageLicense;
|
||||
usage_entry_info.offline_license_expiry_time =
|
||||
kCurrentTime + kDefaultExpireDuration;
|
||||
} else {
|
||||
usage_entry_info.storage_type = kStorageUsageInfo;
|
||||
}
|
||||
}
|
||||
|
||||
// Select a streaming license to be more stale than the rest.
|
||||
uint32_t modified_usage_info_number = kInvalidEntry;
|
||||
while (modified_usage_info_number == kInvalidEntry) {
|
||||
const uint32_t i = static_cast<uint32_t>(
|
||||
wvutil::CdmRandom::RandomInRange(kLargeSetSize - 1));
|
||||
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[i];
|
||||
// Skip offline licenses.
|
||||
if (usage_entry_info.storage_type != kStorageUsageInfo) continue;
|
||||
usage_entry_info.last_use_time = kLruBaseTime + 10;
|
||||
usage_entry_info.key_set_id = "stale_streaming";
|
||||
modified_usage_info_number = i;
|
||||
usage_entry_info.offline_license_expiry_time =
|
||||
kCurrentTime + kDefaultExpireDuration;
|
||||
}
|
||||
|
||||
// Select a offline license to be even more stale, but unexpired.
|
||||
uint32_t modified_offline_license_number = kInvalidEntry;
|
||||
while (modified_offline_license_number == kInvalidEntry) {
|
||||
const uint32_t i = static_cast<uint32_t>(
|
||||
wvutil::CdmRandom::RandomInRange(kLargeSetSize - 1));
|
||||
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[i];
|
||||
// Skip streaming licenses.
|
||||
if (usage_entry_info.storage_type != kStorageLicense) continue;
|
||||
usage_entry_info.last_use_time = kLruBaseTime;
|
||||
usage_entry_info.key_set_id = "stale_offline";
|
||||
modified_offline_license_number = i;
|
||||
}
|
||||
const uint32_t most_stale_offline_license_number = static_cast<uint32_t>(
|
||||
wvutil::CdmRandom::RandomInRange(kLargeSetSize - 1));
|
||||
CdmUsageEntryInfo& usage_entry_info =
|
||||
usage_entry_info_list[most_stale_offline_license_number];
|
||||
usage_entry_info.last_use_time = kLruBaseTime;
|
||||
usage_entry_info.key_set_id = "stale_offline";
|
||||
|
||||
// Test using only streaming and expired offline licenses
|
||||
// (which there are none).
|
||||
// Case 1: Most stale license is selected.
|
||||
uint32_t entry_to_remove = kInvalidEntry;
|
||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||
usage_entry_info_list, kCurrentTime,
|
||||
/* unexpired_threshold = */ kLargeSetSize, &entry_to_remove));
|
||||
EXPECT_EQ(modified_usage_info_number, entry_to_remove);
|
||||
EXPECT_EQ(most_stale_offline_license_number, entry_to_remove);
|
||||
|
||||
// Test where the equality threshold is met, now the stale unexpired
|
||||
// license should be selected.
|
||||
// Case 2: Most stale license is selected.
|
||||
entry_to_remove = kInvalidEntry;
|
||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||
usage_entry_info_list, kCurrentTime,
|
||||
/* unexpired_threshold = */ 0, &entry_to_remove));
|
||||
EXPECT_EQ(modified_offline_license_number, entry_to_remove);
|
||||
EXPECT_EQ(most_stale_offline_license_number, entry_to_remove);
|
||||
|
||||
// Make the stale offline license expired.
|
||||
CdmUsageEntryInfo& offline_usage_entry_info =
|
||||
usage_entry_info_list[modified_offline_license_number];
|
||||
offline_usage_entry_info.offline_license_expiry_time = kLruBaseTime;
|
||||
// Select a offline license to be marked as expired but not the most
|
||||
// stale.
|
||||
uint32_t expired_offline_license_number = kInvalidEntry;
|
||||
while (expired_offline_license_number == kInvalidEntry) {
|
||||
const uint32_t i = static_cast<uint32_t>(
|
||||
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].offline_license_expiry_time = kLruBaseTime;
|
||||
expired_offline_license_number = i;
|
||||
}
|
||||
|
||||
// Test again, expecting that the expired license should be considered.
|
||||
// Case 3: Expired license is selected.
|
||||
entry_to_remove = kInvalidEntry;
|
||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||
usage_entry_info_list, kCurrentTime,
|
||||
/* unexpired_threshold = */ kLargeSetSize, &entry_to_remove));
|
||||
EXPECT_EQ(modified_offline_license_number, entry_to_remove);
|
||||
EXPECT_EQ(expired_offline_license_number, entry_to_remove);
|
||||
|
||||
// Case 4: Most stale license is selected.
|
||||
entry_to_remove = kInvalidEntry;
|
||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||
usage_entry_info_list, kCurrentTime,
|
||||
/* unexpired_threshold = */ 0, &entry_to_remove));
|
||||
EXPECT_EQ(most_stale_offline_license_number, entry_to_remove);
|
||||
}
|
||||
|
||||
TEST_F(UsageTableHeaderTest, PotentialTableCapacity_Unavailable) {
|
||||
|
||||
Reference in New Issue
Block a user