Merge "Only one function for reporting usage support." into sc-dev am: d4b24490f2

Original change: https://googleplex-android-review.googlesource.com/c/platform/vendor/widevine/+/14137666

Change-Id: Ifb59fc8325682c657b41c58d0a77a18860926819
This commit is contained in:
Alex Dale
2021-04-16 20:00:10 +00:00
committed by Automerger Merge Worker
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
@@ -298,8 +298,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,13 +238,12 @@ 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.
@@ -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)
@@ -225,9 +220,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();
} }
@@ -322,10 +315,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()) {
@@ -381,8 +373,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) {
@@ -421,8 +412,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);
@@ -440,8 +430,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) {
@@ -583,8 +572,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()) {
@@ -608,8 +596,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(
@@ -633,9 +620,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_);
} }
@@ -835,8 +820,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_);
@@ -850,7 +834,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;
} }
} }
@@ -883,9 +867,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;
} }
@@ -900,11 +883,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) {
@@ -999,11 +980,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(
@@ -1055,8 +1035,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();
@@ -1106,14 +1085,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()))