LRU algorithm adapts to usage table capacity.

[ Merge of http://go/wvgerrit/93564 ]

OEMCrypto v16 introduced the ability to report the maximum possible
size of the usage table to the CDM.  The LRU algorithm will take the
table capacity into account when deciding which entry is removed.

Bug: 148795097
Bug: 135298906
Test: CDM unit tests
Change-Id: Ibba88813618c13a9bf1121e560b8cc02b1c7e7a6
This commit is contained in:
Alex Dale
2020-02-18 12:22:23 -08:00
parent ea2e110213
commit 4a8aeb29ef
3 changed files with 92 additions and 16 deletions

View File

@@ -25,14 +25,14 @@ std::string kOldUsageEntryPoviderSessionToken =
constexpr int64_t kDefaultExpireDuration = 33 * 24 * 60 * 60; // 33 Days
// Number of elements to consider for removal using the LRU algorithm.
constexpr size_t kLruRemovalSetSize = 3;
// Threshold for maximum number of unexpired offline licenses before
// they are considered to be removed. This could occur if there are
// not enough expired offline or streaming licenses to remove.
// This threshold is set to prevent thrashing in the case that there
// are a very large number of unexpired offline licenses and few
// expired / streaming licenses (ie, number of unexpired licenses nears
// the capacity of the usage table).
constexpr size_t kLruUnexpiredThreshold = 150;
// Fraction of table capacity of number of unexpired offline licenses
// before they are considered to be removed. This could occur if
// there are not enough expired offline or streaming licenses to
// remove. This threshold is set to prevent thrashing in the case that
// there are a very large number of unexpired offline licenses and few
// expired / streaming licenses (ie, number of unexpired licenses
// nears the capacity of the usage table).
constexpr double kLruUnexpiredThresholdFraction = 0.75;
// Convert |license_message| -> SignedMessage -> License.
bool ParseLicenseFromLicenseMessage(const CdmKeyResponse& license_message,
@@ -162,6 +162,17 @@ bool UsageTableHeader::Init(CdmSecurityLevel security_level,
requested_security_level_ =
security_level_ == kSecurityLevelL3 ? kLevel3 : kLevelDefault;
if (!crypto_session->GetMaximumUsageTableEntries(
requested_security_level_, &potential_table_capacity_)) {
potential_table_capacity_ = kMinimumUsageTableEntriesSupported;
} else if (potential_table_capacity_ < kMinimumUsageTableEntriesSupported) {
LOGW(
"Reported usage table capacity is smaller than minimally required: "
"capacity = %zu, minimum = %zu",
potential_table_capacity_, kMinimumUsageTableEntriesSupported);
potential_table_capacity_ = kMinimumUsageTableEntriesSupported;
}
if (!file_handle_->Init(security_level)) {
LOGE("Failed to initialize device files");
return false;
@@ -193,7 +204,7 @@ bool UsageTableHeader::Init(CdmSecurityLevel security_level,
// minimum capacity (>200), we need to make sure we can still add and
// remove entries. If not, clear files/data and recreate usage header table.
if (status == NO_ERROR && lru_success) {
if (usage_entry_info_.size() > kMinimumUsageTableEntriesSupported) {
if (usage_entry_info_.size() > potential_table_capacity()) {
uint32_t temporary_usage_entry_number;
// Create a new temporary usage entry, close the session and then
@@ -886,8 +897,10 @@ bool UsageTableHeader::GetRemovalCandidates(
std::vector<uint32_t>* removal_candidates) {
LOGI("Locking to determine removal candidates");
std::unique_lock<std::mutex> auto_lock(usage_table_header_lock_);
const size_t lru_unexpired_threshold =
kLruUnexpiredThresholdFraction * potential_table_capacity();
return DetermineLicenseToRemove(usage_entry_info_, GetCurrentTime(),
kLruUnexpiredThreshold, kLruRemovalSetSize,
lru_unexpired_threshold, kLruRemovalSetSize,
removal_candidates);
}