Merge "Revert "Core CDM: Remove secure stop from LRU algorithm.""
This commit is contained in:
@@ -261,9 +261,10 @@ class UsageTableHeader {
|
|||||||
int64_t GetCurrentTime() { return clock_ref_->GetCurrentTime(); }
|
int64_t GetCurrentTime() { return clock_ref_->GetCurrentTime(); }
|
||||||
|
|
||||||
// Sets LRU related metrics based on the provided |staleness| (in
|
// Sets LRU related metrics based on the provided |staleness| (in
|
||||||
// seconds).
|
// seconds) and |storage_type| of the entry removed.
|
||||||
void RecordLruEventMetrics(metrics::CryptoMetrics* metrics,
|
void RecordLruEventMetrics(metrics::CryptoMetrics* metrics,
|
||||||
uint64_t staleness);
|
uint64_t staleness,
|
||||||
|
CdmUsageEntryStorageType storage_type);
|
||||||
|
|
||||||
// Uses an LRU-base algorithm to determine which license should be
|
// Uses an LRU-base algorithm to determine which license should be
|
||||||
// removed. This is intended to be used if the usage table is full
|
// removed. This is intended to be used if the usage table is full
|
||||||
|
|||||||
@@ -96,6 +96,41 @@ bool RetrieveOfflineLicense(DeviceFiles* device_files,
|
|||||||
return true;
|
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) {
|
bool EntryIsUsageInfo(const CdmUsageEntryInfo& info) {
|
||||||
// Used for stl filters.
|
// Used for stl filters.
|
||||||
return info.storage_type == kStorageUsageInfo;
|
return info.storage_type == kStorageUsageInfo;
|
||||||
@@ -1128,6 +1163,7 @@ CdmResponseType UsageTableHeader::ReleaseOldestEntry(
|
|||||||
// Capture metric values now, as the |usage_entry_info| reference will
|
// Capture metric values now, as the |usage_entry_info| reference will
|
||||||
// change after the call to invalidate.
|
// change after the call to invalidate.
|
||||||
const int64_t staleness = current_time - usage_entry_info.last_use_time;
|
const int64_t staleness = current_time - usage_entry_info.last_use_time;
|
||||||
|
const CdmUsageEntryStorageType storage_type = usage_entry_info.storage_type;
|
||||||
|
|
||||||
const CdmResponseType status =
|
const CdmResponseType status =
|
||||||
InvalidateEntryInternal(entry_number_to_delete, /* defrag_table = */ true,
|
InvalidateEntryInternal(entry_number_to_delete, /* defrag_table = */ true,
|
||||||
@@ -1140,7 +1176,7 @@ CdmResponseType UsageTableHeader::ReleaseOldestEntry(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Record metrics on success.
|
// Record metrics on success.
|
||||||
RecordLruEventMetrics(metrics, staleness);
|
RecordLruEventMetrics(metrics, staleness, storage_type);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1173,16 +1209,34 @@ bool UsageTableHeader::LruUpgradeAllUsageEntries() {
|
|||||||
usage_entry_number < usage_entry_info_.size(); ++usage_entry_number) {
|
usage_entry_number < usage_entry_info_.size(); ++usage_entry_number) {
|
||||||
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_[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;
|
uint32_t retrieved_entry_number;
|
||||||
CdmKeyResponse license_message;
|
CdmKeyResponse license_message;
|
||||||
const bool retrieve_response =
|
bool retrieve_response = false;
|
||||||
RetrieveOfflineLicense(device_files_.get(), usage_entry_info.key_set_id,
|
switch (usage_entry_info.storage_type) {
|
||||||
&license_message, &retrieved_entry_number);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!retrieve_response) {
|
if (!retrieve_response) {
|
||||||
LOGW("Could not retrieve license message: usage_entry_number = %u",
|
LOGW("Could not retrieve license message: usage_entry_number = %u",
|
||||||
usage_entry_number);
|
usage_entry_number);
|
||||||
@@ -1211,18 +1265,22 @@ bool UsageTableHeader::LruUpgradeAllUsageEntries() {
|
|||||||
// for replacement above all others.
|
// for replacement above all others.
|
||||||
usage_entry_info.last_use_time = license.license_start_time();
|
usage_entry_info.last_use_time = license.license_start_time();
|
||||||
|
|
||||||
// Only offline licenses need |offline_license_expiry_time| set.
|
if (usage_entry_info.storage_type == kStorageLicense) {
|
||||||
const video_widevine::License::Policy& policy = license.policy();
|
// Only offline licenses need |offline_license_expiry_time| set.
|
||||||
// TODO(b/139372190): Change how these fields are set once feature is
|
const video_widevine::License::Policy& policy = license.policy();
|
||||||
// implemented.
|
// TODO(b/139372190): Change how these fields are set once feature is
|
||||||
if (policy.license_duration_seconds() == 0) {
|
// implemented.
|
||||||
// Zero implies unlimited license duration.
|
if (policy.license_duration_seconds() == 0) {
|
||||||
usage_entry_info.offline_license_expiry_time =
|
// Zero implies unlimited license duration.
|
||||||
license.license_start_time() + policy.rental_duration_seconds() +
|
usage_entry_info.offline_license_expiry_time =
|
||||||
policy.playback_duration_seconds();
|
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();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
usage_entry_info.offline_license_expiry_time =
|
usage_entry_info.offline_license_expiry_time = 0;
|
||||||
license.license_start_time() + policy.license_duration_seconds();
|
|
||||||
}
|
}
|
||||||
} // End for loop.
|
} // End for loop.
|
||||||
|
|
||||||
@@ -1232,14 +1290,31 @@ bool UsageTableHeader::LruUpgradeAllUsageEntries() {
|
|||||||
return false;
|
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) {
|
for (size_t usage_entry_number : bad_license_file_entries) {
|
||||||
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_[usage_entry_number];
|
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_[usage_entry_number];
|
||||||
if (usage_entry_info.storage_type == kStorageLicense) {
|
if (usage_entry_info.storage_type == kStorageLicense) {
|
||||||
device_files_->DeleteLicense(usage_entry_info.key_set_id);
|
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();
|
usage_entry_info.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto& p : usage_info_clean_up) {
|
||||||
|
device_files_->DeleteMultipleUsageInfoByKeySetIds(p.first, p.second);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1252,18 +1327,16 @@ bool UsageTableHeader::GetRemovalCandidate(uint32_t* entry_to_remove) {
|
|||||||
lru_unexpired_threshold, entry_to_remove);
|
lru_unexpired_threshold, entry_to_remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UsageTableHeader::RecordLruEventMetrics(metrics::CryptoMetrics* metrics,
|
void UsageTableHeader::RecordLruEventMetrics(
|
||||||
uint64_t staleness) {
|
metrics::CryptoMetrics* metrics, uint64_t staleness,
|
||||||
|
CdmUsageEntryStorageType storage_type) {
|
||||||
if (metrics == nullptr) return;
|
if (metrics == nullptr) return;
|
||||||
// Usage info are deprecated, always record 0.
|
metrics->usage_table_header_lru_usage_info_count_.Record(UsageInfoCount());
|
||||||
metrics->usage_table_header_lru_usage_info_count_.Record(0);
|
|
||||||
metrics->usage_table_header_lru_offline_license_count_.Record(
|
metrics->usage_table_header_lru_offline_license_count_.Record(
|
||||||
OfflineEntryCount());
|
OfflineEntryCount());
|
||||||
metrics->usage_table_header_lru_evicted_entry_staleness_.Record(staleness);
|
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(
|
metrics->usage_table_header_lru_evicted_entry_type_.Record(
|
||||||
static_cast<int>(kDefaultEntryType));
|
static_cast<int>(storage_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static.
|
// Static.
|
||||||
@@ -1286,13 +1359,14 @@ bool UsageTableHeader::DetermineLicenseToRemove(
|
|||||||
usage_entry_info_list[j].last_use_time;
|
usage_entry_info_list[j].last_use_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find the most stale expired offline license and the
|
// Find the most stale expired offline / streaming license and the
|
||||||
// most stale unexpired offline entry. Count the number of unexpired
|
// most stale unexpired offline entry. Count the number of unexpired
|
||||||
// entries. If any entry is not of storage type license, then it should
|
// entries. If any entry is of storage type unknown, then it should
|
||||||
// be removed.
|
// be removed.
|
||||||
constexpr uint32_t kNoEntry = std::numeric_limits<uint32_t>::max();
|
constexpr uint32_t kNoEntry = std::numeric_limits<uint32_t>::max();
|
||||||
uint32_t stalest_expired_offline_license = kNoEntry;
|
uint32_t stalest_expired_offline_license = kNoEntry;
|
||||||
uint32_t stalest_unexpired_offline_license = kNoEntry;
|
uint32_t stalest_unexpired_offline_license = kNoEntry;
|
||||||
|
uint32_t stalest_streaming_license = kNoEntry;
|
||||||
size_t unexpired_license_count = 0;
|
size_t unexpired_license_count = 0;
|
||||||
|
|
||||||
for (uint32_t entry_number = 0; entry_number < usage_entry_info_list.size();
|
for (uint32_t entry_number = 0; entry_number < usage_entry_info_list.size();
|
||||||
@@ -1300,28 +1374,37 @@ bool UsageTableHeader::DetermineLicenseToRemove(
|
|||||||
const CdmUsageEntryInfo& usage_entry_info =
|
const CdmUsageEntryInfo& usage_entry_info =
|
||||||
usage_entry_info_list[entry_number];
|
usage_entry_info_list[entry_number];
|
||||||
|
|
||||||
if (usage_entry_info.storage_type != kStorageLicense) {
|
if (usage_entry_info.storage_type != kStorageLicense &&
|
||||||
// Non-license storage type entries. Remove this entry.
|
usage_entry_info.storage_type != kStorageUsageInfo) {
|
||||||
|
// Unknown storage type entries. Remove this entry.
|
||||||
*entry_to_remove = entry_number;
|
*entry_to_remove = entry_number;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (usage_entry_info.offline_license_expiry_time > current_time) {
|
if (usage_entry_info.storage_type == kStorageLicense &&
|
||||||
|
usage_entry_info.offline_license_expiry_time > current_time) {
|
||||||
// Unexpired offline.
|
// Unexpired offline.
|
||||||
++unexpired_license_count;
|
++unexpired_license_count;
|
||||||
if (stalest_unexpired_offline_license == kNoEntry ||
|
if (stalest_unexpired_offline_license == kNoEntry ||
|
||||||
is_more_stale(entry_number, stalest_unexpired_offline_license)) {
|
is_more_stale(entry_number, stalest_unexpired_offline_license)) {
|
||||||
stalest_unexpired_offline_license = entry_number;
|
stalest_unexpired_offline_license = entry_number;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (usage_entry_info.storage_type == kStorageLicense) {
|
||||||
// Expired offline.
|
// Expired offline.
|
||||||
if (stalest_expired_offline_license == kNoEntry ||
|
if (stalest_expired_offline_license == kNoEntry ||
|
||||||
is_more_stale(entry_number, stalest_expired_offline_license)) {
|
is_more_stale(entry_number, stalest_expired_offline_license)) {
|
||||||
stalest_expired_offline_license = entry_number;
|
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 &&
|
if (stalest_expired_offline_license == kNoEntry &&
|
||||||
|
stalest_streaming_license == kNoEntry &&
|
||||||
unexpired_license_count <= unexpired_threshold) {
|
unexpired_license_count <= unexpired_threshold) {
|
||||||
// Unexpected situation, could be an issue with the threshold.
|
// Unexpected situation, could be an issue with the threshold.
|
||||||
LOGW(
|
LOGW(
|
||||||
@@ -1341,10 +1424,12 @@ bool UsageTableHeader::DetermineLicenseToRemove(
|
|||||||
|
|
||||||
// Only consider an unexpired entry if the threshold is reached.
|
// Only consider an unexpired entry if the threshold is reached.
|
||||||
if (unexpired_license_count > unexpired_threshold) {
|
if (unexpired_license_count > unexpired_threshold) {
|
||||||
*entry_to_remove = select_most_stale(stalest_unexpired_offline_license,
|
const uint32_t temp = select_most_stale(stalest_unexpired_offline_license,
|
||||||
stalest_expired_offline_license);
|
stalest_streaming_license);
|
||||||
|
*entry_to_remove = select_most_stale(temp, stalest_expired_offline_license);
|
||||||
} else {
|
} else {
|
||||||
*entry_to_remove = stalest_expired_offline_license;
|
*entry_to_remove = select_most_stale(stalest_streaming_license,
|
||||||
|
stalest_expired_offline_license);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*entry_to_remove == kNoEntry) {
|
if (*entry_to_remove == kNoEntry) {
|
||||||
|
|||||||
@@ -229,9 +229,9 @@ const CdmKeyResponse kKeyRenewalResponse = "key renewal response";
|
|||||||
const std::string kReleaseServerUrl = "some url";
|
const std::string kReleaseServerUrl = "some url";
|
||||||
const std::string kProviderSessionToken = "provider session token";
|
const std::string kProviderSessionToken = "provider session token";
|
||||||
const CdmAppParameterMap kEmptyAppParameters;
|
const CdmAppParameterMap kEmptyAppParameters;
|
||||||
constexpr int64_t kPlaybackStartTime = 1030005;
|
int64_t kPlaybackStartTime = 1030005;
|
||||||
constexpr int64_t kPlaybackDuration = 300;
|
int64_t kPlaybackDuration = 300;
|
||||||
constexpr int64_t kGracePeriodEndTime = 60;
|
int64_t kGracePeriodEndTime = 60;
|
||||||
|
|
||||||
// ==== LRU Upgrade Data ====
|
// ==== LRU Upgrade Data ====
|
||||||
const CdmUsageTableHeader kUpgradableUsageTableHeader =
|
const CdmUsageTableHeader kUpgradableUsageTableHeader =
|
||||||
@@ -245,9 +245,9 @@ const CdmUsageEntryInfo kUpgradableUsageEntryInfo1 = {
|
|||||||
/* last_use_time = */ 0,
|
/* last_use_time = */ 0,
|
||||||
/* offline_license_expiry_time = */ 0};
|
/* offline_license_expiry_time = */ 0};
|
||||||
const CdmUsageEntryInfo kUpgradableUsageEntryInfo2 = {
|
const CdmUsageEntryInfo kUpgradableUsageEntryInfo2 = {
|
||||||
/* storage_type = */ kStorageLicense,
|
/* storage_type = */ kStorageUsageInfo,
|
||||||
/* key_set_id = */ "offline_key_set_2",
|
/* key_set_id = */ "streaming_key_set_2",
|
||||||
/* usage_info_file_name = */ "",
|
/* usage_info_file_name = */ "streaming_license_file_2",
|
||||||
/* last_use_time = */ 0,
|
/* last_use_time = */ 0,
|
||||||
/* offline_license_expiry_time = */ 0};
|
/* offline_license_expiry_time = */ 0};
|
||||||
const CdmUsageEntryInfo kUpgradableUsageEntryInfo3 = {
|
const CdmUsageEntryInfo kUpgradableUsageEntryInfo3 = {
|
||||||
@@ -256,11 +256,7 @@ const CdmUsageEntryInfo kUpgradableUsageEntryInfo3 = {
|
|||||||
/* usage_info_file_name = */ "",
|
/* usage_info_file_name = */ "",
|
||||||
/* last_use_time = */ 0,
|
/* last_use_time = */ 0,
|
||||||
/* offline_license_expiry_time = */ 0};
|
/* offline_license_expiry_time = */ 0};
|
||||||
const std::vector<CdmUsageEntryInfo> kUpgradableUsageEntryInfoList{
|
std::vector<CdmUsageEntryInfo> kUpgradableUsageEntryInfoList;
|
||||||
kUpgradableUsageEntryInfo1, kUpgradableUsageEntryInfo2,
|
|
||||||
kUpgradableUsageEntryInfo3};
|
|
||||||
|
|
||||||
const int64_t kLruBaseTime = 1563399000;
|
|
||||||
|
|
||||||
// Offline license 1.
|
// Offline license 1.
|
||||||
// license_start_time = 1563399000
|
// license_start_time = 1563399000
|
||||||
@@ -270,14 +266,11 @@ const int64_t kLruBaseTime = 1563399000;
|
|||||||
const CdmKeyResponse kUpgradableLicenseInfo1 = wvutil::a2bs_hex(
|
const CdmKeyResponse kUpgradableLicenseInfo1 = wvutil::a2bs_hex(
|
||||||
"08021214120C2080F5242880A3053080E90F20D8A6BEE9051A20D5F7ACE8D84A166C69BB"
|
"08021214120C2080F5242880A3053080E90F20D8A6BEE9051A20D5F7ACE8D84A166C69BB"
|
||||||
"27523C84C019464B90AA9BF06B8332004839119BFD14");
|
"27523C84C019464B90AA9BF06B8332004839119BFD14");
|
||||||
// Offline license 2.
|
// Streaming license 2.
|
||||||
// license_start_time = 1563399000
|
// 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(
|
const CdmKeyResponse kUpgradableLicenseInfo2 = wvutil::a2bs_hex(
|
||||||
"080212101208200028003080E90F20D8A6BEE9051A20D0611C4AFEF3EC9C67143ED39B44"
|
"0802120620D8A6BEE9051A201956F2FD69E5E96DA8C65FDD04A3C294E484F219F2B1A8DD"
|
||||||
"8FAAA67DB6C4DBFDC28A733AF9A2EABDF0B3");
|
"C2B0737F6EF5BD22");
|
||||||
// Offline license 3.
|
// Offline license 3.
|
||||||
// license_start_time = 1563399000
|
// license_start_time = 1563399000
|
||||||
// license_duration_seconds = 0 (unlimited)
|
// license_duration_seconds = 0 (unlimited)
|
||||||
@@ -286,56 +279,26 @@ const CdmKeyResponse kUpgradableLicenseInfo2 = wvutil::a2bs_hex(
|
|||||||
const CdmKeyResponse kUpgradableLicenseInfo3 = wvutil::a2bs_hex(
|
const CdmKeyResponse kUpgradableLicenseInfo3 = wvutil::a2bs_hex(
|
||||||
"08021212120A2080F5242880A305300020D8A6BEE9051A207B09896F46C4EE443170E215"
|
"08021212120A2080F5242880A305300020D8A6BEE9051A207B09896F46C4EE443170E215"
|
||||||
"B2D8D5F072951027B152F4758AC3A339D7C7B4CE");
|
"B2D8D5F072951027B152F4758AC3A339D7C7B4CE");
|
||||||
const std::vector<CdmKeyResponse> kUpgradableLicenseInfoList = {
|
std::vector<CdmKeyResponse> kUpgradableLicenseInfoList;
|
||||||
kUpgradableLicenseInfo1, kUpgradableLicenseInfo2, kUpgradableLicenseInfo3};
|
std::vector<DeviceFiles::CdmLicenseData> kUpgradableLicenseDataList;
|
||||||
|
|
||||||
// Same as Offline license 1, but without signature.
|
// Same as Offline license 1, but without signature.
|
||||||
const CdmKeyResponse kUnsignedUpgradableLicenseInfo1 =
|
const CdmKeyResponse kUnsignedUpgradableLicenseInfo1 =
|
||||||
wvutil::a2bs_hex("08021214120C2080F5242880A3053080E90F20D8A6BEE905");
|
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 kUpgradedUsageEntryInfo1LastUsedTime = kLruBaseTime;
|
||||||
const int64_t kUpgradedUsageEntryInfo1ExpireTime = kLruBaseTime + 259200;
|
const int64_t kUpgradedUsageEntryInfo1ExpireTime = kLruBaseTime + 259200;
|
||||||
const int64_t kUpgradedUsageEntryInfo2LastUsedTime = kLruBaseTime;
|
const int64_t kUpgradedUsageEntryInfo2LastUsedTime = kLruBaseTime;
|
||||||
const int64_t kUpgradedUsageEntryInfo2ExpireTime = kLruBaseTime + 259200;
|
const int64_t kUpgradedUsageEntryInfo2ExpireTime = 0; // Unset
|
||||||
const int64_t kUpgradedUsageEntryInfo3LastUsedTime = kLruBaseTime;
|
const int64_t kUpgradedUsageEntryInfo3LastUsedTime = kLruBaseTime;
|
||||||
const int64_t kUpgradedUsageEntryInfo3ExpireTime =
|
const int64_t kUpgradedUsageEntryInfo3ExpireTime =
|
||||||
kLruBaseTime + 604800 + 86400;
|
kLruBaseTime + 604800 + 86400;
|
||||||
const CdmUsageTableHeader kUpgradedUsageTableHeader = "Upgraded Table Header";
|
const CdmUsageTableHeader kUpgradedUsageTableHeader = "Upgraded Table Header";
|
||||||
const CdmUsageEntryInfo kUpgradedUsageEntryInfo1 = {
|
std::vector<CdmUsageEntryInfo> kUpgradedUsageEntryInfoList;
|
||||||
/* 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() {
|
void InitVectorConstants() {
|
||||||
kOverFullUsageEntryInfoVector.clear();
|
kOverFullUsageEntryInfoVector.clear();
|
||||||
@@ -369,6 +332,40 @@ void InitVectorConstants() {
|
|||||||
for (size_t i = 0; i < kLicenseArraySize; i++) {
|
for (size_t i = 0; i < kLicenseArraySize; i++) {
|
||||||
kLicenseList.push_back(kLicenseArray[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,
|
void ToVector(std::vector<CdmUsageEntryInfo>& vec, const CdmUsageEntryInfo* arr,
|
||||||
@@ -405,6 +402,9 @@ class MockDeviceFiles : public DeviceFiles {
|
|||||||
(override));
|
(override));
|
||||||
MOCK_METHOD(bool, DeleteUsageInfo, (const std::string&, const std::string&),
|
MOCK_METHOD(bool, DeleteUsageInfo, (const std::string&, const std::string&),
|
||||||
(override));
|
(override));
|
||||||
|
MOCK_METHOD(bool, DeleteMultipleUsageInfoByKeySetIds,
|
||||||
|
(const std::string&, const std::vector<std::string>&),
|
||||||
|
(override));
|
||||||
MOCK_METHOD(bool, RetrieveUsageInfoByKeySetId,
|
MOCK_METHOD(bool, RetrieveUsageInfoByKeySetId,
|
||||||
(const std::string&, const std::string&, std::string*,
|
(const std::string&, const std::string&, std::string*,
|
||||||
CdmKeyMessage*, CdmKeyResponse*, CdmUsageEntry*, uint32_t*,
|
CdmKeyMessage*, CdmKeyResponse*, CdmUsageEntry*, uint32_t*,
|
||||||
@@ -3728,6 +3728,9 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_NoAction) {
|
|||||||
|
|
||||||
// These function are called specifically by the LRU upgrading system.
|
// These function are called specifically by the LRU upgrading system.
|
||||||
EXPECT_CALL(*device_files_, RetrieveLicense(_, _, _)).Times(0);
|
EXPECT_CALL(*device_files_, RetrieveLicense(_, _, _)).Times(0);
|
||||||
|
EXPECT_CALL(*device_files_,
|
||||||
|
RetrieveUsageInfoByKeySetId(_, _, _, _, _, _, _, _, _))
|
||||||
|
.Times(0);
|
||||||
|
|
||||||
EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_));
|
EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_));
|
||||||
EXPECT_EQ(usage_table_header_->usage_entry_info(),
|
EXPECT_EQ(usage_table_header_->usage_entry_info(),
|
||||||
@@ -3737,8 +3740,8 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_NoAction) {
|
|||||||
// Initial Test state:
|
// Initial Test state:
|
||||||
// 1. Table info is load from device files; however, device files reports
|
// 1. Table info is load from device files; however, device files reports
|
||||||
// that the table has not been configured for upgrade.
|
// that the table has not been configured for upgrade.
|
||||||
// 2. The usage table header will load offline license to determine
|
// 2. The usage table header will load license or usage information to
|
||||||
// appropriate expiry and last_used times.
|
// determine appropriate expiry and last_used times.
|
||||||
TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_Succeed) {
|
TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_Succeed) {
|
||||||
EXPECT_CALL(*crypto_session_,
|
EXPECT_CALL(*crypto_session_,
|
||||||
GetNumberOfOpenSessions(kLevelDefault, NotNull()))
|
GetNumberOfOpenSessions(kLevelDefault, NotNull()))
|
||||||
@@ -3753,18 +3756,24 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_Succeed) {
|
|||||||
LoadUsageTableHeader(kLevelDefault, kUpgradableUsageTableHeader))
|
LoadUsageTableHeader(kLevelDefault, kUpgradableUsageTableHeader))
|
||||||
.WillOnce(Return(NO_ERROR));
|
.WillOnce(Return(NO_ERROR));
|
||||||
|
|
||||||
const std::vector<DeviceFiles::CdmLicenseData> license_info_list =
|
|
||||||
CreateUpgradableLicenseInfoList();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < kUpgradableUsageEntryInfoList.size(); ++i) {
|
for (size_t i = 0; i < kUpgradableUsageEntryInfoList.size(); ++i) {
|
||||||
const CdmUsageEntryInfo& info = kUpgradableUsageEntryInfoList[i];
|
const CdmUsageEntryInfo& info = kUpgradableUsageEntryInfoList[i];
|
||||||
|
|
||||||
if (info.storage_type == kStorageLicense) {
|
if (info.storage_type == kStorageLicense) {
|
||||||
// Only offline licenses are supported.
|
|
||||||
EXPECT_CALL(*device_files_,
|
EXPECT_CALL(*device_files_,
|
||||||
RetrieveLicense(info.key_set_id, NotNull(), NotNull()))
|
RetrieveLicense(info.key_set_id, NotNull(), NotNull()))
|
||||||
.WillOnce(
|
.WillOnce(DoAll(SetArgPointee<1>(kUpgradableLicenseDataList[i]),
|
||||||
DoAll(SetArgPointee<1>(license_info_list[i]), Return(true)));
|
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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3774,22 +3783,33 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_Succeed) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initial Test state:
|
// Initial Test state:
|
||||||
// Table info is load from device files and must be upgraded.
|
// 1. Table info is load from device files and must be upgraded.
|
||||||
// A few entries have the unknown storage type value.
|
// 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.
|
||||||
//
|
//
|
||||||
// Entry# Storage type Result info
|
// Entry# Storage type Result info
|
||||||
// ====== ============ ===========
|
// ====== ============ ===========
|
||||||
// 0 Offline Upgraded
|
// 0 Offline Upgraded
|
||||||
// 1 Unknown Cleared
|
// 1 Unknown Cleared
|
||||||
// 2 Unknown Cleared
|
// 2 Invalid (99) Cleared
|
||||||
TEST_F(UsageTableHeaderTest,
|
TEST_F(UsageTableHeaderTest,
|
||||||
LruUsageTableUpgrade_PartialSucceedWithUnknownStorageTypes) {
|
LruUsageTableUpgrade_PartialSucceedWithUnknownStorageTypes) {
|
||||||
const std::vector<CdmUsageEntryInfo> upgradable_usage_entry_info_list = {
|
std::vector<CdmUsageEntryInfo> upgradable_usage_entry_info_list =
|
||||||
kUpgradableUsageEntryInfo1, kUsageEntryInfoStorageTypeUnknown,
|
kUpgradableUsageEntryInfoList;
|
||||||
kUsageEntryInfoStorageTypeUnknown};
|
std::vector<CdmUsageEntryInfo> upgraded_usage_entry_info_list =
|
||||||
const std::vector<CdmUsageEntryInfo> upgraded_usage_entry_info_list = {
|
kUpgradedUsageEntryInfoList;
|
||||||
kUpgradedUsageEntryInfo1, kUsageEntryInfoStorageTypeUnknown,
|
|
||||||
kUsageEntryInfoStorageTypeUnknown};
|
// 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;
|
||||||
|
|
||||||
// Load table expectations.
|
// Load table expectations.
|
||||||
EXPECT_CALL(*crypto_session_,
|
EXPECT_CALL(*crypto_session_,
|
||||||
@@ -3806,12 +3826,11 @@ TEST_F(UsageTableHeaderTest,
|
|||||||
.WillOnce(Return(NO_ERROR));
|
.WillOnce(Return(NO_ERROR));
|
||||||
|
|
||||||
// Expectations of the one successful license.
|
// Expectations of the one successful license.
|
||||||
const std::vector<DeviceFiles::CdmLicenseData> license_info_list =
|
|
||||||
CreateUpgradableLicenseInfoList();
|
|
||||||
EXPECT_CALL(*device_files_,
|
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()))
|
NotNull(), NotNull()))
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(license_info_list[0]), Return(true)));
|
.WillOnce(
|
||||||
|
DoAll(SetArgPointee<1>(kUpgradableLicenseDataList[0]), Return(true)));
|
||||||
|
|
||||||
EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_));
|
EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_));
|
||||||
EXPECT_EQ(upgraded_usage_entry_info_list,
|
EXPECT_EQ(upgraded_usage_entry_info_list,
|
||||||
@@ -3827,14 +3846,12 @@ TEST_F(UsageTableHeaderTest,
|
|||||||
// Entry# Storage type License Issue Result info
|
// Entry# Storage type License Issue Result info
|
||||||
// ====== ============ ============= ===========
|
// ====== ============ ============= ===========
|
||||||
// 0 Offline No signature Cleared
|
// 0 Offline No signature Cleared
|
||||||
// 1 Unknown Clear entry Cleared
|
// 1 Streaming Wrong type Cleared
|
||||||
// 2 Offline Upgraded
|
// 2 Offline Upgraded
|
||||||
TEST_F(UsageTableHeaderTest,
|
TEST_F(UsageTableHeaderTest,
|
||||||
LruUsageTableUpgrade_PartialSucceedWithLicenseParseIssues) {
|
LruUsageTableUpgrade_PartialSucceedWithLicenseParseIssues) {
|
||||||
std::vector<CdmUsageEntryInfo> upgradable_usage_entry_info_list =
|
|
||||||
kUpgradableUsageEntryInfoList;
|
|
||||||
std::vector<DeviceFiles::CdmLicenseData> license_data_list =
|
std::vector<DeviceFiles::CdmLicenseData> license_data_list =
|
||||||
CreateUpgradableLicenseInfoList();
|
kUpgradableLicenseDataList;
|
||||||
std::vector<CdmKeyResponse> upgradable_license_info_list =
|
std::vector<CdmKeyResponse> upgradable_license_info_list =
|
||||||
kUpgradableLicenseInfoList;
|
kUpgradableLicenseInfoList;
|
||||||
std::vector<CdmUsageEntryInfo> upgraded_usage_entry_info_list =
|
std::vector<CdmUsageEntryInfo> upgraded_usage_entry_info_list =
|
||||||
@@ -3842,12 +3859,21 @@ TEST_F(UsageTableHeaderTest,
|
|||||||
|
|
||||||
// Modify entry 0 to be invalid.
|
// Modify entry 0 to be invalid.
|
||||||
license_data_list[0].license = kUnsignedUpgradableLicenseInfo1;
|
license_data_list[0].license = kUnsignedUpgradableLicenseInfo1;
|
||||||
upgraded_usage_entry_info_list[0].Clear();
|
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;
|
||||||
|
|
||||||
// Modify entry 1 to be clear.
|
// Modify entry 1 to be invalid.
|
||||||
upgradable_usage_entry_info_list[1].Clear();
|
upgradable_license_info_list[1] = kWrongTypedUpgradableLicenseInfo2;
|
||||||
upgradable_license_info_list[1].clear();
|
CdmUsageEntryInfo& wrond_typed_usage_entry_info =
|
||||||
upgraded_usage_entry_info_list[1].Clear();
|
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;
|
||||||
|
|
||||||
EXPECT_CALL(*crypto_session_,
|
EXPECT_CALL(*crypto_session_,
|
||||||
GetNumberOfOpenSessions(kLevelDefault, NotNull()))
|
GetNumberOfOpenSessions(kLevelDefault, NotNull()))
|
||||||
@@ -3855,27 +3881,46 @@ TEST_F(UsageTableHeaderTest,
|
|||||||
EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull(),
|
EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull(),
|
||||||
NotNull(), NotNull()))
|
NotNull(), NotNull()))
|
||||||
.WillOnce(DoAll(SetArgPointee<0>(kUpgradableUsageTableHeader),
|
.WillOnce(DoAll(SetArgPointee<0>(kUpgradableUsageTableHeader),
|
||||||
SetArgPointee<1>(upgradable_usage_entry_info_list),
|
SetArgPointee<1>(kUpgradableUsageEntryInfoList),
|
||||||
SetArgPointee<2>(/* lru_upgrade = */ true),
|
SetArgPointee<2>(/* lru_upgrade = */ true),
|
||||||
SetArgPointee<3>(false), Return(true)));
|
SetArgPointee<3>(false), Return(true)));
|
||||||
EXPECT_CALL(*crypto_session_,
|
EXPECT_CALL(*crypto_session_,
|
||||||
LoadUsageTableHeader(kLevelDefault, kUpgradableUsageTableHeader))
|
LoadUsageTableHeader(kLevelDefault, kUpgradableUsageTableHeader))
|
||||||
.WillOnce(Return(NO_ERROR));
|
.WillOnce(Return(NO_ERROR));
|
||||||
|
|
||||||
for (size_t i = 0; i < upgradable_usage_entry_info_list.size(); ++i) {
|
for (size_t i = 0; i < kUpgradableUsageEntryInfoList.size(); ++i) {
|
||||||
const CdmUsageEntryInfo& info = upgradable_usage_entry_info_list[i];
|
const CdmUsageEntryInfo& info = kUpgradableUsageEntryInfoList[i];
|
||||||
if (info.storage_type == kStorageLicense) {
|
if (info.storage_type == kStorageLicense) {
|
||||||
EXPECT_CALL(*device_files_,
|
EXPECT_CALL(*device_files_,
|
||||||
RetrieveLicense(info.key_set_id, NotNull(), NotNull()))
|
RetrieveLicense(info.key_set_id, NotNull(), NotNull()))
|
||||||
.WillOnce(
|
.WillOnce(
|
||||||
DoAll(SetArgPointee<1>(license_data_list[i]), Return(true)));
|
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
|
// For the entries which failed, there should be an attempt to delete the
|
||||||
// files associated with them.
|
// files associated with them.
|
||||||
|
// Offline license.
|
||||||
EXPECT_CALL(*device_files_,
|
EXPECT_CALL(*device_files_,
|
||||||
DeleteLicense(upgradable_usage_entry_info_list[0].key_set_id))
|
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)))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_));
|
EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_));
|
||||||
@@ -3908,6 +3953,13 @@ TEST_F(UsageTableHeaderTest, LruUsageTableUpgrade_AllFailure) {
|
|||||||
EXPECT_CALL(*device_files_,
|
EXPECT_CALL(*device_files_,
|
||||||
RetrieveLicense(info.key_set_id, NotNull(), NotNull()))
|
RetrieveLicense(info.key_set_id, NotNull(), NotNull()))
|
||||||
.WillOnce(Return(false));
|
.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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3955,7 +4007,46 @@ TEST_F(UsageTableHeaderTest, LruLastUsedTime_CreateLicenseEntry) {
|
|||||||
EXPECT_EQ(NO_ERROR, usage_table_header_->AddEntry(
|
EXPECT_EQ(NO_ERROR, usage_table_header_->AddEntry(
|
||||||
crypto_session_, true /* persistent_license */,
|
crypto_session_, true /* persistent_license */,
|
||||||
expected_new_entry.key_set_id,
|
expected_new_entry.key_set_id,
|
||||||
/* usage_info_file_name */ kEmptyString, kEmptyString,
|
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_entry_number));
|
&usage_entry_number));
|
||||||
|
|
||||||
EXPECT_EQ(expected_usage_entry_number, usage_entry_number);
|
EXPECT_EQ(expected_usage_entry_number, usage_entry_number);
|
||||||
@@ -4060,7 +4151,6 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) {
|
|||||||
// Unexpired offline license.
|
// Unexpired offline license.
|
||||||
CdmUsageEntryInfo unexpired_entry_info;
|
CdmUsageEntryInfo unexpired_entry_info;
|
||||||
unexpired_entry_info.storage_type = kStorageLicense;
|
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.last_use_time = kLruBaseTime;
|
||||||
unexpired_entry_info.offline_license_expiry_time = kLruBaseTime + 2 * kOneDay;
|
unexpired_entry_info.offline_license_expiry_time = kLruBaseTime + 2 * kOneDay;
|
||||||
usage_entry_info_list.push_back(unexpired_entry_info);
|
usage_entry_info_list.push_back(unexpired_entry_info);
|
||||||
@@ -4069,43 +4159,59 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) {
|
|||||||
// Expired offline license.
|
// Expired offline license.
|
||||||
CdmUsageEntryInfo expired_entry_info;
|
CdmUsageEntryInfo expired_entry_info;
|
||||||
expired_entry_info.storage_type = kStorageLicense;
|
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.last_use_time = kLruBaseTime;
|
||||||
expired_entry_info.offline_license_expiry_time = kLruBaseTime;
|
expired_entry_info.offline_license_expiry_time = kLruBaseTime;
|
||||||
usage_entry_info_list.push_back(expired_entry_info);
|
usage_entry_info_list.push_back(expired_entry_info);
|
||||||
constexpr uint32_t expired_entry_number = 1;
|
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.
|
// Unknown entry.
|
||||||
CdmUsageEntryInfo unknown_entry_info;
|
CdmUsageEntryInfo unknown_entry_info;
|
||||||
unknown_entry_info.storage_type = kStorageTypeUnknown;
|
unknown_entry_info.storage_type = kStorageTypeUnknown;
|
||||||
// Should be chosen regardless of |last_use_time|.
|
// Should be chosen regardless of |last_use_time|.
|
||||||
unknown_entry_info.last_use_time = kCurrentTime;
|
unknown_entry_info.last_use_time = kCurrentTime;
|
||||||
usage_entry_info_list.push_back(unknown_entry_info);
|
usage_entry_info_list.push_back(unknown_entry_info);
|
||||||
constexpr uint32_t unknown_entry_number = 2;
|
constexpr uint32_t unknown_entry_number = 3;
|
||||||
|
|
||||||
// Case 1: If there is a clear entry, it should be selected above
|
// Case 1: If there is an entry with unknown storage type, it should
|
||||||
// any other entry.
|
// be selected above any other entry.
|
||||||
uint32_t entry_to_remove = kInvalidEntry;
|
uint32_t entry_to_remove = kInvalidEntry;
|
||||||
|
|
||||||
// Expect the clear.
|
// Expect the unknown entry.
|
||||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||||
usage_entry_info_list, kCurrentTime,
|
usage_entry_info_list, kCurrentTime,
|
||||||
/* unexpired_threshold = */ 3, &entry_to_remove));
|
/* unexpired_threshold = */ 3, &entry_to_remove));
|
||||||
EXPECT_EQ(unknown_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.pop_back(); // Removing unknown.
|
||||||
// |usage_entry_info_list| only contains 1 expired and 1 unexpired offline
|
|
||||||
// license.
|
|
||||||
|
|
||||||
// Case 2a: Threshold not met, all entries are equally stale.
|
// Case 2a: Threshold not met, all entries are equally stale.
|
||||||
// The expired entry should be selected over the unexpired entry.
|
// The expired entry should be selected over the streaming license.
|
||||||
entry_to_remove = kInvalidEntry;
|
entry_to_remove = kInvalidEntry;
|
||||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||||
usage_entry_info_list, kCurrentTime,
|
usage_entry_info_list, kCurrentTime,
|
||||||
/* unexpired_threshold = */ 3, &entry_to_remove));
|
/* unexpired_threshold = */ 3, &entry_to_remove));
|
||||||
EXPECT_EQ(expired_entry_number, entry_to_remove);
|
EXPECT_EQ(expired_entry_number, entry_to_remove);
|
||||||
|
|
||||||
// Case 2b: Threshold met, equally stale entries. Expect the expired
|
// 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
|
||||||
// entry over the unexpired.
|
// entry over the unexpired.
|
||||||
entry_to_remove = kInvalidEntry;
|
entry_to_remove = kInvalidEntry;
|
||||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||||
@@ -4167,8 +4273,45 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_BasicPriorities) {
|
|||||||
EXPECT_EQ(unexpired_entry_number, entry_to_remove);
|
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
|
// When the number of unexpired offline licenses are below the
|
||||||
// threshold, only expired offline licenses should be considered.
|
// threshold, only streaming licenses and expired offline licenses
|
||||||
|
// should be considered.
|
||||||
// Providing only offline licenses, only the expired license should be
|
// Providing only offline licenses, only the expired license should be
|
||||||
// considered for removal.
|
// considered for removal.
|
||||||
TEST_F(UsageTableHeaderTest,
|
TEST_F(UsageTableHeaderTest,
|
||||||
@@ -4187,20 +4330,20 @@ TEST_F(UsageTableHeaderTest,
|
|||||||
for (uint32_t i = 0; i < kSetSize; ++i) {
|
for (uint32_t i = 0; i < kSetSize; ++i) {
|
||||||
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[i];
|
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[i];
|
||||||
usage_entry_info.storage_type = kStorageLicense;
|
usage_entry_info.storage_type = kStorageLicense;
|
||||||
usage_entry_info.key_set_id = "unexpired_offline";
|
usage_entry_info.key_set_id = "nothing_unusual";
|
||||||
usage_entry_info.last_use_time = kLruBaseTime;
|
usage_entry_info.last_use_time = kLruBaseTime;
|
||||||
usage_entry_info.offline_license_expiry_time =
|
usage_entry_info.offline_license_expiry_time =
|
||||||
kCurrentTime + kDefaultExpireDuration;
|
kCurrentTime + kDefaultExpireDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark three licenses as expired.
|
// Mark 3 as expired.
|
||||||
std::vector<uint32_t> expired_license_numbers;
|
std::vector<uint32_t> expired_license_numbers;
|
||||||
while (expired_license_numbers.size() < 3) {
|
while (expired_license_numbers.size() < 3) {
|
||||||
const uint32_t i =
|
const uint32_t i =
|
||||||
static_cast<uint32_t>(wvutil::CdmRandom::RandomInRange(kSetSize - 1));
|
static_cast<uint32_t>(wvutil::CdmRandom::RandomInRange(kSetSize - 1));
|
||||||
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[i];
|
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[i];
|
||||||
// Skip already expired ones
|
// Skip already expired ones
|
||||||
if (usage_entry_info.key_set_id != "unexpired_offline") continue;
|
if (usage_entry_info.key_set_id != "nothing_unusual") continue;
|
||||||
// Make these less stale than the unexpired licenses.
|
// Make these less stale than the unexpired licenses.
|
||||||
usage_entry_info.last_use_time = kLruBaseTime + kOneDay;
|
usage_entry_info.last_use_time = kLruBaseTime + kOneDay;
|
||||||
usage_entry_info.offline_license_expiry_time = kCurrentTime - kOneDay;
|
usage_entry_info.offline_license_expiry_time = kCurrentTime - kOneDay;
|
||||||
@@ -4216,31 +4359,16 @@ TEST_F(UsageTableHeaderTest,
|
|||||||
EXPECT_THAT(expired_license_numbers, Contains(entry_to_remove));
|
EXPECT_THAT(expired_license_numbers, Contains(entry_to_remove));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This primarily tests the robustness of the algorithm for a full
|
// This test primarily tests the robustness of the algorithm for a full
|
||||||
// set of entries (200). Creates 1 offline license which are more
|
// set of entries (200). Creates 1 stale streaming license and 1
|
||||||
// stale than the all other licenses.
|
// offline licenses which are more stale than the streaming.
|
||||||
//
|
//
|
||||||
// All cases: 1 unexpired license is most stale.
|
// First, with the stale offline licenses unexpired, checks that the
|
||||||
|
// streaming are always selected, so long as |unexpired_threshold|
|
||||||
|
// is not met.
|
||||||
//
|
//
|
||||||
// Case 1:
|
// Second, with the stale offline license marked as expired, checks that
|
||||||
// - Unexpired threshold met: No
|
// offline licenses are selected over the streaming.
|
||||||
// - 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) {
|
TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_LargeMixedSet) {
|
||||||
constexpr int64_t kOneDay = 24 * 60 * 60;
|
constexpr int64_t kOneDay = 24 * 60 * 60;
|
||||||
constexpr size_t kLargeSetSize = 200;
|
constexpr size_t kLargeSetSize = 200;
|
||||||
@@ -4249,63 +4377,74 @@ TEST_F(UsageTableHeaderTest, DetermineLicenseToRemove_LargeMixedSet) {
|
|||||||
std::vector<CdmUsageEntryInfo> usage_entry_info_list;
|
std::vector<CdmUsageEntryInfo> usage_entry_info_list;
|
||||||
usage_entry_info_list.resize(kLargeSetSize);
|
usage_entry_info_list.resize(kLargeSetSize);
|
||||||
|
|
||||||
// Create a set of unexpired license entries.
|
// Create a set of usage entries.
|
||||||
for (uint32_t i = 0; i < kLargeSetSize; ++i) {
|
for (uint32_t i = 0; i < kLargeSetSize; ++i) {
|
||||||
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[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 + kOneDay;
|
usage_entry_info.last_use_time = kLruBaseTime + kOneDay;
|
||||||
usage_entry_info.offline_license_expiry_time =
|
if ((i % 4) == 0) {
|
||||||
kCurrentTime + kDefaultExpireDuration;
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select a offline license to be even more stale, but unexpired.
|
// Select a offline license to be even more stale, but unexpired.
|
||||||
const uint32_t most_stale_offline_license_number = static_cast<uint32_t>(
|
uint32_t modified_offline_license_number = kInvalidEntry;
|
||||||
wvutil::CdmRandom::RandomInRange(kLargeSetSize - 1));
|
while (modified_offline_license_number == kInvalidEntry) {
|
||||||
CdmUsageEntryInfo& usage_entry_info =
|
const uint32_t i = static_cast<uint32_t>(
|
||||||
usage_entry_info_list[most_stale_offline_license_number];
|
wvutil::CdmRandom::RandomInRange(kLargeSetSize - 1));
|
||||||
usage_entry_info.last_use_time = kLruBaseTime;
|
CdmUsageEntryInfo& usage_entry_info = usage_entry_info_list[i];
|
||||||
usage_entry_info.key_set_id = "stale_offline";
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
// Case 1: Most stale license is selected.
|
// Test using only streaming and expired offline licenses
|
||||||
|
// (which there are none).
|
||||||
uint32_t entry_to_remove = kInvalidEntry;
|
uint32_t entry_to_remove = kInvalidEntry;
|
||||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||||
usage_entry_info_list, kCurrentTime,
|
usage_entry_info_list, kCurrentTime,
|
||||||
/* unexpired_threshold = */ kLargeSetSize, &entry_to_remove));
|
/* unexpired_threshold = */ kLargeSetSize, &entry_to_remove));
|
||||||
EXPECT_EQ(most_stale_offline_license_number, entry_to_remove);
|
EXPECT_EQ(modified_usage_info_number, entry_to_remove);
|
||||||
|
|
||||||
// Case 2: Most stale license is selected.
|
// Test where the equality threshold is met, now the stale unexpired
|
||||||
|
// license should be selected.
|
||||||
entry_to_remove = kInvalidEntry;
|
entry_to_remove = kInvalidEntry;
|
||||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||||
usage_entry_info_list, kCurrentTime,
|
usage_entry_info_list, kCurrentTime,
|
||||||
/* unexpired_threshold = */ 0, &entry_to_remove));
|
/* unexpired_threshold = */ 0, &entry_to_remove));
|
||||||
EXPECT_EQ(most_stale_offline_license_number, entry_to_remove);
|
EXPECT_EQ(modified_offline_license_number, entry_to_remove);
|
||||||
|
|
||||||
// Select a offline license to be marked as expired but not the most
|
// Make the stale offline license expired.
|
||||||
// stale.
|
CdmUsageEntryInfo& offline_usage_entry_info =
|
||||||
uint32_t expired_offline_license_number = kInvalidEntry;
|
usage_entry_info_list[modified_offline_license_number];
|
||||||
while (expired_offline_license_number == kInvalidEntry) {
|
offline_usage_entry_info.offline_license_expiry_time = kLruBaseTime;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Case 3: Expired license is selected.
|
// Test again, expecting that the expired license should be considered.
|
||||||
entry_to_remove = kInvalidEntry;
|
entry_to_remove = kInvalidEntry;
|
||||||
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
EXPECT_TRUE(UsageTableHeader::DetermineLicenseToRemoveForTesting(
|
||||||
usage_entry_info_list, kCurrentTime,
|
usage_entry_info_list, kCurrentTime,
|
||||||
/* unexpired_threshold = */ kLargeSetSize, &entry_to_remove));
|
/* unexpired_threshold = */ kLargeSetSize, &entry_to_remove));
|
||||||
EXPECT_EQ(expired_offline_license_number, entry_to_remove);
|
EXPECT_EQ(modified_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) {
|
TEST_F(UsageTableHeaderTest, PotentialTableCapacity_Unavailable) {
|
||||||
|
|||||||
Reference in New Issue
Block a user