OEMCrypto v16.1
Merge of http://go/wvgerrit/93404 This CL updates the Widevine CDM to support OEMCrypto v16.1 Test: Tested in 16.2 CL Bug: 141247171 Change-Id: I69bd993500f6fb63bf6010c8b0250dc7acc3d71b
This commit is contained in:
@@ -27,7 +27,6 @@
|
||||
namespace {
|
||||
const uint64_t kReleaseSessionTimeToLive = 60; // seconds
|
||||
const uint32_t kUpdateUsageInformationPeriod = 60; // seconds
|
||||
const size_t kUsageReportsPerRequest = 1;
|
||||
|
||||
wvcdm::CdmOfflineLicenseState MapDeviceFilesLicenseState(
|
||||
wvcdm::DeviceFiles::LicenseState state) {
|
||||
@@ -571,7 +570,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
return NO_ERROR;
|
||||
} else if (query_token == QUERY_KEY_USAGE_SUPPORT) {
|
||||
bool supports_usage_reporting;
|
||||
bool got_info = crypto_session->UsageInformationSupport(
|
||||
const bool got_info = crypto_session->UsageInformationSupport(
|
||||
security_level, &supports_usage_reporting);
|
||||
|
||||
if (!got_info) {
|
||||
@@ -698,6 +697,24 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
break;
|
||||
}
|
||||
return NO_ERROR;
|
||||
} else if (query_token == QUERY_KEY_MAX_USAGE_TABLE_ENTRIES) {
|
||||
size_t max_number_of_usage_entries;
|
||||
if (!crypto_session->GetMaximumUsageTableEntries(
|
||||
security_level, &max_number_of_usage_entries)) {
|
||||
LOGW("GetMaxUsageTableEntries failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
*query_response = std::to_string(max_number_of_usage_entries);
|
||||
} else if (query_token == QUERY_KEY_OEMCRYPTO_API_MINOR_VERSION) {
|
||||
uint32_t api_minor_version;
|
||||
if (!crypto_session->GetApiMinorVersion(security_level,
|
||||
&api_minor_version)) {
|
||||
LOGW("GetApiMinorVersion failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
*query_response = std::to_string(api_minor_version);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
M_TIME(status = crypto_session->Open(security_level),
|
||||
@@ -804,9 +821,6 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
|
||||
CdmKeyAllowedUsage* key_usage) {
|
||||
LOGI("Querying allowed key useage (all sessions): key_id = %s",
|
||||
key_id.c_str());
|
||||
CdmResponseType sts;
|
||||
CdmKeyAllowedUsage found_in_this_session;
|
||||
bool found = false;
|
||||
if (!key_usage) {
|
||||
LOGE("No response destination");
|
||||
return PARAMETER_NULL;
|
||||
@@ -816,9 +830,12 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
|
||||
CdmSessionList sessions;
|
||||
session_map_.GetSessionList(sessions);
|
||||
|
||||
bool found = false;
|
||||
for (CdmSessionList::iterator iter = sessions.begin(); iter != sessions.end();
|
||||
++iter) {
|
||||
sts = (*iter)->QueryKeyAllowedUsage(key_id, &found_in_this_session);
|
||||
CdmKeyAllowedUsage found_in_this_session;
|
||||
CdmResponseType sts =
|
||||
(*iter)->QueryKeyAllowedUsage(key_id, &found_in_this_session);
|
||||
if (sts == NO_ERROR) {
|
||||
if (found) {
|
||||
// Found another key. If usage settings do not match, fail.
|
||||
@@ -890,8 +907,7 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
return INVALID_PROVISIONING_REQUEST_PARAM_2;
|
||||
}
|
||||
|
||||
DeleteAllUsageReportsUponFactoryReset();
|
||||
|
||||
// TODO(b/141705730): Remove usage entries on provisioning.
|
||||
if (!cert_provisioning_) {
|
||||
cert_provisioning_.reset(
|
||||
new CertificateProvisioning(metrics_->GetCryptoMetrics()));
|
||||
@@ -1004,6 +1020,8 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
|
||||
return UNPROVISION_ERROR_1;
|
||||
}
|
||||
|
||||
// TODO(b/141705730): Remove usage entries during unprovisioning.
|
||||
|
||||
if (!file_system_->IsGlobal()) {
|
||||
if (!handle.RemoveCertificate()) {
|
||||
LOGE("Unable to delete certificate");
|
||||
@@ -1015,34 +1033,10 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
|
||||
LOGE("Unable to delete files");
|
||||
return UNPROVISION_ERROR_3;
|
||||
}
|
||||
return DeleteUsageTable(security_level);
|
||||
return NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::DeleteUsageTable(CdmSecurityLevel security_level) {
|
||||
LOGI("Deleting usage table: security_level = %d",
|
||||
static_cast<int>(security_level));
|
||||
std::unique_ptr<CryptoSession> crypto_session(
|
||||
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
|
||||
CdmResponseType status;
|
||||
M_TIME(status = crypto_session->Open(
|
||||
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault),
|
||||
metrics_->GetCryptoMetrics(), crypto_session_open_, status,
|
||||
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("Error opening crypto session: status = %d", static_cast<int>(status));
|
||||
return UNPROVISION_ERROR_4;
|
||||
}
|
||||
status = crypto_session->DeleteAllUsageReports();
|
||||
metrics_->GetCryptoMetrics()
|
||||
->crypto_session_delete_all_usage_reports_.Increment(status);
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("Error deleteing usage reports: status = %d",
|
||||
static_cast<int>(status));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ListStoredLicenses(
|
||||
CdmSecurityLevel security_level, std::vector<std::string>* key_set_ids) {
|
||||
DeviceFiles handle(file_system_);
|
||||
@@ -1195,9 +1189,6 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
return GET_USAGE_INFO_ERROR_1;
|
||||
}
|
||||
|
||||
CdmKeyMessage license_request;
|
||||
CdmKeyResponse license_response;
|
||||
std::string usage_entry;
|
||||
DeviceFiles::CdmUsageData usage_data;
|
||||
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id), ssid,
|
||||
&usage_data)) {
|
||||
@@ -1206,7 +1197,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
usage_session_.reset(new CdmSession(file_system_, metrics_->AddSession()));
|
||||
status = usage_session_->Init(usage_property_set_.get());
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("Session init error");
|
||||
LOGE("Session init error: status = %d", static_cast<int>(status));
|
||||
return status;
|
||||
}
|
||||
if (!handle.Reset(usage_session_->GetSecurityLevel())) {
|
||||
@@ -1280,6 +1271,11 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
CdmUsageInfo* usage_info) {
|
||||
LOGI("Getting usage info: app_id = %s, security_level = %d", app_id.c_str(),
|
||||
static_cast<int>(requested_security_level));
|
||||
if (!usage_info) {
|
||||
LOGE("No usage info destination");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
if (!usage_property_set_) {
|
||||
usage_property_set_.reset(new UsagePropertySet());
|
||||
}
|
||||
@@ -1307,20 +1303,15 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
return GET_USAGE_INFO_ERROR_4;
|
||||
}
|
||||
|
||||
if (!usage_info) {
|
||||
LOGE("No usage info destination");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
if (0 == usage_data.size()) {
|
||||
usage_info->resize(0);
|
||||
if (usage_data.empty()) {
|
||||
usage_info->clear();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
usage_info->resize(kUsageReportsPerRequest);
|
||||
|
||||
size_t index = CdmRandom::RandomInRange(usage_data.size() - 1);
|
||||
const size_t index = CdmRandom::RandomInRange(usage_data.size() - 1);
|
||||
status = usage_session_->RestoreUsageSession(usage_data[index], error_detail);
|
||||
if (KEY_ADDED != status) {
|
||||
// TODO(b/141704872): Make multiple attempts.
|
||||
LOGE("RestoreUsageSession failed: index = %zu, status = %d", index,
|
||||
static_cast<int>(status));
|
||||
usage_info->clear();
|
||||
@@ -1367,64 +1358,42 @@ CdmResponseType CdmEngine::RemoveAllUsageInfo(
|
||||
usage_session_.reset(new CdmSession(file_system_, metrics_->AddSession()));
|
||||
usage_session_->Init(usage_property_set_.get());
|
||||
|
||||
switch (usage_session_->get_usage_support_type()) {
|
||||
case kUsageEntrySupport: {
|
||||
std::vector<DeviceFiles::CdmUsageData> usage_data;
|
||||
// Retrieve all usage information but delete only one before
|
||||
// refetching. This is because deleting the usage entry
|
||||
// might cause other entries to be shifted and information updated.
|
||||
do {
|
||||
if (!handle.RetrieveUsageInfo(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id), &usage_data)) {
|
||||
LOGW("Failed to retrieve usage info");
|
||||
break;
|
||||
}
|
||||
|
||||
if (usage_data.empty()) break;
|
||||
|
||||
CdmResponseType res = usage_session_->DeleteUsageEntry(
|
||||
usage_data[0].usage_entry_number);
|
||||
|
||||
if (res != NO_ERROR) {
|
||||
LOGW("Failed to delete usage entry: status = %d",
|
||||
static_cast<int>(res));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
usage_data[0].provider_session_token)) {
|
||||
LOGW("Failed to delete usage info");
|
||||
break;
|
||||
}
|
||||
} while (!usage_data.empty());
|
||||
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&provider_session_tokens)) {
|
||||
status = REMOVE_ALL_USAGE_INFO_ERROR_5;
|
||||
if (usage_session_->get_usage_support_type() == kUsageEntrySupport) {
|
||||
std::vector<DeviceFiles::CdmUsageData> usage_data;
|
||||
// Retrieve all usage information but delete only one before
|
||||
// refetching. This is because deleting the usage entry
|
||||
// might cause other entries to be shifted and information updated.
|
||||
do {
|
||||
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&usage_data)) {
|
||||
LOGW("Failed to retrieve usage info");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kUsageTableSupport: {
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&provider_session_tokens)) {
|
||||
LOGE("Failed to delete secure stops: cdm_security_level = %d",
|
||||
static_cast<int>(cdm_security_level));
|
||||
status = REMOVE_ALL_USAGE_INFO_ERROR_1;
|
||||
} else {
|
||||
CdmResponseType status2 =
|
||||
usage_session_->DeleteMultipleUsageInformation(
|
||||
provider_session_tokens);
|
||||
if (status2 != NO_ERROR) status = status2;
|
||||
|
||||
if (usage_data.empty()) break;
|
||||
|
||||
CdmResponseType res =
|
||||
usage_session_->DeleteUsageEntry(usage_data[0].usage_entry_number);
|
||||
|
||||
if (res != NO_ERROR) {
|
||||
LOGW("Failed to delete usage entry: status = %d",
|
||||
static_cast<int>(res));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
if (!handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
usage_data[0].provider_session_token)) {
|
||||
LOGW("Failed to delete usage info");
|
||||
break;
|
||||
}
|
||||
} while (!usage_data.empty());
|
||||
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&provider_session_tokens)) {
|
||||
status = REMOVE_ALL_USAGE_INFO_ERROR_5;
|
||||
}
|
||||
default:
|
||||
// Ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
usage_session_.reset();
|
||||
@@ -1479,38 +1448,14 @@ CdmResponseType CdmEngine::RemoveUsageInfo(
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (usage_session_->get_usage_support_type()) {
|
||||
case kUsageEntrySupport: {
|
||||
status = usage_session_->DeleteUsageEntry(usage_entry_number);
|
||||
|
||||
if (!handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
provider_session_token)) {
|
||||
status = REMOVE_USAGE_INFO_ERROR_1;
|
||||
}
|
||||
usage_session_.reset();
|
||||
return status;
|
||||
if (usage_session_->get_usage_support_type() == kUsageEntrySupport) {
|
||||
status = usage_session_->DeleteUsageEntry(usage_entry_number);
|
||||
if (!handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
provider_session_token)) {
|
||||
status = REMOVE_USAGE_INFO_ERROR_1;
|
||||
}
|
||||
case kUsageTableSupport: {
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
provider_session_token);
|
||||
std::unique_ptr<CryptoSession> crypto_session(
|
||||
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
|
||||
status = crypto_session->Open(static_cast<CdmSecurityLevel>(j) ==
|
||||
kSecurityLevelL3
|
||||
? kLevel3
|
||||
: kLevelDefault);
|
||||
if (status == NO_ERROR) {
|
||||
crypto_session->UpdateUsageInformation();
|
||||
status =
|
||||
crypto_session->DeleteUsageInformation(provider_session_token);
|
||||
crypto_session->UpdateUsageInformation();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
default:
|
||||
// Ignore
|
||||
break;
|
||||
usage_session_.reset();
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
LOGE("Failed to initialize L%d device files", j);
|
||||
@@ -1530,6 +1475,7 @@ CdmResponseType CdmEngine::ReleaseUsageInfo(
|
||||
}
|
||||
|
||||
CdmResponseType status = usage_session_->ReleaseKey(message);
|
||||
// Q: Should this only be reset if release key was successful?
|
||||
usage_session_.reset();
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("ReleaseKey failed: status = %d", status);
|
||||
@@ -1908,36 +1854,15 @@ void CdmEngine::OnTimerEvent() {
|
||||
|
||||
if (is_usage_update_needed &&
|
||||
(usage_update_period_expired || is_initial_usage_update)) {
|
||||
bool has_usage_been_updated = false;
|
||||
|
||||
// Session list may have changed. Rebuild.
|
||||
session_map_.GetSessionList(sessions);
|
||||
|
||||
for (CdmSessionList::iterator iter = sessions.begin();
|
||||
iter != sessions.end(); ++iter) {
|
||||
(*iter)->reset_usage_flags();
|
||||
switch ((*iter)->get_usage_support_type()) {
|
||||
case kUsageEntrySupport:
|
||||
if ((*iter)->has_provider_session_token()) {
|
||||
(*iter)->UpdateUsageEntryInformation();
|
||||
}
|
||||
break;
|
||||
case kUsageTableSupport:
|
||||
if (!has_usage_been_updated) {
|
||||
// usage is updated for all sessions so this needs to be
|
||||
// called only once per update usage information period
|
||||
CdmResponseType status = (*iter)->UpdateUsageTableInformation();
|
||||
if (NO_ERROR != status) {
|
||||
LOGW("UpdateUsageTableInformation failed: status = %d",
|
||||
static_cast<int>(status));
|
||||
} else {
|
||||
has_usage_been_updated = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Ignore
|
||||
break;
|
||||
if ((*iter)->get_usage_support_type() == kUsageEntrySupport &&
|
||||
(*iter)->has_provider_session_token()) {
|
||||
(*iter)->UpdateUsageEntryInformation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2004,38 +1929,4 @@ void CdmEngine::CloseExpiredReleaseSessions() {
|
||||
}
|
||||
}
|
||||
|
||||
void CdmEngine::DeleteAllUsageReportsUponFactoryReset() {
|
||||
std::string device_base_path_level1 = "";
|
||||
std::string device_base_path_level3 = "";
|
||||
Properties::GetDeviceFilesBasePath(kSecurityLevelL1,
|
||||
&device_base_path_level1);
|
||||
Properties::GetDeviceFilesBasePath(kSecurityLevelL3,
|
||||
&device_base_path_level3);
|
||||
|
||||
if (!file_system_->Exists(device_base_path_level1) &&
|
||||
!file_system_->Exists(device_base_path_level3)) {
|
||||
std::unique_ptr<CryptoSession> crypto_session(
|
||||
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
|
||||
CdmResponseType status;
|
||||
M_TIME(status = crypto_session->Open(
|
||||
cert_provisioning_requested_security_level_),
|
||||
metrics_->GetCryptoMetrics(), crypto_session_open_, status,
|
||||
cert_provisioning_requested_security_level_);
|
||||
if (NO_ERROR == status) {
|
||||
status = crypto_session->DeleteAllUsageReports();
|
||||
metrics_->GetCryptoMetrics()
|
||||
->crypto_session_delete_all_usage_reports_.Increment(status);
|
||||
if (NO_ERROR != status) {
|
||||
LOGW("Failed to delete usage reports: status = %d",
|
||||
static_cast<int>(status));
|
||||
}
|
||||
} else {
|
||||
LOGW(
|
||||
"Failed to open crypto session: status = %d\n"
|
||||
"Usage reports are not removed after factory reset",
|
||||
static_cast<int>(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
Reference in New Issue
Block a user