Merge "Revert "Core CDM: Remove secure stop from LRU algorithm.""

This commit is contained in:
Alex Dale
2022-12-02 22:41:06 +00:00
committed by Android (Google) Code Review
3 changed files with 427 additions and 202 deletions

View File

@@ -96,6 +96,41 @@ 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;
@@ -1128,6 +1163,7 @@ 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,
@@ -1140,7 +1176,7 @@ CdmResponseType UsageTableHeader::ReleaseOldestEntry(
}
// Record metrics on success.
RecordLruEventMetrics(metrics, staleness);
RecordLruEventMetrics(metrics, staleness, storage_type);
return NO_ERROR;
}
@@ -1173,16 +1209,34 @@ 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;
const bool retrieve_response =
RetrieveOfflineLicense(device_files_.get(), usage_entry_info.key_set_id,
&license_message, &retrieved_entry_number);
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;
}
}
if (!retrieve_response) {
LOGW("Could not retrieve license message: usage_entry_number = %u",
usage_entry_number);
@@ -1211,18 +1265,22 @@ bool UsageTableHeader::LruUpgradeAllUsageEntries() {
// for replacement above all others.
usage_entry_info.last_use_time = license.license_start_time();
// Only offline licenses need |offline_license_expiry_time| set.
const video_widevine::License::Policy& policy = license.policy();
// TODO(b/139372190): Change how these fields are set once feature is
// implemented.
if (policy.license_duration_seconds() == 0) {
// Zero implies unlimited license duration.
usage_entry_info.offline_license_expiry_time =
license.license_start_time() + policy.rental_duration_seconds() +
policy.playback_duration_seconds();
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();
}
} else {
usage_entry_info.offline_license_expiry_time =
license.license_start_time() + policy.license_duration_seconds();
usage_entry_info.offline_license_expiry_time = 0;
}
} // End for loop.
@@ -1232,14 +1290,31 @@ 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;
}
@@ -1252,18 +1327,16 @@ bool UsageTableHeader::GetRemovalCandidate(uint32_t* entry_to_remove) {
lru_unexpired_threshold, entry_to_remove);
}
void UsageTableHeader::RecordLruEventMetrics(metrics::CryptoMetrics* metrics,
uint64_t staleness) {
void UsageTableHeader::RecordLruEventMetrics(
metrics::CryptoMetrics* metrics, uint64_t staleness,
CdmUsageEntryStorageType storage_type) {
if (metrics == nullptr) return;
// Usage info are deprecated, always record 0.
metrics->usage_table_header_lru_usage_info_count_.Record(0);
metrics->usage_table_header_lru_usage_info_count_.Record(UsageInfoCount());
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>(kDefaultEntryType));
static_cast<int>(storage_type));
}
// Static.
@@ -1286,13 +1359,14 @@ bool UsageTableHeader::DetermineLicenseToRemove(
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
// 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.
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();
@@ -1300,28 +1374,37 @@ bool UsageTableHeader::DetermineLicenseToRemove(
const CdmUsageEntryInfo& usage_entry_info =
usage_entry_info_list[entry_number];
if (usage_entry_info.storage_type != kStorageLicense) {
// Non-license storage type entries. Remove this entry.
if (usage_entry_info.storage_type != kStorageLicense &&
usage_entry_info.storage_type != kStorageUsageInfo) {
// Unknown storage type entries. Remove this entry.
*entry_to_remove = entry_number;
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_license_count;
if (stalest_unexpired_offline_license == kNoEntry ||
is_more_stale(entry_number, stalest_unexpired_offline_license)) {
stalest_unexpired_offline_license = entry_number;
}
} else {
} else if (usage_entry_info.storage_type == kStorageLicense) {
// 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(
@@ -1341,10 +1424,12 @@ bool UsageTableHeader::DetermineLicenseToRemove(
// Only consider an unexpired entry if the threshold is reached.
if (unexpired_license_count > unexpired_threshold) {
*entry_to_remove = select_most_stale(stalest_unexpired_offline_license,
stalest_expired_offline_license);
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 = stalest_expired_offline_license;
*entry_to_remove = select_most_stale(stalest_streaming_license,
stalest_expired_offline_license);
}
if (*entry_to_remove == kNoEntry) {