Source release v3.5.0

This commit is contained in:
Gene Morgan
2017-11-28 17:42:16 -08:00
parent 501c22890d
commit 31381a1311
155 changed files with 16680 additions and 3816 deletions

View File

@@ -14,7 +14,6 @@
#include "clock.h"
#include "device_files.h"
#include "file_store.h"
#include "license_protocol.pb.h"
#include "log.h"
#include "properties.h"
#include "string_conversions.h"
@@ -29,9 +28,6 @@ const size_t kUsageReportsPerRequest = 1;
namespace wvcdm {
using video_widevine::SignedMessage;
using video_widevine::LicenseError;
class UsagePropertySet : public CdmClientPropertySet {
public:
UsagePropertySet() {}
@@ -68,14 +64,27 @@ CdmEngine::CdmEngine(FileSystem* file_system, const std::string& spoid)
usage_session_(NULL),
last_usage_information_update_time_(0) {
assert(file_system);
Properties::Init();
if (!seeded_) {
Properties::Init();
srand(clock_.GetCurrentTime());
seeded_ = true;
}
life_span_.Start();
metrics_.cdm_engine_creation_time_millis_.Record(clock_.GetCurrentTime());
std::string cdm_version;
if(Properties::GetWVCdmVersion(&cdm_version)) {
metrics_.cdm_engine_cdm_version_.Record(cdm_version);
} else {
// Set error "false", the return value of GetWVCdmVersion.
metrics_.cdm_engine_cdm_version_.SetError(false);
}
}
CdmEngine::~CdmEngine() {}
CdmEngine::~CdmEngine() {
M_RECORD(&metrics_, cdm_engine_life_span_, life_span_.AsMs());
}
CdmResponseType CdmEngine::SetServiceCertificate(
const std::string& certificate) {
@@ -86,66 +95,6 @@ bool CdmEngine::HasServiceCertificate() {
return service_certificate_.has_certificate();
}
bool CdmEngine::GetServiceCertificateRequest(CdmKeyMessage* request) {
if (!request) {
LOGE("ServiceCertificate::PrepareRequest: no request parameter provided");
return false;
}
SignedMessage message;
message.set_type(SignedMessage::SERVICE_CERTIFICATE_REQUEST);
message.SerializeToString(request);
return true;
}
CdmResponseType CdmEngine::ParseServiceCertificateResponse(
const std::string& response, std::string* certificate) {
if (response.empty()) {
LOGE("CdmEngine::ParseServiceCertificateResponse: empty response");
return EMPTY_RESPONSE_ERROR_1;
}
if (!certificate) {
LOGE("CdmEngine::ParseServiceCertificateResponse: null return parameter");
return INVALID_PARAMETERS_ENG_19;
}
SignedMessage signed_response;
if (!signed_response.ParseFromString(response)) {
LOGE(
"CdmEngine::ParseServiceCertificateResponse: cannot parse response");
return PARSE_RESPONSE_ERROR_1;
}
if (signed_response.type() == SignedMessage::SERVICE_CERTIFICATE) {
CdmResponseType status;
status = service_certificate_.Init(signed_response.msg());
if (status != NO_ERROR) {
LOGE(
"CdmEngine::ParseServiceCertificateResponse: certificate handling "
"failure, status=%d", status);
return PARSE_SERVICE_CERTIFICATE_ERROR;
}
certificate->assign(signed_response.msg());
} else if (signed_response.type() == SignedMessage::ERROR_RESPONSE) {
LicenseError license_error;
if (!license_error.ParseFromString(signed_response.msg())) {
LOGE("CdmEngine::ParseServiceCertificateResponse: cannot parse "
"license error");
return PARSE_RESPONSE_ERROR_2;
}
LOGE("CdmEngine::ParseServiceCertificateResponse: server returned error:"
"error code = %d", license_error.error_code());
return PARSE_RESPONSE_ERROR_3;
} else {
LOGE(
"CdmEngine::ParseServiceCertificateResponse: response (%d) is "
"wrong type", signed_response.type());
return PARSE_RESPONSE_ERROR_4;
}
return NO_ERROR;
}
CdmResponseType CdmEngine::OpenSession(
const CdmKeySystem& key_system, CdmClientPropertySet* property_set,
const CdmSessionId& forced_session_id, WvCdmEventListener* event_listener) {
@@ -183,9 +132,10 @@ CdmResponseType CdmEngine::OpenSession(
CloseExpiredReleaseSessions();
scoped_ptr<CdmSession> new_session(new CdmSession(file_system_));
CdmResponseType sts = new_session->Init(&service_certificate_, property_set,
forced_session_id, event_listener);
scoped_ptr<CdmSession> new_session(new CdmSession(file_system_,
metrics_.AddSession()));
CdmResponseType sts = new_session->Init(property_set, forced_session_id,
event_listener);
if (sts != NO_ERROR) {
if (sts == NEED_PROVISIONING) {
cert_provisioning_requested_security_level_ =
@@ -240,7 +190,7 @@ CdmResponseType CdmEngine::OpenKeySetSession(
}
CdmResponseType CdmEngine::CloseSession(const CdmSessionId& session_id) {
LOGI("CdmEngine::CloseSession");
LOGV("CdmEngine::CloseSession: %s", session_id.c_str());
if (!session_map_.CloseSession(session_id)) {
LOGE("CdmEngine::CloseSession: session not found = %s", session_id.c_str());
return SESSION_NOT_FOUND_1;
@@ -312,8 +262,8 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
id = iter->second.first;
}
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(id, &session)) {
LOGE("CdmEngine::GenerateKeyRequest: session_id not found = %s",
id.c_str());
return SESSION_NOT_FOUND_2;
@@ -329,6 +279,7 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
if (license_type == kLicenseTypeRelease &&
!session->license_received()) {
sts = session->RestoreOfflineSession(key_set_id, kLicenseTypeRelease);
session->GetMetrics()->cdm_session_restore_offline_session_.Increment(sts);
if (sts != KEY_ADDED) {
LOGE("CdmEngine::GenerateKeyRequest: key release restoration failed,"
"sts = %d", static_cast<int>(sts));
@@ -385,8 +336,8 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id,
id = iter->second.first;
}
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(id, &session)) {
LOGE("CdmEngine::AddKey: session id not found = %s", id.c_str());
return SESSION_NOT_FOUND_3;
}
@@ -398,7 +349,12 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id,
CdmResponseType sts = session->AddKey(key_data);
if (key_set_id) {
*key_set_id = session->key_set_id();
if ((session->is_offline() ||
session->has_provider_session_token()) && !license_type_release) {
*key_set_id = session->key_set_id();
} else {
key_set_id->clear();
}
}
switch (sts) {
@@ -424,15 +380,16 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id,
return EMPTY_KEYSET_ID_ENG_4;
}
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::RestoreKey: session_id not found = %s ",
session_id.c_str());
return SESSION_NOT_FOUND_4;
}
CdmResponseType sts =
session->RestoreOfflineSession(key_set_id, kLicenseTypeOffline);
CdmResponseType sts;
sts = session->RestoreOfflineSession(key_set_id, kLicenseTypeOffline);
session->GetMetrics()->cdm_session_restore_offline_session_.Increment(sts);
if (sts == NEED_PROVISIONING) {
cert_provisioning_requested_security_level_ =
session->GetRequestedSecurityLevel();
@@ -446,14 +403,15 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id,
CdmResponseType CdmEngine::RemoveKeys(const CdmSessionId& session_id) {
LOGI("CdmEngine::RemoveKeys");
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::RemoveKeys: session_id not found = %s",
session_id.c_str());
return SESSION_NOT_FOUND_5;
}
session->ReleaseCrypto();
return NO_ERROR;
}
@@ -461,8 +419,8 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
const CdmSessionId& session_id, CdmKeyRequest* key_request) {
LOGI("CdmEngine::GenerateRenewalRequest");
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenerateRenewalRequest: session_id not found = %s",
session_id.c_str());
return SESSION_NOT_FOUND_6;
@@ -490,8 +448,8 @@ CdmResponseType CdmEngine::RenewKey(const CdmSessionId& session_id,
const CdmKeyResponse& key_data) {
LOGI("CdmEngine::RenewKey");
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::RenewKey: session_id not found = %s", session_id.c_str());
return SESSION_NOT_FOUND_7;
}
@@ -501,7 +459,14 @@ CdmResponseType CdmEngine::RenewKey(const CdmSessionId& session_id,
return EMPTY_KEY_DATA_2;
}
CdmResponseType sts = session->RenewKey(key_data);
CdmResponseType sts;
M_TIME(
sts = session->RenewKey(
key_data),
session->GetMetrics(),
cdm_session_renew_key_,
sts);
if (KEY_ADDED != sts) {
LOGE("CdmEngine::RenewKey: keys not added, sts=%d", static_cast<int>(sts));
return sts;
@@ -514,9 +479,16 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
const std::string& query_token,
std::string* query_response) {
LOGI("CdmEngine::QueryStatus");
CryptoSession crypto_session;
CryptoSession crypto_session(metrics_.GetCryptoMetrics());
if (security_level == kLevel3) {
CdmResponseType status = crypto_session.Open(kLevel3);
CdmResponseType status;
M_TIME(
status = crypto_session.Open(
kLevel3),
metrics_.GetCryptoMetrics(),
crypto_session_open_,
status,
kLevel3);
if (NO_ERROR != status) return INVALID_QUERY_STATUS;
}
@@ -526,8 +498,9 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
}
if (query_token == QUERY_KEY_SECURITY_LEVEL) {
CdmSecurityLevel level = crypto_session.GetSecurityLevel();
switch (level) {
CdmSecurityLevel found_security_level =
crypto_session.GetSecurityLevel();
switch (found_security_level) {
case kSecurityLevelL1:
*query_response = QUERY_VALUE_SECURITY_LEVEL_L1;
break;
@@ -542,12 +515,16 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
*query_response = QUERY_VALUE_SECURITY_LEVEL_UNKNOWN;
break;
default:
LOGW("CdmEngine::QueryStatus: Unknown security level: %d", level);
LOGW("CdmEngine::QueryStatus: Unknown security level: %d",
found_security_level);
return UNKNOWN_ERROR;
}
} else if (query_token == QUERY_KEY_DEVICE_ID) {
std::string deviceId;
if (!crypto_session.GetDeviceUniqueId(&deviceId)) {
bool got_id = crypto_session.GetExternalDeviceUniqueId(&deviceId);
metrics_.GetCryptoMetrics()->crypto_session_get_device_unique_id_
.Increment(got_id);
if (!got_id) {
LOGW("CdmEngine::QueryStatus: QUERY_KEY_DEVICE_ID unknown failure");
return UNKNOWN_ERROR;
}
@@ -555,7 +532,8 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
*query_response = deviceId;
} else if (query_token == QUERY_KEY_SYSTEM_ID) {
uint32_t system_id;
if (!crypto_session.GetSystemId(&system_id)) {
bool got_id = crypto_session.GetSystemId(&system_id);
if (!got_id) {
LOGW("CdmEngine::QueryStatus: QUERY_KEY_SYSTEM_ID unknown failure");
return UNKNOWN_ERROR;
}
@@ -584,10 +562,17 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
current_hdcp : max_hdcp);
} else if (query_token == QUERY_KEY_USAGE_SUPPORT) {
bool supports_usage_reporting;
if (!crypto_session.UsageInformationSupport(&supports_usage_reporting)) {
bool got_info = crypto_session.UsageInformationSupport(
&supports_usage_reporting);
if (!got_info) {
LOGW("CdmEngine::QueryStatus: UsageInformationSupport failed");
metrics_.GetCryptoMetrics()->crypto_session_usage_information_support_
.SetError(got_info);
return UNKNOWN_ERROR;
}
metrics_.GetCryptoMetrics()->crypto_session_usage_information_support_
.Record(supports_usage_reporting);
*query_response =
supports_usage_reporting ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
@@ -613,7 +598,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
*query_response = max_sessions_stream.str();
} else if (query_token == QUERY_KEY_OEMCRYPTO_API_VERSION) {
uint32_t api_version;
if (!crypto_session.GetApiVersion(&api_version)) {
if (crypto_session.GetApiVersion(&api_version)) {
LOGW("CdmEngine::QueryStatus: GetApiVersion failed");
return UNKNOWN_ERROR;
}
@@ -621,6 +606,28 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
std::ostringstream api_version_stream;
api_version_stream << api_version;
*query_response = api_version_stream.str();
} else if (query_token == QUERY_KEY_CURRENT_SRM_VERSION) {
uint16_t current_srm_version;
if (!crypto_session.GetSrmVersion(&current_srm_version)) {
LOGW("CdmEngine::QueryStatus: GetCurrentSRMVersion failed");
return UNKNOWN_ERROR;
}
std::ostringstream current_srm_version_stream;
current_srm_version_stream << current_srm_version;
*query_response = current_srm_version_stream.str();
} else if (query_token == QUERY_KEY_SRM_UPDATE_SUPPORT) {
bool is_srm_update_supported = crypto_session.IsSrmUpdateSupported();
*query_response =
is_srm_update_supported ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
} else if (query_token == QUERY_KEY_WVCDM_VERSION) {
std::string cdm_version;
if (!Properties::GetWVCdmVersion(&cdm_version)) {
LOGW("CdmEngine::QueryStatus: GetWVCdmVersion failed");
return UNKNOWN_ERROR;
}
*query_response = cdm_version;
} else {
LOGW("CdmEngine::QueryStatus: Unknown status requested, token = %s",
query_token.c_str());
@@ -633,8 +640,8 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
CdmResponseType CdmEngine::QuerySessionStatus(const CdmSessionId& session_id,
CdmQueryMap* query_response) {
LOGI("CdmEngine::QuerySessionStatus");
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::QuerySessionStatus: session_id not found = %s",
session_id.c_str());
return SESSION_NOT_FOUND_8;
@@ -644,8 +651,8 @@ CdmResponseType CdmEngine::QuerySessionStatus(const CdmSessionId& session_id,
bool CdmEngine::IsReleaseSession(const CdmSessionId& session_id) {
LOGI("CdmEngine::IsReleaseSession");
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::IsReleaseSession: session_id not found = %s",
session_id.c_str());
return false;
@@ -655,8 +662,8 @@ bool CdmEngine::IsReleaseSession(const CdmSessionId& session_id) {
bool CdmEngine::IsOfflineSession(const CdmSessionId& session_id) {
LOGI("CdmEngine::IsOfflineSession");
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::IsOfflineSession: session_id not found = %s",
session_id.c_str());
return false;
@@ -667,8 +674,8 @@ bool CdmEngine::IsOfflineSession(const CdmSessionId& session_id) {
CdmResponseType CdmEngine::QueryKeyStatus(const CdmSessionId& session_id,
CdmQueryMap* query_response) {
LOGI("CdmEngine::QueryKeyStatus");
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::QueryKeyStatus: session_id not found = %s",
session_id.c_str());
return SESSION_NOT_FOUND_9;
@@ -684,8 +691,8 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const CdmSessionId& session_id,
LOGE("CdmEngine::QueryKeyAllowedUsage: no response destination");
return INVALID_PARAMETERS_ENG_12;
}
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::QueryKeyAllowedUsage: session_id not found = %s",
session_id.c_str());
return SESSION_NOT_FOUND_12;
@@ -710,9 +717,6 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
for (CdmSessionList::iterator iter = sessions.begin();
iter != sessions.end(); ++iter) {
if ((*iter)->IsClosed()) {
continue;
}
session_sts = (*iter)->QueryKeyAllowedUsage(key_id, &found_in_this_session);
if (session_sts == NO_ERROR) {
if (found) {
@@ -738,8 +742,8 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
CdmResponseType CdmEngine::QueryOemCryptoSessionId(
const CdmSessionId& session_id, CdmQueryMap* query_response) {
LOGI("CdmEngine::QueryOemCryptoSessionId");
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::QueryOemCryptoSessionId: session_id not found = %s",
session_id.c_str());
return SESSION_NOT_FOUND_10;
@@ -770,7 +774,8 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
if (NULL == cert_provisioning_.get()) {
cert_provisioning_.reset(
new CertificateProvisioning(&service_certificate_));
new CertificateProvisioning(metrics_.GetCryptoMetrics(),
&service_certificate_));
}
CdmResponseType ret = cert_provisioning_->GetProvisioningRequest(
cert_provisioning_requested_security_level_, cert_type, cert_authority,
@@ -812,9 +817,15 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
if (NULL == cert_provisioning_.get()) {
// Certificate provisioning object has been released. Check if a concurrent
// provisioning attempt has succeeded before declaring failure.
CryptoSession crypto_session;
CdmResponseType status =
crypto_session.Open(cert_provisioning_requested_security_level_);
CryptoSession crypto_session(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) {
LOGE(
"CdmEngine::HandleProvisioningResponse: provisioning object "
@@ -873,17 +884,27 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
}
CdmResponseType CdmEngine::DeleteUsageTable(CdmSecurityLevel security_level) {
scoped_ptr<CryptoSession> crypto_session(new CryptoSession());
CdmResponseType status = crypto_session->Open(
CryptoSession crypto_session(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("CdmEngine::DeleteUsageTable: error opening crypto session: %d",
status);
status);
return UNPROVISION_ERROR_4;
}
status = crypto_session->DeleteAllUsageReports();
status = crypto_session.DeleteAllUsageReports();
metrics_.GetCryptoMetrics()->crypto_session_delete_all_usage_reports_
.Increment(status);
if (status != NO_ERROR) {
LOGE("CdmEngine::DeleteUsageTable: error deleting usage reports: %d",
LOGE("CdmEngine::DeleteUsageTable: error deleteing usage reports: %d",
status);
}
return status;
@@ -894,7 +915,7 @@ CdmResponseType CdmEngine::ListStoredLicenses(
DeviceFiles handle(file_system_);
if (!key_set_ids) {
LOGE("CdmEngine::ListStoredLicenses: no response destination");
return INVALID_PARAMETERS_ENG_17;
return INVALID_PARAMETERS_ENG_22;
}
if (!handle.Init(security_level)) {
LOGE("CdmEngine::ListStoredLicenses: unable to initialize device files");
@@ -913,7 +934,7 @@ CdmResponseType CdmEngine::ListUsageRecords(const std::string& app_id,
DeviceFiles handle(file_system_);
if (!ksids) {
LOGE("CdmEngine::ListUsageRecords: no response destination");
return INVALID_PARAMETERS_ENG_18;
return INVALID_PARAMETERS_ENG_23;
}
if (!handle.Init(security_level)) {
LOGE("CdmEngine::ListUsageRecords: unable to initialize device files");
@@ -936,13 +957,15 @@ CdmResponseType CdmEngine::DeleteUsageRecord(const std::string& app_id,
LOGE("CdmEngine::DeleteUsageRecord: unable to initialize device files");
return DELETE_USAGE_ERROR_1;
}
if (!handle.GetProviderToken(app_id, key_set_id, &provider_session_token)) {
LOGE("CdmEngine::DeleteUsageRecord: GetProviderToken failed");
if (!handle.GetProviderSessionToken(app_id, key_set_id,
&provider_session_token)) {
LOGE("CdmEngine::DeleteUsageRecord: GetProviderSessionToken failed");
return DELETE_USAGE_ERROR_2;
}
// Got provider token. Remove from OEMCrypto.
scoped_ptr<CryptoSession> crypto_session(new CryptoSession());
scoped_ptr<CryptoSession> crypto_session(
new CryptoSession(metrics_.GetCryptoMetrics()));
CdmResponseType status = crypto_session->Open(
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
if (status == NO_ERROR) {
@@ -972,10 +995,10 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
}
usage_property_set_->set_security_level(kLevelDefault);
usage_property_set_->set_app_id(app_id);
usage_session_.reset(new CdmSession(file_system_));
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
CdmResponseType status = usage_session_->Init(usage_property_set_.get());
if (NO_ERROR != status) {
LOGE("CdmEngine::GetUsageInfo: session init error");
LOGE("CdmEngine::GetUsageInfo: session init error: %d", status);
return status;
}
DeviceFiles handle(file_system_);
@@ -986,11 +1009,13 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
CdmKeyMessage license_request;
CdmKeyResponse license_response;
if (!handle.RetrieveUsageInfo(app_id, ssid, &license_request,
&license_response)) {
std::string usage_entry;
DeviceFiles::CdmUsageData usage_data;
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
ssid, &usage_data)) {
usage_property_set_->set_security_level(kLevel3);
usage_property_set_->set_app_id(app_id);
usage_session_.reset(new CdmSession(file_system_));
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
status = usage_session_->Init(usage_property_set_.get());
if (NO_ERROR != status) {
LOGE("CdmEngine::GetUsageInfo: session init error");
@@ -1000,15 +1025,15 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
LOGE("CdmEngine::GetUsageInfo: device file init error");
return GET_USAGE_INFO_ERROR_2;
}
if (!handle.RetrieveUsageInfo(app_id, ssid, &license_request,
&license_response)) {
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
ssid, &usage_data)) {
// No entry found for that ssid.
return USAGE_INFO_NOT_FOUND;
}
}
status =
usage_session_->RestoreUsageSession(license_request,license_response);
usage_session_->RestoreUsageSession(usage_data);
if (KEY_ADDED != status) {
LOGE("CdmEngine::GetUsageInfo: restore usage session error %d", status);
@@ -1067,7 +1092,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
usage_property_set_->set_security_level(requested_security_level);
usage_property_set_->set_app_id(app_id);
usage_session_.reset(new CdmSession(file_system_));
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
CdmResponseType status = usage_session_->Init(usage_property_set_.get());
if (NO_ERROR != status) {
@@ -1081,8 +1106,9 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
return GET_USAGE_INFO_ERROR_3;
}
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> > license_info;
if (!handle.RetrieveUsageInfo(app_id, &license_info)) {
std::vector<DeviceFiles::CdmUsageData> usage_data;
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
&usage_data)) {
LOGE("CdmEngine::GetUsageInfo: unable to read usage information");
return GET_USAGE_INFO_ERROR_4;
}
@@ -1091,16 +1117,15 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
LOGE("CdmEngine::GetUsageInfo: no usage info destination");
return INVALID_PARAMETERS_ENG_10;
}
if (0 == license_info.size()) {
if (0 == usage_data.size()) {
usage_info->resize(0);
return NO_ERROR;
}
usage_info->resize(kUsageReportsPerRequest);
uint32_t index = rand() % license_info.size();
status = usage_session_->RestoreUsageSession(license_info[index].first,
license_info[index].second);
uint32_t index = rand() % usage_data.size();
status = usage_session_->RestoreUsageSession(usage_data[index]);
if (KEY_ADDED != status) {
LOGE("CdmEngine::GetUsageInfo: restore usage session (%d) error %ld", index,
status);
@@ -1135,12 +1160,12 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(
DeviceFiles handle(file_system_);
if (!handle.Init(security_level)) {
LOGE("CdmEngine::ReleaseAllUsageInfo: unable to initialize device files");
return RELEASE_ALL_USAGE_INFO_ERROR_3;
return RELEASE_ALL_USAGE_INFO_ERROR_6;
}
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(app_id, &provider_session_tokens)) {
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete usage records");
return RELEASE_ALL_USAGE_INFO_ERROR_4;
return RELEASE_ALL_USAGE_INFO_ERROR_7;
}
if (provider_session_tokens.size() == 0UL) {
@@ -1148,7 +1173,8 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(
}
// Got at least one provider token. Remove from OEMCrypto.
scoped_ptr<CryptoSession> crypto_session(new CryptoSession());
scoped_ptr<CryptoSession> crypto_session(
new CryptoSession(metrics_.GetCryptoMetrics()));
CdmResponseType status = crypto_session->Open(
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
if (status == NO_ERROR) {
@@ -1156,7 +1182,7 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(
DeleteMultipleUsageInformation(provider_session_tokens);
}
if (status != NO_ERROR) {
LOGE("CdmEngine::DeleteUsageRecord: CryptoSession failure");
LOGE("CdmEngine::ReleaseAllUsageInfo: CryptoSession failure");
}
return status;
}
@@ -1171,24 +1197,69 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
for (int j = kSecurityLevelL1; j < kSecurityLevelUnknown; ++j) {
DeviceFiles handle(file_system_);
if (handle.Init(static_cast<CdmSecurityLevel>(j))) {
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(app_id, &provider_session_tokens)) {
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete L%d secure"
"stops", j);
status = RELEASE_ALL_USAGE_INFO_ERROR_1;
} else {
SecurityLevel security_level =
static_cast<CdmSecurityLevel>(j) == kSecurityLevelL3
? kLevel3
: kLevelDefault;
usage_property_set_->set_security_level(security_level);
usage_session_.reset(new CdmSession(file_system_));
usage_session_->Init(usage_property_set_.get());
CdmResponseType status2 = usage_session_->
DeleteMultipleUsageInformation(provider_session_tokens);
if (status2 != NO_ERROR) {
status = status2;
SecurityLevel security_level =
static_cast<CdmSecurityLevel>(j) == kSecurityLevelL3
? kLevel3
: kLevelDefault;
usage_property_set_->set_security_level(security_level);
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)) {
status = RELEASE_ALL_USAGE_INFO_ERROR_4;
break;
}
if (usage_data.empty()) break;
status = usage_session_->DeleteUsageEntry(
usage_data[0].usage_entry_number);
if (status != NO_ERROR) break;
if (!handle.DeleteUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id),
usage_data[0].provider_session_token)) {
status = RELEASE_ALL_USAGE_INFO_ERROR_6;
break;
}
} while (status == NO_ERROR && !usage_data.empty());
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(app_id),
&provider_session_tokens)) {
status = RELEASE_ALL_USAGE_INFO_ERROR_5;
}
break;
}
case kUsageTableSupport: {
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(app_id),
&provider_session_tokens)) {
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete %d secure"
"stops", j);
status = RELEASE_ALL_USAGE_INFO_ERROR_1;
} else {
CdmResponseType status2 = usage_session_->
DeleteMultipleUsageInformation(provider_session_tokens);
if (status2 != NO_ERROR) status = status2;
}
break;
}
default:
// Ignore
break;
}
} else {
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to initialize L%d device"
@@ -1227,8 +1298,8 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
return EMPTY_KEYSET_ID_ENG_5;
}
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(key_set_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(key_set_id, &session)) {
LOGE("CdmEngine::LoadUsageSession: session_id not found = %s ",
key_set_id.c_str());
return SESSION_NOT_FOUND_11;
@@ -1248,16 +1319,19 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
std::string app_id;
session->GetApplicationId(&app_id);
CdmKeyMessage key_message;
CdmKeyResponse key_response;
if (!handle.RetrieveUsageInfoByKeySetId(app_id, key_set_id, &key_message,
&key_response)) {
DeviceFiles::CdmUsageData usage_data;
if (!handle.RetrieveUsageInfoByKeySetId(
DeviceFiles::GetUsageInfoFileName(app_id), key_set_id,
&(usage_data.provider_session_token),
&(usage_data.license_request),
&(usage_data.license), &(usage_data.usage_entry),
&(usage_data.usage_entry_number))) {
LOGE("CdmEngine::LoadUsageSession: unable to find usage information");
return LOAD_USAGE_INFO_MISSING;
}
CdmResponseType status = session->RestoreUsageSession(key_message,
key_response);
CdmResponseType status = session->RestoreUsageSession(usage_data);
session->GetMetrics()->cdm_session_restore_usage_session_.Increment(status);
if (KEY_ADDED != status) {
LOGE("CdmEngine::LoadUsageSession: usage session error %ld", status);
return status;
@@ -1265,13 +1339,15 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
CdmKeyRequest request;
status = session->GenerateReleaseRequest(&request);
*release_message = request.message;
switch (status) {
case KEY_MESSAGE:
break;
case KEY_CANCELED: // usage information not present in
session->DeleteLicense(); // OEMCrypto, delete and try again
case KEY_CANCELED:
// usage information not present in OEMCrypto, delete and try again
session->DeleteLicense();
break;
default:
LOGE("CdmEngine::LoadUsageSession: generate release request error: %d",
@@ -1307,7 +1383,7 @@ CdmResponseType CdmEngine::Decrypt(const CdmSessionId& session_id,
// else we must be level 1 direct and we don't need to return a buffer.
}
std::shared_ptr<CdmSession> session;
shared_ptr<CdmSession> session;
if (session_id.empty()) {
CdmSessionList sessions;
session_map_.GetSessionList(sessions);
@@ -1317,9 +1393,6 @@ CdmResponseType CdmEngine::Decrypt(const CdmSessionId& session_id,
int64_t seconds_remaining = 0;
for (CdmSessionList::iterator iter = sessions.begin();
iter != sessions.end(); ++iter) {
if ((*iter)->IsClosed()) {
continue;
}
if ((*iter)->IsKeyLoaded(*parameters.key_id)) {
int64_t duration = (*iter)->GetDurationRemaining();
if (duration > seconds_remaining) {
@@ -1328,18 +1401,16 @@ CdmResponseType CdmEngine::Decrypt(const CdmSessionId& session_id,
}
}
}
} else {
session_map_.FindSession(session_id, session);
}
if (session.get() == NULL) {
if (session_id.empty()) {
if (session.get() == NULL) {
LOGE("CdmEngine::Decrypt: session not found: Empty session ID");
} else {
return SESSION_NOT_FOUND_FOR_DECRYPT;
}
} else {
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::Decrypt: session not found: id=%s, id size=%d",
session_id.c_str(), session_id.size());
return SESSION_NOT_FOUND_FOR_DECRYPT;
}
return SESSION_NOT_FOUND_FOR_DECRYPT;
}
return session->Decrypt(parameters);
@@ -1349,8 +1420,8 @@ CdmResponseType CdmEngine::GenericEncrypt(
const std::string& session_id, const std::string& in_buffer,
const std::string& key_id, const std::string& iv,
CdmEncryptionAlgorithm algorithm, std::string* out_buffer) {
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenericEncrypt: session_id not found = %s ",
session_id.c_str());
return SESSION_NOT_FOUND_13;
@@ -1363,8 +1434,8 @@ CdmResponseType CdmEngine::GenericDecrypt(
const std::string& key_id, const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer) {
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenericDecrypt: session_id not found = %s ",
session_id.c_str());
return SESSION_NOT_FOUND_14;
@@ -1376,8 +1447,8 @@ CdmResponseType CdmEngine::GenericSign(
const std::string& session_id, const std::string& message,
const std::string& key_id, CdmSigningAlgorithm algorithm,
std::string* signature) {
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenericSign: session_id not found = %s ",
session_id.c_str());
return SESSION_NOT_FOUND_15;
@@ -1389,8 +1460,8 @@ CdmResponseType CdmEngine::GenericVerify(
const std::string& session_id, const std::string& message,
const std::string& key_id, CdmSigningAlgorithm algorithm,
const std::string& signature) {
std::shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenericVerify: session_id not found = %s ",
session_id.c_str());
return SESSION_NOT_FOUND_16;
@@ -1404,9 +1475,6 @@ bool CdmEngine::IsKeyLoaded(const KeyId& key_id) {
session_map_.GetSessionList(sessions);
for (CdmSessionList::iterator iter = sessions.begin();
iter != sessions.end(); ++iter) {
if ((*iter)->IsClosed()) {
continue;
}
if ((*iter)->IsKeyLoaded(key_id)) {
return true;
}
@@ -1431,9 +1499,6 @@ bool CdmEngine::FindSessionForKey(const KeyId& key_id,
int64_t seconds_remaining = 0;
for (CdmSessionList::iterator iter = sessions.begin();
iter != sessions.end(); ++iter) {
if ((*iter)->IsClosed()) {
continue;
}
CdmSessionId id = (*iter)->session_id();
if (Properties::GetSessionSharingId(id) == session_sharing_id) {
if ((*iter)->IsKeyLoaded(key_id)) {
@@ -1455,8 +1520,8 @@ bool CdmEngine::FindSessionForKey(const KeyId& key_id,
bool CdmEngine::NotifyResolution(const CdmSessionId& session_id, uint32_t width,
uint32_t height) {
std::shared_ptr<CdmSession> session;
if (session_map_.FindSession(session_id, session)) {
shared_ptr<CdmSession> session;
if (session_map_.FindSession(session_id, &session)) {
session->NotifyResolution(width, height);
return true;
}
@@ -1490,9 +1555,7 @@ void CdmEngine::OnTimerEvent() {
is_usage_update_needed =
is_usage_update_needed || sessions.front()->is_usage_update_needed();
if (!sessions.front()->IsClosed()) {
sessions.front()->OnTimerEvent(usage_update_period_expired);
}
sessions.front()->OnTimerEvent(usage_update_period_expired);
sessions.pop_front();
}
@@ -1505,19 +1568,26 @@ void CdmEngine::OnTimerEvent() {
for (CdmSessionList::iterator iter = sessions.begin();
iter != sessions.end(); ++iter) {
if ((*iter)->IsClosed()) {
continue;
}
(*iter)->reset_usage_flags();
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)->UpdateUsageInformation();
if (NO_ERROR != status) {
LOGW("Update usage information failed: %d", status);
} else {
has_usage_been_updated = true;
}
switch ((*iter)->get_usage_support_type()) {
case kUsageEntrySupport:
(*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("Update usage information failed: %d", status);
} else {
has_usage_been_updated = true;
}
}
break;
default:
// Ignore
break;
}
}
}
@@ -1529,9 +1599,7 @@ void CdmEngine::OnKeyReleaseEvent(const CdmKeySetId& key_set_id) {
session_map_.GetSessionList(sessions);
while (!sessions.empty()) {
if (!sessions.front()->IsClosed()) {
sessions.front()->OnKeyReleaseEvent(key_set_id);
}
sessions.front()->OnKeyReleaseEvent(key_set_id);
sessions.pop_front();
}
}
@@ -1588,11 +1656,20 @@ void CdmEngine::DeleteAllUsageReportsUponFactoryReset() {
if (!file_system_->Exists(device_base_path_level1) &&
!file_system_->Exists(device_base_path_level3)) {
scoped_ptr<CryptoSession> crypto_session(new CryptoSession());
CdmResponseType status = crypto_session->Open(
scoped_ptr<CryptoSession> crypto_session(
new CryptoSession(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(
"CdmEngine::DeleteAllUsageReportsUponFactoryReset: "