Merge "Handle unlimited usage table capacity."

This commit is contained in:
Alex Dale
2020-08-07 20:35:43 +00:00
committed by Android (Google) Code Review
6 changed files with 274 additions and 85 deletions

View File

@@ -8,6 +8,7 @@
#include <stdlib.h>
#include <iostream>
#include <limits>
#include <list>
#include <memory>
#include <sstream>
@@ -696,6 +697,12 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
LOGW("GetMaxUsageTableEntries failed");
return UNKNOWN_ERROR;
}
if (max_number_of_usage_entries == 0) {
// Zero indicates that the table is dynamically allocated and does
// not have a defined limit. Setting to max value of int32_t to
// be able to fit into a Java int.
max_number_of_usage_entries = std::numeric_limits<int32_t>::max();
}
*query_response = std::to_string(max_number_of_usage_entries);
return NO_ERROR;
} else if (query_token == QUERY_KEY_OEMCRYPTO_API_MINOR_VERSION) {

View File

@@ -2008,6 +2008,11 @@ bool CryptoSession::GetMaximumUsageTableEntries(SecurityLevel security_level,
metrics_->oemcrypto_maximum_usage_table_header_size_.Record(
*number_of_entries);
if (*number_of_entries == 0) {
// Special value, indicating that the table size is not directly
// limited.
return true;
}
return *number_of_entries >= kMinimumUsageTableEntriesSupported;
}

View File

@@ -176,13 +176,23 @@ bool UsageTableHeader::Init(CdmSecurityLevel security_level,
if (!crypto_session->GetMaximumUsageTableEntries(
requested_security_level_, &potential_table_capacity_)) {
LOGW(
"Could not determine usage table capacity, assuming default: "
"default = %zu",
kMinimumUsageTableEntriesSupported);
potential_table_capacity_ = kMinimumUsageTableEntriesSupported;
} else if (potential_table_capacity_ == 0) {
LOGD("Usage table capacity is unlimited: security_level = %d",
static_cast<int>(security_level));
} 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;
} else {
LOGD("Usage table capacity: %zu, security_level = %d",
potential_table_capacity_, static_cast<int>(security_level));
}
if (!device_files_->Init(security_level)) {
@@ -213,11 +223,21 @@ bool UsageTableHeader::Init(CdmSecurityLevel security_level,
}
}
// If the usage table header has been successfully loaded, and is at
// 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 the usage table header has been successfully loaded, and is
// at minimum capacity (>200) or the table size does not have a
// hard limit, 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() > potential_table_capacity()) {
if ((HasUnlimitedTableCapacity() &&
usage_entry_info_.size() > kMinimumUsageTableEntriesSupported) ||
(!HasUnlimitedTableCapacity() &&
usage_entry_info_.size() > potential_table_capacity())) {
LOGD("Checking if new entry can be added: size = %zu, capacity = %s",
usage_entry_info_.size(),
HasUnlimitedTableCapacity()
? "unlimited"
: std::to_string(potential_table_capacity()).c_str());
uint32_t temporary_usage_entry_number;
// Create a new temporary usage entry, close the session and then
@@ -359,6 +379,18 @@ CdmResponseType UsageTableHeader::AddEntry(
}
}
// Call to update the usage table header, but don't store the usage
// entry. If the entry is used by the CDM, the CDM session will make
// subsequent calls to update the usage entry and store that entry.
std::string usage_entry;
status = crypto_session->UpdateUsageEntry(&usage_table_header_, &usage_entry);
if (status != NO_ERROR) {
LOGE("Failed to update new usage entry: usage_entry_number = %u",
*usage_entry_number);
usage_entry_info_[*usage_entry_number].Clear();
return status;
}
LOGI("New usage entry: usage_entry_number = %u", *usage_entry_number);
StoreTable(device_files_.get());
return NO_ERROR;
@@ -1115,7 +1147,9 @@ bool UsageTableHeader::GetRemovalCandidate(uint32_t* entry_to_remove) {
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();
HasUnlimitedTableCapacity()
? kLruUnexpiredThresholdFraction * size()
: kLruUnexpiredThresholdFraction * potential_table_capacity();
return DetermineLicenseToRemove(usage_entry_info_, GetCurrentTime(),
lru_unexpired_threshold, entry_to_remove);
}