Only one function for reporting usage support.

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

Replaced the two usage support functions GetUsageSupportType() and
UsageInformationSupport() into a single function HasUsageInfoSupport().

Since moving to only supporting a single usage info system (usage table
header + usage entries), the different usage support functions have
lost their purpose.

One version of the method works on an open session and will use a
cached value of the property if previously set.  The other can be
called without opening the session (as used for query calls).

This is part of larger fix for the usage table initialization process.

Bug: 169195093
Test: CE CDM unit tests
Change-Id: I637c24dd143e995dbb0f8848850e3c71ff1018eb
This commit is contained in:
Alex Dale
2021-04-09 01:31:05 -07:00
parent ccda4faf7b
commit ca335b2c11
10 changed files with 149 additions and 169 deletions

View File

@@ -160,8 +160,8 @@ class CdmSession {
license_parser_->provider_session_token().size() > 0); license_parser_->provider_session_token().size() > 0);
} }
virtual CdmUsageSupportType get_usage_support_type() { virtual bool supports_usage_info() const {
return usage_support_type_; return usage_table_header_ != nullptr;
} }
// This method will remove keys by resetting crypto resources and // This method will remove keys by resetting crypto resources and
@@ -297,8 +297,9 @@ class CdmSession {
// Usage related flags and data // Usage related flags and data
bool is_initial_usage_update_; bool is_initial_usage_update_;
bool is_usage_update_needed_; bool is_usage_update_needed_;
CdmUsageSupportType usage_support_type_; // Only assign |usage_table_header_| if capable of supporting usage
UsageTableHeader* usage_table_header_; // information.
UsageTableHeader* usage_table_header_ = nullptr;
uint32_t usage_entry_number_; uint32_t usage_entry_number_;
CdmUsageEntry usage_entry_; CdmUsageEntry usage_entry_;
std::string usage_provider_session_token_; std::string usage_provider_session_token_;

View File

@@ -238,14 +238,13 @@ class CryptoSession {
// Used to manipulate the CDM managed usage table header & entries, // Used to manipulate the CDM managed usage table header & entries,
// delegating calls to OEMCrypto. // delegating calls to OEMCrypto.
// Usage support. // Determines whether the OEMCrypto library supports usage info.
virtual CdmResponseType GetUsageSupportType(CdmUsageSupportType* type); // As of V16, the only valid type of support is usage table header +
// usage entries.
// The overloaded method with |security_level| may be called without a // The first method will use a cached value if present.
// preceding call to Open. The other method must call Open first. virtual bool HasUsageInfoSupport(bool* has_support);
virtual bool UsageInformationSupport(bool* has_support); virtual bool HasUsageInfoSupport(SecurityLevel security_level,
virtual bool UsageInformationSupport(SecurityLevel security_level, bool* has_support);
bool* has_support);
// Usage report. // Usage report.
virtual CdmResponseType DeactivateUsageInformation( virtual CdmResponseType DeactivateUsageInformation(
@@ -329,6 +328,12 @@ class CryptoSession {
CdmResponseType SelectKey(const std::string& key_id, CdmResponseType SelectKey(const std::string& key_id,
CdmCipherMode cipher_mode); CdmCipherMode cipher_mode);
// Retrieves the OEMCrypto usage info support for the specified
// |requested_security_level|.
// Caller should acquire the OEMCrypto read lock before calling.
bool HasUsageInfoSupportInternal(SecurityLevel requested_security_level,
bool* has_support);
// These methods fall back into each other in the order given, depending on // These methods fall back into each other in the order given, depending on
// how much data they were given and how much data OEMCrypto can accept in one // how much data they were given and how much data OEMCrypto can accept in one
// call. // call.
@@ -415,6 +420,15 @@ class CryptoSession {
static int session_count_; static int session_count_;
static int termination_counter_; static int termination_counter_;
enum CachedBooleanProperty {
// Property has not yet been checked/cached.
kBooleanUnset,
// Property has been cached as false.
kBooleanFalse,
// Property has been cached as true.
kBooleanTrue
};
metrics::CryptoMetrics* metrics_; metrics::CryptoMetrics* metrics_;
metrics::TimerMetric life_span_; metrics::TimerMetric life_span_;
uint32_t system_id_; uint32_t system_id_;
@@ -430,8 +444,9 @@ class CryptoSession {
bool is_destination_buffer_type_valid_; bool is_destination_buffer_type_valid_;
SecurityLevel requested_security_level_; SecurityLevel requested_security_level_;
CdmUsageSupportType usage_support_type_; // Open session-cached result of OEMCrypto_SupportsUsageTable().
UsageTableHeader* usage_table_header_; CachedBooleanProperty has_usage_info_support_ = kBooleanUnset;
UsageTableHeader* usage_table_header_ = nullptr;
static UsageTableHeader* usage_table_header_l1_; static UsageTableHeader* usage_table_header_l1_;
static UsageTableHeader* usage_table_header_l3_; static UsageTableHeader* usage_table_header_l3_;

View File

@@ -575,11 +575,11 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
return NO_ERROR; return NO_ERROR;
} else if (query_token == QUERY_KEY_USAGE_SUPPORT) { } else if (query_token == QUERY_KEY_USAGE_SUPPORT) {
bool supports_usage_reporting; bool supports_usage_reporting;
const bool got_info = crypto_session->UsageInformationSupport( const bool got_info = crypto_session->HasUsageInfoSupport(
security_level, &supports_usage_reporting); security_level, &supports_usage_reporting);
if (!got_info) { if (!got_info) {
LOGW("UsageInformationSupport failed"); LOGW("HasUsageInfoSupport failed");
metrics_->GetCryptoMetrics() metrics_->GetCryptoMetrics()
->crypto_session_usage_information_support_.SetError(got_info); ->crypto_session_usage_information_support_.SetError(got_info);
return UNKNOWN_ERROR; return UNKNOWN_ERROR;
@@ -1414,7 +1414,7 @@ CdmResponseType CdmEngine::RemoveAllUsageInfo(
usage_session_.reset(new CdmSession(file_system_, metrics_->AddSession())); usage_session_.reset(new CdmSession(file_system_, metrics_->AddSession()));
usage_session_->Init(usage_property_set_.get()); usage_session_->Init(usage_property_set_.get());
if (usage_session_->get_usage_support_type() == kUsageEntrySupport) { if (usage_session_->supports_usage_info()) {
std::vector<DeviceFiles::CdmUsageData> usage_data; std::vector<DeviceFiles::CdmUsageData> usage_data;
// Retrieve all usage information but delete only one before // Retrieve all usage information but delete only one before
// refetching. This is because deleting the usage entry // refetching. This is because deleting the usage entry
@@ -1505,7 +1505,7 @@ CdmResponseType CdmEngine::RemoveUsageInfo(
continue; continue;
} }
if (usage_session_->get_usage_support_type() == kUsageEntrySupport) { if (usage_session_->supports_usage_info()) {
status = usage_session_->DeleteUsageEntry(usage_entry_number); status = usage_session_->DeleteUsageEntry(usage_entry_number);
if (!handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id), if (!handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
provider_session_token)) { provider_session_token)) {
@@ -1910,7 +1910,7 @@ void CdmEngine::OnTimerEvent() {
for (CdmSessionList::iterator iter = sessions.begin(); for (CdmSessionList::iterator iter = sessions.begin();
iter != sessions.end(); ++iter) { iter != sessions.end(); ++iter) {
(*iter)->reset_usage_flags(); (*iter)->reset_usage_flags();
if ((*iter)->get_usage_support_type() == kUsageEntrySupport && if ((*iter)->supports_usage_info() &&
(*iter)->has_provider_session_token()) { (*iter)->has_provider_session_token()) {
(*iter)->UpdateUsageEntryInformation(); (*iter)->UpdateUsageEntryInformation();
} }

View File

@@ -82,7 +82,6 @@ CdmSession::CdmSession(FileSystem* file_system,
has_decrypted_since_last_report_(false), has_decrypted_since_last_report_(false),
is_initial_usage_update_(true), is_initial_usage_update_(true),
is_usage_update_needed_(false), is_usage_update_needed_(false),
usage_support_type_(kNonSecureUsageSupport),
usage_table_header_(nullptr), usage_table_header_(nullptr),
usage_entry_number_(0), usage_entry_number_(0),
mock_license_parser_in_use_(false), mock_license_parser_in_use_(false),
@@ -94,9 +93,7 @@ CdmSession::CdmSession(FileSystem* file_system,
} }
CdmSession::~CdmSession() { CdmSession::~CdmSession() {
if (usage_support_type_ == kUsageEntrySupport && if (has_provider_session_token() && supports_usage_info() && !is_release_) {
has_provider_session_token() && usage_table_header_ != nullptr &&
!is_release_) {
UpdateUsageEntryInformation(); UpdateUsageEntryInformation();
} }
@@ -162,11 +159,9 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
return SESSION_FILE_HANDLE_INIT_ERROR; return SESSION_FILE_HANDLE_INIT_ERROR;
} }
if (crypto_session_->GetUsageSupportType(&usage_support_type_) == NO_ERROR) { bool has_support = false;
if (usage_support_type_ == kUsageEntrySupport) if (crypto_session_->HasUsageInfoSupport(&has_support) && has_support) {
usage_table_header_ = crypto_session_->GetUsageTableHeader(); usage_table_header_ = crypto_session_->GetUsageTableHeader();
} else {
usage_support_type_ = kNonSecureUsageSupport;
} }
if (cdm_client_property_set != nullptr) if (cdm_client_property_set != nullptr)
@@ -222,9 +217,7 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
CdmResponseType CdmSession::ReleaseOfflineResources() { CdmResponseType CdmSession::ReleaseOfflineResources() {
// |license_parser_| and |policy_engine_| are reset in Init. No need to // |license_parser_| and |policy_engine_| are reset in Init. No need to
// deallocate here. // deallocate here.
if (usage_support_type_ == kUsageEntrySupport && if (has_provider_session_token() && supports_usage_info() && !is_release_) {
has_provider_session_token() && usage_table_header_ != nullptr &&
!is_release_) {
UpdateUsageEntryInformation(); UpdateUsageEntryInformation();
} }
@@ -319,10 +312,9 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
std::string provider_session_token; std::string provider_session_token;
bool sign_fake_request = false; // TODO(b/169483174): remove this variable. bool sign_fake_request = false; // TODO(b/169483174): remove this variable.
if (usage_support_type_ == kUsageEntrySupport) { if (supports_usage_info()) {
if (!license_parser_->ExtractProviderSessionToken( if (!license_parser_->ExtractProviderSessionToken(
key_response_, &provider_session_token) || key_response_, &provider_session_token)) {
usage_table_header_ == nullptr) {
provider_session_token.clear(); provider_session_token.clear();
sign_fake_request = true; // TODO(b/169483174): remove this line. sign_fake_request = true; // TODO(b/169483174): remove this line.
} else if (!VerifyOfflineUsageEntry()) { } else if (!VerifyOfflineUsageEntry()) {
@@ -378,8 +370,7 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
} }
} }
if (usage_support_type_ == kUsageEntrySupport && if (!provider_session_token.empty() && supports_usage_info()) {
!provider_session_token.empty() && usage_table_header_ != nullptr) {
CdmResponseType sts = usage_table_header_->UpdateEntry( CdmResponseType sts = usage_table_header_->UpdateEntry(
usage_entry_number_, crypto_session_.get(), &usage_entry_); usage_entry_number_, crypto_session_.get(), &usage_entry_);
if (sts != NO_ERROR) { if (sts != NO_ERROR) {
@@ -418,8 +409,7 @@ CdmResponseType CdmSession::RestoreUsageSession(
if (status != NO_ERROR) return status; if (status != NO_ERROR) return status;
CdmResponseType sts = NO_ERROR; CdmResponseType sts = NO_ERROR;
if (usage_support_type_ == kUsageEntrySupport && if (supports_usage_info()) {
usage_table_header_ != nullptr) {
sts = usage_table_header_->LoadEntry(crypto_session_.get(), usage_entry_, sts = usage_table_header_->LoadEntry(crypto_session_.get(), usage_entry_,
usage_entry_number_); usage_entry_number_);
crypto_metrics_->usage_table_header_load_entry_.Increment(sts); crypto_metrics_->usage_table_header_load_entry_.Increment(sts);
@@ -437,8 +427,7 @@ CdmResponseType CdmSession::RestoreUsageSession(
return RELEASE_LICENSE_ERROR_2; return RELEASE_LICENSE_ERROR_2;
} }
if (usage_support_type_ == kUsageEntrySupport && if (supports_usage_info()) {
usage_table_header_ != nullptr) {
sts = usage_table_header_->UpdateEntry( sts = usage_table_header_->UpdateEntry(
usage_entry_number_, crypto_session_.get(), &usage_entry_); usage_entry_number_, crypto_session_.get(), &usage_entry_);
if (sts != NO_ERROR) { if (sts != NO_ERROR) {
@@ -580,8 +569,7 @@ CdmResponseType CdmSession::AddKeyInternal(const CdmKeyResponse& key_response) {
// to be created. // to be created.
CdmResponseType sts; CdmResponseType sts;
std::string provider_session_token; std::string provider_session_token;
if (usage_support_type_ == kUsageEntrySupport && if (supports_usage_info()) {
usage_table_header_ != nullptr) {
if (license_parser_->ExtractProviderSessionToken( if (license_parser_->ExtractProviderSessionToken(
key_response, &provider_session_token) && key_response, &provider_session_token) &&
!provider_session_token.empty()) { !provider_session_token.empty()) {
@@ -605,8 +593,7 @@ CdmResponseType CdmSession::AddKeyInternal(const CdmKeyResponse& key_response) {
version_info.license_service_version()); version_info.license_service_version());
// Update or invalidate entry if usage table header+entries are supported // Update or invalidate entry if usage table header+entries are supported
if (usage_support_type_ == kUsageEntrySupport && if (!provider_session_token.empty() && supports_usage_info()) {
!provider_session_token.empty() && usage_table_header_ != nullptr) {
if (sts != KEY_ADDED) { if (sts != KEY_ADDED) {
const CdmResponseType invalidate_sts = const CdmResponseType invalidate_sts =
usage_table_header_->InvalidateEntry( usage_table_header_->InvalidateEntry(
@@ -630,9 +617,7 @@ CdmResponseType CdmSession::AddKeyInternal(const CdmKeyResponse& key_response) {
license_parser_->provider_session_token().size()); license_parser_->provider_session_token().size());
if ((is_offline_ || has_provider_session_token()) && !is_temporary_) { if ((is_offline_ || has_provider_session_token()) && !is_temporary_) {
if (has_provider_session_token() && if (has_provider_session_token() && supports_usage_info()) {
usage_support_type_ == kUsageEntrySupport &&
usage_table_header_ != nullptr) {
usage_table_header_->UpdateEntry(usage_entry_number_, usage_table_header_->UpdateEntry(usage_entry_number_,
crypto_session_.get(), &usage_entry_); crypto_session_.get(), &usage_entry_);
} }
@@ -832,8 +817,7 @@ CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyRequest* key_request) {
if (KEY_MESSAGE != status) return status; if (KEY_MESSAGE != status) return status;
if (has_provider_session_token() && if (has_provider_session_token() && supports_usage_info()) {
usage_support_type_ == kUsageEntrySupport) {
status = usage_table_header_->UpdateEntry( status = usage_table_header_->UpdateEntry(
usage_entry_number_, crypto_session_.get(), &usage_entry_); usage_entry_number_, crypto_session_.get(), &usage_entry_);
@@ -847,7 +831,7 @@ CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyRequest* key_request) {
if (!StoreLicense(DeviceFiles::kLicenseStateReleasing, nullptr)) if (!StoreLicense(DeviceFiles::kLicenseStateReleasing, nullptr))
return RELEASE_KEY_REQUEST_ERROR; return RELEASE_KEY_REQUEST_ERROR;
} else if (!usage_provider_session_token_.empty()) { } else if (!usage_provider_session_token_.empty()) {
if (usage_support_type_ == kUsageEntrySupport) { if (supports_usage_info()) {
if (!UpdateUsageInfo()) return RELEASE_USAGE_INFO_FAILED; if (!UpdateUsageInfo()) return RELEASE_USAGE_INFO_FAILED;
} }
} }
@@ -880,9 +864,8 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
LOGE("CDM session not initialized"); LOGE("CDM session not initialized");
return NOT_INITIALIZED_ERROR; return NOT_INITIALIZED_ERROR;
} }
if (usage_support_type_ != kUsageEntrySupport) { if (!supports_usage_info()) {
LOGE("Unexpected usage support type: %d", LOGE("Cannot delete entry, usage table not supported");
static_cast<int>(usage_support_type_));
return INCORRECT_USAGE_SUPPORT_TYPE_1; return INCORRECT_USAGE_SUPPORT_TYPE_1;
} }
@@ -897,11 +880,9 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
if (sts != NO_ERROR) return sts; if (sts != NO_ERROR) return sts;
usage_table_header_ = nullptr; usage_table_header_ = nullptr;
if (crypto_session_->GetUsageSupportType(&usage_support_type_) == NO_ERROR) { bool has_support = false;
if (usage_support_type_ == kUsageEntrySupport) if (crypto_session_->HasUsageInfoSupport(&has_support) && has_support) {
usage_table_header_ = crypto_session_->GetUsageTableHeader(); usage_table_header_ = crypto_session_->GetUsageTableHeader();
} else {
usage_support_type_ = kNonSecureUsageSupport;
} }
if (usage_table_header_ == nullptr) { if (usage_table_header_ == nullptr) {
@@ -996,11 +977,10 @@ CdmResponseType CdmSession::StoreLicense() {
usage_entry_number_, drm_certificate_, wrapped_private_key_)) { usage_entry_number_, drm_certificate_, wrapped_private_key_)) {
LOGE("Unable to store usage info"); LOGE("Unable to store usage info");
// Usage info file is corrupt. Delete current usage entry and file. // Usage info file is corrupt. Delete current usage entry and file.
if (usage_support_type_ == kUsageEntrySupport) { if (supports_usage_info()) {
DeleteUsageEntry(usage_entry_number_); DeleteUsageEntry(usage_entry_number_);
} else { } else {
LOGW("Unexpected usage support type: %d", LOGW("Cannot store, usage table not supported");
static_cast<int>(usage_support_type_));
} }
std::vector<std::string> provider_session_tokens; std::vector<std::string> provider_session_tokens;
file_handle_->DeleteAllUsageInfoForApp( file_handle_->DeleteAllUsageInfoForApp(
@@ -1052,8 +1032,7 @@ CdmResponseType CdmSession::RemoveKeys() {
CdmResponseType CdmSession::RemoveLicense() { CdmResponseType CdmSession::RemoveLicense() {
if (is_offline_ || has_provider_session_token()) { if (is_offline_ || has_provider_session_token()) {
if (usage_support_type_ == kUsageEntrySupport && if (has_provider_session_token() && supports_usage_info()) {
has_provider_session_token()) {
DeleteUsageEntry(usage_entry_number_); DeleteUsageEntry(usage_entry_number_);
} }
DeleteLicenseFile(); DeleteLicenseFile();
@@ -1103,14 +1082,10 @@ void CdmSession::GetApplicationId(std::string* app_id) {
} }
CdmResponseType CdmSession::UpdateUsageEntryInformation() { CdmResponseType CdmSession::UpdateUsageEntryInformation() {
if (usage_support_type_ != kUsageEntrySupport || if (!has_provider_session_token() || !supports_usage_info()) {
!has_provider_session_token() || usage_table_header_ == nullptr) { LOGE("Unexpected state: usage_support = %s, PST present = %s, ",
LOGE( supports_usage_info() ? "true" : "false",
"Unexpected state: usage support type = %d, PST present = %s, " has_provider_session_token() ? "yes" : "no");
"usage table header available = %s",
static_cast<int>(usage_support_type_),
has_provider_session_token() ? "yes" : "no",
usage_table_header_ == nullptr ? "no" : "yes");
return INCORRECT_USAGE_SUPPORT_TYPE_2; return INCORRECT_USAGE_SUPPORT_TYPE_2;
} }

View File

@@ -196,7 +196,7 @@ CdmResponseType ClientIdentification::Prepare(
if (is_license_request_) { if (is_license_request_) {
bool supports_usage_information; bool supports_usage_information;
if (crypto_session_->UsageInformationSupport(&supports_usage_information)) { if (crypto_session_->HasUsageInfoSupport(&supports_usage_information)) {
client_capabilities->set_session_token(supports_usage_information); client_capabilities->set_session_token(supports_usage_information);
} }

View File

@@ -164,6 +164,11 @@ size_t GenericEncryptionBlockSize(CdmEncryptionAlgorithm algorithm) {
} }
return kAes128BlockSize; return kAes128BlockSize;
} }
const char* SecurityLevelToString(SecurityLevel security_level) {
return security_level == kLevel3 ? QUERY_VALUE_SECURITY_LEVEL_L3.c_str()
: QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str();
}
} // namespace } // namespace
shared_mutex CryptoSession::static_field_mutex_; shared_mutex CryptoSession::static_field_mutex_;
@@ -251,8 +256,6 @@ CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics)
update_usage_table_after_close_session_(false), update_usage_table_after_close_session_(false),
is_destination_buffer_type_valid_(false), is_destination_buffer_type_valid_(false),
requested_security_level_(kLevelDefault), requested_security_level_(kLevelDefault),
usage_support_type_(kUnknownUsageSupport),
usage_table_header_(nullptr),
api_version_(0), api_version_(0),
max_subsample_region_size_(0) { max_subsample_region_size_(0) {
assert(metrics); assert(metrics);
@@ -491,8 +494,8 @@ CdmSecurityLevel CryptoSession::GetSecurityLevel() {
CdmSecurityLevel CryptoSession::GetSecurityLevel( CdmSecurityLevel CryptoSession::GetSecurityLevel(
SecurityLevel requested_security_level) { SecurityLevel requested_security_level) {
LOGV("Getting security level: requested_security_level = %d", LOGV("Getting security level: requested_security_level = %s",
static_cast<int>(requested_security_level)); SecurityLevelToString(requested_security_level));
RETURN_IF_UNINITIALIZED(kSecurityLevelUninitialized); RETURN_IF_UNINITIALIZED(kSecurityLevelUninitialized);
const char* const level = WithOecReadLock("GetSecurityLevel", [&] { const char* const level = WithOecReadLock("GetSecurityLevel", [&] {
return OEMCrypto_SecurityLevel(requested_security_level); return OEMCrypto_SecurityLevel(requested_security_level);
@@ -610,8 +613,8 @@ bool CryptoSession::GetApiVersion(uint32_t* version) {
bool CryptoSession::GetApiVersion(SecurityLevel security_level, bool CryptoSession::GetApiVersion(SecurityLevel security_level,
uint32_t* version) { uint32_t* version) {
LOGV("Getting API version: security_level = %d", LOGV("Getting API version: security_level = %s",
static_cast<int>(security_level)); SecurityLevelToString(security_level));
if (!version) { if (!version) {
LOGE("Output parameter |version| not provided"); LOGE("Output parameter |version| not provided");
return false; return false;
@@ -628,8 +631,8 @@ bool CryptoSession::GetApiVersion(SecurityLevel security_level,
bool CryptoSession::GetApiMinorVersion(SecurityLevel security_level, bool CryptoSession::GetApiMinorVersion(SecurityLevel security_level,
uint32_t* minor_version) { uint32_t* minor_version) {
LOGV("Getting API minor version: security_level = %d", LOGV("Getting API minor version: security_level = %s",
static_cast<int>(security_level)); SecurityLevelToString(security_level));
if (!minor_version) { if (!minor_version) {
LOGE("Output parameter |minor_version| not provided"); LOGE("Output parameter |minor_version| not provided");
return false; return false;
@@ -754,9 +757,7 @@ uint8_t CryptoSession::GetSecurityPatchLevel() {
CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) { CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
LOGD("Opening crypto session: requested_security_level = %s", LOGD("Opening crypto session: requested_security_level = %s",
requested_security_level == kLevel3 SecurityLevelToString(requested_security_level));
? QUERY_VALUE_SECURITY_LEVEL_L3.c_str()
: QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str());
RETURN_IF_UNINITIALIZED(UNKNOWN_ERROR); RETURN_IF_UNINITIALIZED(UNKNOWN_ERROR);
if (open_) return NO_ERROR; if (open_) return NO_ERROR;
@@ -838,11 +839,11 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
return USAGE_SUPPORT_GET_API_FAILED; return USAGE_SUPPORT_GET_API_FAILED;
} }
CdmUsageSupportType usage_support_type; bool supports_usage_table = false;
result = GetUsageSupportType(&usage_support_type); if (HasUsageInfoSupport(&supports_usage_table)) {
if (result == NO_ERROR) { metrics_->oemcrypto_usage_table_support_.Record(
metrics_->oemcrypto_usage_table_support_.Record(usage_support_type); supports_usage_table ? kUsageEntrySupport : kNonSecureUsageSupport);
if (usage_support_type == kUsageEntrySupport) { if (supports_usage_table) {
CdmSecurityLevel security_level = GetSecurityLevel(); CdmSecurityLevel security_level = GetSecurityLevel();
if (security_level == kSecurityLevelL1 || if (security_level == kSecurityLevelL1 ||
security_level == kSecurityLevelL3) { security_level == kSecurityLevelL3) {
@@ -875,7 +876,8 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
} // End |static_field_mutex_| block. } // End |static_field_mutex_| block.
} }
} else { } else {
metrics_->oemcrypto_usage_table_support_.SetError(result); metrics_->oemcrypto_usage_table_support_.SetError(
USAGE_INFORMATION_SUPPORT_FAILED);
} }
// Do not add logic after this point as it may never get exercised. In the // Do not add logic after this point as it may never get exercised. In the
@@ -898,6 +900,9 @@ void CryptoSession::Close() {
"Close", [&] { close_sts = OEMCrypto_CloseSession(oec_session_id_); }); "Close", [&] { close_sts = OEMCrypto_CloseSession(oec_session_id_); });
metrics_->oemcrypto_close_session_.Increment(close_sts); metrics_->oemcrypto_close_session_.Increment(close_sts);
// Clear cached values.
has_usage_info_support_ = kBooleanUnset;
if (close_sts != OEMCrypto_SUCCESS) { if (close_sts != OEMCrypto_SUCCESS) {
LOGW("OEMCrypto_CloseSession failed: status = %d", LOGW("OEMCrypto_CloseSession failed: status = %d",
static_cast<int>(close_sts)); static_cast<int>(close_sts));
@@ -1637,19 +1642,39 @@ CdmResponseType CryptoSession::Decrypt(
} }
} }
bool CryptoSession::UsageInformationSupport(bool* has_support) { bool CryptoSession::HasUsageInfoSupport(bool* has_support) {
LOGV("Checking if usage information is supported");
RETURN_IF_NOT_OPEN(false); RETURN_IF_NOT_OPEN(false);
return UsageInformationSupport(requested_security_level_, has_support); RETURN_IF_NULL(has_support, false);
return WithOecReadLock("HasUsageInfoSupport", [&] {
// Use cached value if set.
if (has_usage_info_support_ != kBooleanUnset) {
*has_support = (has_usage_info_support_ == kBooleanTrue);
return true;
}
if (!HasUsageInfoSupportInternal(requested_security_level_, has_support)) {
return false;
}
// Cache result if successful.
has_usage_info_support_ = (*has_support ? kBooleanTrue : kBooleanFalse);
return true;
});
} }
bool CryptoSession::UsageInformationSupport(SecurityLevel security_level, bool CryptoSession::HasUsageInfoSupport(SecurityLevel requested_security_level,
bool* has_support) { bool* has_support) {
LOGV("Checking if usage information is supported: security_level = %d",
static_cast<int>(security_level));
RETURN_IF_UNINITIALIZED(false); RETURN_IF_UNINITIALIZED(false);
WithOecReadLock("UsageInformationSupport", [&] { RETURN_IF_NULL(has_support, false);
*has_support = OEMCrypto_SupportsUsageTable(security_level); return WithOecReadLock("HasUsageInfoSupport", [&] {
return HasUsageInfoSupportInternal(requested_security_level, has_support);
});
}
bool CryptoSession::HasUsageInfoSupportInternal(
SecurityLevel requested_security_level, bool* has_support) {
LOGV("requested_security_level = %s",
SecurityLevelToString(requested_security_level));
*has_support = WithOecReadLock("HasUsageInfoSupport", [&] {
return OEMCrypto_SupportsUsageTable(requested_security_level);
}); });
return true; return true;
} }
@@ -1875,8 +1900,8 @@ CdmResponseType CryptoSession::GetHdcpCapabilities(HdcpCapability* current,
CdmResponseType CryptoSession::GetHdcpCapabilities(SecurityLevel security_level, CdmResponseType CryptoSession::GetHdcpCapabilities(SecurityLevel security_level,
HdcpCapability* current, HdcpCapability* current,
HdcpCapability* max) { HdcpCapability* max) {
LOGV("Getting HDCP capabilities: id = %u, security_level = %d", LOGV("Getting HDCP capabilities: id = %u, security_level = %s",
oec_session_id_, static_cast<int>(security_level)); oec_session_id_, SecurityLevelToString(security_level));
RETURN_IF_UNINITIALIZED(CRYPTO_SESSION_NOT_INITIALIZED); RETURN_IF_UNINITIALIZED(CRYPTO_SESSION_NOT_INITIALIZED);
RETURN_IF_NULL(current, PARAMETER_NULL); RETURN_IF_NULL(current, PARAMETER_NULL);
RETURN_IF_NULL(max, PARAMETER_NULL); RETURN_IF_NULL(max, PARAMETER_NULL);
@@ -1930,8 +1955,8 @@ CdmResponseType CryptoSession::GetRandom(size_t data_length,
CdmResponseType CryptoSession::GetNumberOfOpenSessions( CdmResponseType CryptoSession::GetNumberOfOpenSessions(
SecurityLevel security_level, size_t* count) { SecurityLevel security_level, size_t* count) {
LOGV("Getting number of open sessions: id = %u, security_level = %d", LOGV("Getting number of open sessions: id = %u, security_level = %s",
oec_session_id_, static_cast<int>(security_level)); oec_session_id_, SecurityLevelToString(security_level));
RETURN_IF_UNINITIALIZED(CRYPTO_SESSION_NOT_INITIALIZED); RETURN_IF_UNINITIALIZED(CRYPTO_SESSION_NOT_INITIALIZED);
RETURN_IF_NULL(count, PARAMETER_NULL); RETURN_IF_NULL(count, PARAMETER_NULL);
@@ -1954,8 +1979,8 @@ CdmResponseType CryptoSession::GetNumberOfOpenSessions(
CdmResponseType CryptoSession::GetMaxNumberOfSessions( CdmResponseType CryptoSession::GetMaxNumberOfSessions(
SecurityLevel security_level, size_t* max) { SecurityLevel security_level, size_t* max) {
LOGV("Getting max number of sessions: id = %u, security_level = %d", LOGV("Getting max number of sessions: id = %u, security_level = %s",
oec_session_id_, static_cast<int>(security_level)); oec_session_id_, SecurityLevelToString(security_level));
RETURN_IF_UNINITIALIZED(CRYPTO_SESSION_NOT_INITIALIZED); RETURN_IF_UNINITIALIZED(CRYPTO_SESSION_NOT_INITIALIZED);
RETURN_IF_NULL(max, PARAMETER_NULL); RETURN_IF_NULL(max, PARAMETER_NULL);
@@ -2036,8 +2061,8 @@ bool CryptoSession::GetResourceRatingTier(uint32_t* tier) {
bool CryptoSession::GetResourceRatingTier(SecurityLevel security_level, bool CryptoSession::GetResourceRatingTier(SecurityLevel security_level,
uint32_t* tier) { uint32_t* tier) {
LOGV("Getting resource rating tier: security_level = %d", LOGV("Getting resource rating tier: security_level = %s",
static_cast<int>(security_level)); SecurityLevelToString(security_level));
RETURN_IF_UNINITIALIZED(false); RETURN_IF_UNINITIALIZED(false);
RETURN_IF_NULL(tier, false); RETURN_IF_NULL(tier, false);
@@ -2064,8 +2089,8 @@ bool CryptoSession::GetBuildInformation(std::string* info) {
bool CryptoSession::GetBuildInformation(SecurityLevel security_level, bool CryptoSession::GetBuildInformation(SecurityLevel security_level,
std::string* info) { std::string* info) {
LOGV("Getting build information: security_level = %d", LOGV("Getting build information: security_level = %s",
static_cast<int>(security_level)); SecurityLevelToString(security_level));
RETURN_IF_UNINITIALIZED(false); RETURN_IF_UNINITIALIZED(false);
RETURN_IF_NULL(info, false); RETURN_IF_NULL(info, false);
@@ -2084,8 +2109,8 @@ bool CryptoSession::GetBuildInformation(SecurityLevel security_level,
bool CryptoSession::GetMaximumUsageTableEntries(SecurityLevel security_level, bool CryptoSession::GetMaximumUsageTableEntries(SecurityLevel security_level,
size_t* number_of_entries) { size_t* number_of_entries) {
LOGV("Getting maximum usage table entries: security_level = %d", LOGV("Getting maximum usage table entries: security_level = %s",
static_cast<int>(security_level)); SecurityLevelToString(security_level));
RETURN_IF_UNINITIALIZED(false); RETURN_IF_UNINITIALIZED(false);
if (number_of_entries == nullptr) { if (number_of_entries == nullptr) {
LOGE("Output parameter |number_of_entries| not provided"); LOGE("Output parameter |number_of_entries| not provided");
@@ -2422,40 +2447,11 @@ CdmResponseType CryptoSession::GenericVerify(const std::string& message,
} }
} }
CdmResponseType CryptoSession::GetUsageSupportType(
CdmUsageSupportType* usage_support_type) {
LOGV("Getting usage support type: id = %u", oec_session_id_);
RETURN_IF_NULL(usage_support_type, PARAMETER_NULL);
if (usage_support_type_ != kUnknownUsageSupport) {
*usage_support_type = usage_support_type_;
return NO_ERROR;
}
bool has_support = false;
if (!UsageInformationSupport(&has_support)) {
LOGE("UsageInformationSupport failed");
return USAGE_INFORMATION_SUPPORT_FAILED;
}
if (!has_support) {
*usage_support_type = usage_support_type_ = kNonSecureUsageSupport;
} else {
// As of v16, all supported version of OEMCrypto provide usage entry
// support or no usage info support.
*usage_support_type = usage_support_type_ = kUsageEntrySupport;
}
return NO_ERROR;
}
CdmResponseType CryptoSession::CreateUsageTableHeader( CdmResponseType CryptoSession::CreateUsageTableHeader(
SecurityLevel requested_security_level, SecurityLevel requested_security_level,
CdmUsageTableHeader* usage_table_header) { CdmUsageTableHeader* usage_table_header) {
LOGV("Creating usage table header: requested_security_level = %s", LOGV("Creating usage table header: requested_security_level = %s",
requested_security_level == kLevel3 SecurityLevelToString(requested_security_level));
? QUERY_VALUE_SECURITY_LEVEL_L3.c_str()
: QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str());
RETURN_IF_NULL(usage_table_header, PARAMETER_NULL); RETURN_IF_NULL(usage_table_header, PARAMETER_NULL);
usage_table_header->resize(kEstimatedInitialUsageTableHeader); usage_table_header->resize(kEstimatedInitialUsageTableHeader);
@@ -2496,9 +2492,7 @@ CdmResponseType CryptoSession::LoadUsageTableHeader(
SecurityLevel requested_security_level, SecurityLevel requested_security_level,
const CdmUsageTableHeader& usage_table_header) { const CdmUsageTableHeader& usage_table_header) {
LOGV("Loading usage table header: requested_security_level = %s", LOGV("Loading usage table header: requested_security_level = %s",
requested_security_level == kLevel3 SecurityLevelToString(requested_security_level));
? QUERY_VALUE_SECURITY_LEVEL_L3.c_str()
: QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str());
OEMCryptoResult result; OEMCryptoResult result;
WithOecWriteLock("LoadUsageTableHeader", [&] { WithOecWriteLock("LoadUsageTableHeader", [&] {
@@ -2540,9 +2534,7 @@ CdmResponseType CryptoSession::ShrinkUsageTableHeader(
SecurityLevel requested_security_level, uint32_t new_entry_count, SecurityLevel requested_security_level, uint32_t new_entry_count,
CdmUsageTableHeader* usage_table_header) { CdmUsageTableHeader* usage_table_header) {
LOGV("Shrinking usage table header: requested_security_level = %s", LOGV("Shrinking usage table header: requested_security_level = %s",
requested_security_level == kLevel3 SecurityLevelToString(requested_security_level));
? QUERY_VALUE_SECURITY_LEVEL_L3.c_str()
: QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str());
RETURN_IF_NULL(usage_table_header, PARAMETER_NULL); RETURN_IF_NULL(usage_table_header, PARAMETER_NULL);
size_t usage_table_header_len = 0; size_t usage_table_header_len = 0;
@@ -3085,5 +3077,4 @@ CryptoSession* CryptoSessionFactory::MakeCryptoSession(
metrics::CryptoMetrics* crypto_metrics) { metrics::CryptoMetrics* crypto_metrics) {
return new CryptoSession(crypto_metrics); return new CryptoSession(crypto_metrics);
} }
} // namespace wvcdm } // namespace wvcdm

View File

@@ -437,9 +437,8 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
} }
// TODO(rfrias): Refactor to avoid needing to call CdmSession // TODO(rfrias): Refactor to avoid needing to call CdmSession
if (cdm_session && if (cdm_session && cdm_session->supports_usage_info()) {
cdm_session->get_usage_support_type() == kUsageEntrySupport) { const CdmResponseType status = cdm_session->UpdateUsageEntryInformation();
CdmResponseType status = cdm_session->UpdateUsageEntryInformation();
if (NO_ERROR != status) return status; if (NO_ERROR != status) return status;
} }
@@ -843,9 +842,8 @@ CdmResponseType CdmLicense::RestoreOfflineLicense(
} }
if (!provider_session_token_.empty()) { if (!provider_session_token_.empty()) {
if (cdm_session && if (cdm_session && cdm_session->supports_usage_info()) {
cdm_session->get_usage_support_type() == kUsageEntrySupport) { const CdmResponseType status = cdm_session->UpdateUsageEntryInformation();
CdmResponseType status = cdm_session->UpdateUsageEntryInformation();
if (NO_ERROR != status) return sts; if (NO_ERROR != status) return sts;
} }

View File

@@ -136,10 +136,10 @@ class MockCryptoSession : public TestCryptoSession {
public: public:
MockCryptoSession(metrics::CryptoMetrics* crypto_metrics) MockCryptoSession(metrics::CryptoMetrics* crypto_metrics)
: TestCryptoSession(crypto_metrics) { : TestCryptoSession(crypto_metrics) {
// By default, call the concrete implementation of GetUsageSupportType. // By default, call the concrete implementation of HasUsageInfoSupport.
ON_CALL(*this, GetUsageSupportType(_)) ON_CALL(*this, HasUsageInfoSupport(_))
.WillByDefault( .WillByDefault(
Invoke(this, &MockCryptoSession::BaseGetUsageSupportType)); Invoke(this, &MockCryptoSession::BaseHasUsageInfoSupport));
} }
MOCK_METHOD1(GetClientToken, bool(std::string*)); MOCK_METHOD1(GetClientToken, bool(std::string*));
MOCK_METHOD1(GetProvisioningToken, CdmResponseType(std::string*)); MOCK_METHOD1(GetProvisioningToken, CdmResponseType(std::string*));
@@ -150,11 +150,11 @@ class MockCryptoSession : public TestCryptoSession {
MOCK_METHOD1(LoadCertificatePrivateKey, MOCK_METHOD1(LoadCertificatePrivateKey,
CdmResponseType(const CryptoWrappedKey&)); CdmResponseType(const CryptoWrappedKey&));
MOCK_METHOD0(DeleteAllUsageReports, CdmResponseType()); MOCK_METHOD0(DeleteAllUsageReports, CdmResponseType());
MOCK_METHOD1(GetUsageSupportType, CdmResponseType(CdmUsageSupportType* type)); MOCK_METHOD1(HasUsageInfoSupport, bool(bool*));
MOCK_METHOD0(GetUsageTableHeader, UsageTableHeader*()); MOCK_METHOD0(GetUsageTableHeader, UsageTableHeader*());
CdmResponseType BaseGetUsageSupportType(CdmUsageSupportType* type) { bool BaseHasUsageInfoSupport(bool* has_support) {
return CryptoSession::GetUsageSupportType(type); return CryptoSession::HasUsageInfoSupport(has_support);
} }
}; };
@@ -291,17 +291,15 @@ TEST_F(CdmSessionTest, UpdateUsageEntry) {
.WillOnce(Return(true)); .WillOnce(Return(true));
// Set up mocks and expectations for the UpdateUsageEntryInformation call. // Set up mocks and expectations for the UpdateUsageEntryInformation call.
EXPECT_CALL(*crypto_session_, GetUsageSupportType(_)) EXPECT_CALL(*crypto_session_, HasUsageInfoSupport(_))
.WillRepeatedly( .WillRepeatedly(DoAll(SetArgPointee<0>(true), Return(true)));
DoAll(SetArgPointee<0>(kUsageEntrySupport), Return(NO_ERROR)));
EXPECT_CALL(*license_parser_, provider_session_token()) EXPECT_CALL(*license_parser_, provider_session_token())
.WillRepeatedly(Return("Mock provider session token")); .WillRepeatedly(Return("Mock provider session token"));
EXPECT_CALL(usage_table_header_, UpdateEntry(_, NotNull(), NotNull())) EXPECT_CALL(usage_table_header_, UpdateEntry(_, NotNull(), NotNull()))
.WillRepeatedly(Return(NO_ERROR)); .WillRepeatedly(Return(NO_ERROR));
EXPECT_EQ(NO_ERROR, cdm_session_->Init(nullptr)); EXPECT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
EXPECT_EQ(kUsageEntrySupport, cdm_session_->get_usage_support_type()) EXPECT_TRUE(cdm_session_->supports_usage_info());
<< "Usage support type: " << cdm_session_->get_usage_support_type();
EXPECT_EQ(NO_ERROR, cdm_session_->UpdateUsageEntryInformation()); EXPECT_EQ(NO_ERROR, cdm_session_->UpdateUsageEntryInformation());
// Verify the UsageEntry metric is set. // Verify the UsageEntry metric is set.

View File

@@ -291,8 +291,8 @@ TEST_F(CryptoSessionMetricsTest, OpenSessionValidMetrics) {
CryptoSession::MakeCryptoSession(&crypto_metrics)); CryptoSession::MakeCryptoSession(&crypto_metrics));
session->Open(wvcdm::kLevelDefault); session->Open(wvcdm::kLevelDefault);
// Exercise a method that will touch a metric. // Exercise a method that will touch a metric.
CdmUsageSupportType usage_type; bool supports_usage_table;
ASSERT_EQ(NO_ERROR, session->GetUsageSupportType(&usage_type)); ASSERT_TRUE(session->HasUsageInfoSupport(&supports_usage_table));
drm_metrics::WvCdmMetrics::CryptoMetrics metrics_proto; drm_metrics::WvCdmMetrics::CryptoMetrics metrics_proto;
crypto_metrics.Serialize(&metrics_proto); crypto_metrics.Serialize(&metrics_proto);
@@ -309,6 +309,8 @@ TEST_F(CryptoSessionMetricsTest, OpenSessionValidMetrics) {
metrics_proto.oemcrypto_initialize_time_us(0).operation_count()); metrics_proto.oemcrypto_initialize_time_us(0).operation_count());
EXPECT_TRUE(metrics_proto.oemcrypto_initialize_time_us(0).has_mean()); EXPECT_TRUE(metrics_proto.oemcrypto_initialize_time_us(0).has_mean());
const CdmUsageSupportType usage_type =
supports_usage_table ? kUsageEntrySupport : kNonSecureUsageSupport;
EXPECT_EQ(usage_type, EXPECT_EQ(usage_type,
metrics_proto.oemcrypto_usage_table_support().int_value()); metrics_proto.oemcrypto_usage_table_support().int_value());

View File

@@ -141,7 +141,7 @@ class MockCryptoSession : public TestCryptoSession {
: TestCryptoSession(crypto_metrics) {} : TestCryptoSession(crypto_metrics) {}
MOCK_METHOD0(IsOpen, bool()); MOCK_METHOD0(IsOpen, bool());
MOCK_METHOD0(request_id, const std::string&()); MOCK_METHOD0(request_id, const std::string&());
MOCK_METHOD1(UsageInformationSupport, bool(bool*)); MOCK_METHOD1(HasUsageInfoSupport, bool(bool*));
MOCK_METHOD2(GetHdcpCapabilities, MOCK_METHOD2(GetHdcpCapabilities,
CdmResponseType(HdcpCapability*, HdcpCapability*)); CdmResponseType(HdcpCapability*, HdcpCapability*));
MOCK_METHOD1(GetSupportedCertificateTypes, bool(SupportedCertificateTypes*)); MOCK_METHOD1(GetSupportedCertificateTypes, bool(SupportedCertificateTypes*));
@@ -301,7 +301,7 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true)); EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
EXPECT_CALL(*crypto_session_, request_id()) EXPECT_CALL(*crypto_session_, request_id())
.WillOnce(ReturnRef(kCryptoRequestId)); .WillOnce(ReturnRef(kCryptoRequestId));
EXPECT_CALL(*crypto_session_, UsageInformationSupport(NotNull())) EXPECT_CALL(*crypto_session_, HasUsageInfoSupport(NotNull()))
.WillOnce( .WillOnce(
DoAll(SetArgPointee<0>(usage_information_support), Return(true))); DoAll(SetArgPointee<0>(usage_information_support), Return(true)));
EXPECT_CALL(*crypto_session_, GetHdcpCapabilities(NotNull(), NotNull())) EXPECT_CALL(*crypto_session_, GetHdcpCapabilities(NotNull(), NotNull()))
@@ -424,7 +424,7 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true)); EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
EXPECT_CALL(*crypto_session_, request_id()) EXPECT_CALL(*crypto_session_, request_id())
.WillOnce(ReturnRef(kCryptoRequestId)); .WillOnce(ReturnRef(kCryptoRequestId));
EXPECT_CALL(*crypto_session_, UsageInformationSupport(NotNull())) EXPECT_CALL(*crypto_session_, HasUsageInfoSupport(NotNull()))
.WillOnce( .WillOnce(
DoAll(SetArgPointee<0>(usage_information_support), Return(true))); DoAll(SetArgPointee<0>(usage_information_support), Return(true)));
EXPECT_CALL(*crypto_session_, GetHdcpCapabilities(NotNull(), NotNull())) EXPECT_CALL(*crypto_session_, GetHdcpCapabilities(NotNull(), NotNull()))