Source release v3.3.0
This commit is contained in:
@@ -3,12 +3,14 @@
|
||||
#include "cdm_engine.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <list>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "cdm_session.h"
|
||||
#include "cdm_session_map.h"
|
||||
#include "clock.h"
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
@@ -27,6 +29,9 @@ const size_t kUsageReportsPerRequest = 1;
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
using video_widevine::SignedMessage;
|
||||
using video_widevine::LicenseError;
|
||||
|
||||
class UsagePropertySet : public CdmClientPropertySet {
|
||||
public:
|
||||
UsagePropertySet() {}
|
||||
@@ -70,20 +75,77 @@ CdmEngine::CdmEngine(FileSystem* file_system, const std::string& spoid)
|
||||
}
|
||||
}
|
||||
|
||||
CdmEngine::~CdmEngine() {
|
||||
AutoLock lock(session_list_lock_);
|
||||
CdmSessionMap::iterator i(sessions_.begin());
|
||||
for (; i != sessions_.end(); ++i) {
|
||||
delete i->second;
|
||||
}
|
||||
sessions_.clear();
|
||||
}
|
||||
CdmEngine::~CdmEngine() {}
|
||||
|
||||
CdmResponseType CdmEngine::SetServiceCertificate(
|
||||
const std::string& certificate) {
|
||||
return service_certificate_.Init(certificate);
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -114,7 +176,7 @@ CdmResponseType CdmEngine::OpenSession(
|
||||
}
|
||||
|
||||
if (forced_session_id) {
|
||||
if (sessions_.find(*forced_session_id) != sessions_.end()) {
|
||||
if (session_map_.Exists(*forced_session_id)) {
|
||||
return DUPLICATE_SESSION_ID_SPECIFIED;
|
||||
}
|
||||
}
|
||||
@@ -138,8 +200,7 @@ CdmResponseType CdmEngine::OpenSession(
|
||||
}
|
||||
CdmSessionId id = new_session->session_id();
|
||||
|
||||
AutoLock lock(session_list_lock_);
|
||||
sessions_[id] = new_session.release();
|
||||
session_map_.Add(id, new_session.release());
|
||||
if (session_id) *session_id = id;
|
||||
return NO_ERROR;
|
||||
}
|
||||
@@ -180,15 +241,10 @@ CdmResponseType CdmEngine::OpenKeySetSession(
|
||||
|
||||
CdmResponseType CdmEngine::CloseSession(const CdmSessionId& session_id) {
|
||||
LOGI("CdmEngine::CloseSession");
|
||||
AutoLock lock(session_list_lock_);
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
if (!session_map_.CloseSession(session_id)) {
|
||||
LOGE("CdmEngine::CloseSession: session not found = %s", session_id.c_str());
|
||||
return SESSION_NOT_FOUND_1;
|
||||
}
|
||||
CdmSession* session = iter->second;
|
||||
sessions_.erase(session_id);
|
||||
delete session;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -218,9 +274,7 @@ CdmResponseType CdmEngine::CloseKeySetSession(const CdmKeySetId& key_set_id) {
|
||||
}
|
||||
|
||||
bool CdmEngine::IsOpenSession(const CdmSessionId& session_id) {
|
||||
AutoLock lock(session_list_lock_);
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
return iter != sessions_.end();
|
||||
return session_map_.Exists(session_id);
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GenerateKeyRequest(
|
||||
@@ -258,8 +312,8 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
|
||||
id = iter->second.first;
|
||||
}
|
||||
|
||||
CdmSessionMap::iterator iter = sessions_.find(id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
@@ -273,8 +327,8 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
|
||||
key_request->message.clear();
|
||||
|
||||
if (license_type == kLicenseTypeRelease &&
|
||||
!iter->second->license_received()) {
|
||||
sts = iter->second->RestoreOfflineSession(key_set_id, kLicenseTypeRelease);
|
||||
!session->license_received()) {
|
||||
sts = session->RestoreOfflineSession(key_set_id, kLicenseTypeRelease);
|
||||
if (sts != KEY_ADDED) {
|
||||
LOGE("CdmEngine::GenerateKeyRequest: key release restoration failed,"
|
||||
"sts = %d", static_cast<int>(sts));
|
||||
@@ -282,13 +336,13 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
|
||||
}
|
||||
}
|
||||
|
||||
sts = iter->second->GenerateKeyRequest(
|
||||
init_data, license_type, app_parameters, key_request);
|
||||
sts = session->GenerateKeyRequest(init_data, license_type, app_parameters,
|
||||
key_request);
|
||||
|
||||
if (KEY_MESSAGE != sts) {
|
||||
if (sts == NEED_PROVISIONING) {
|
||||
cert_provisioning_requested_security_level_ =
|
||||
iter->second->GetRequestedSecurityLevel();
|
||||
session->GetRequestedSecurityLevel();
|
||||
}
|
||||
LOGE("CdmEngine::GenerateKeyRequest: key request generation failed, "
|
||||
"sts = %d", static_cast<int>(sts));
|
||||
@@ -331,9 +385,8 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id,
|
||||
id = iter->second.first;
|
||||
}
|
||||
|
||||
CdmSessionMap::iterator iter = sessions_.find(id);
|
||||
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
@@ -343,9 +396,9 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id,
|
||||
return EMPTY_KEY_DATA_1;
|
||||
}
|
||||
|
||||
CdmResponseType sts = iter->second->AddKey(key_data);
|
||||
CdmResponseType sts = session->AddKey(key_data);
|
||||
if (key_set_id) {
|
||||
*key_set_id = iter->second->key_set_id();
|
||||
*key_set_id = session->key_set_id();
|
||||
}
|
||||
|
||||
switch (sts) {
|
||||
@@ -371,18 +424,18 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id,
|
||||
return EMPTY_KEYSET_ID_ENG_4;
|
||||
}
|
||||
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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 =
|
||||
iter->second->RestoreOfflineSession(key_set_id, kLicenseTypeOffline);
|
||||
session->RestoreOfflineSession(key_set_id, kLicenseTypeOffline);
|
||||
if (sts == NEED_PROVISIONING) {
|
||||
cert_provisioning_requested_security_level_ =
|
||||
iter->second->GetRequestedSecurityLevel();
|
||||
session->GetRequestedSecurityLevel();
|
||||
}
|
||||
if (sts != KEY_ADDED && sts != GET_RELEASED_LICENSE_ERROR) {
|
||||
LOGE("CdmEngine::RestoreKey: restore offline session failed = %d", sts);
|
||||
@@ -393,14 +446,14 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id,
|
||||
CdmResponseType CdmEngine::RemoveKeys(const CdmSessionId& session_id) {
|
||||
LOGI("CdmEngine::RemoveKeys");
|
||||
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
|
||||
iter->second->ReleaseCrypto();
|
||||
session->ReleaseCrypto();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -408,8 +461,8 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
|
||||
const CdmSessionId& session_id, CdmKeyRequest* key_request) {
|
||||
LOGI("CdmEngine::GenerateRenewalRequest");
|
||||
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
@@ -422,7 +475,7 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
|
||||
|
||||
key_request->message.clear();
|
||||
|
||||
CdmResponseType sts = iter->second->GenerateRenewalRequest(key_request);
|
||||
CdmResponseType sts = session->GenerateRenewalRequest(key_request);
|
||||
|
||||
if (KEY_MESSAGE != sts) {
|
||||
LOGE("CdmEngine::GenerateRenewalRequest: key request gen. failed, sts=%d",
|
||||
@@ -437,8 +490,8 @@ CdmResponseType CdmEngine::RenewKey(const CdmSessionId& session_id,
|
||||
const CdmKeyResponse& key_data) {
|
||||
LOGI("CdmEngine::RenewKey");
|
||||
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
@@ -448,7 +501,7 @@ CdmResponseType CdmEngine::RenewKey(const CdmSessionId& session_id,
|
||||
return EMPTY_KEY_DATA_2;
|
||||
}
|
||||
|
||||
CdmResponseType sts = iter->second->RenewKey(key_data);
|
||||
CdmResponseType sts = session->RenewKey(key_data);
|
||||
if (KEY_ADDED != sts) {
|
||||
LOGE("CdmEngine::RenewKey: keys not added, sts=%d", static_cast<int>(sts));
|
||||
return sts;
|
||||
@@ -473,8 +526,8 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
}
|
||||
|
||||
if (query_token == QUERY_KEY_SECURITY_LEVEL) {
|
||||
CdmSecurityLevel security_level = crypto_session.GetSecurityLevel();
|
||||
switch (security_level) {
|
||||
CdmSecurityLevel level = crypto_session.GetSecurityLevel();
|
||||
switch (level) {
|
||||
case kSecurityLevelL1:
|
||||
*query_response = QUERY_VALUE_SECURITY_LEVEL_L1;
|
||||
break;
|
||||
@@ -489,8 +542,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
*query_response = QUERY_VALUE_SECURITY_LEVEL_UNKNOWN;
|
||||
break;
|
||||
default:
|
||||
LOGW("CdmEngine::QueryStatus: Unknown security level: %d",
|
||||
security_level);
|
||||
LOGW("CdmEngine::QueryStatus: Unknown security level: %d", level);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
} else if (query_token == QUERY_KEY_DEVICE_ID) {
|
||||
@@ -581,47 +633,47 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
CdmResponseType CdmEngine::QuerySessionStatus(const CdmSessionId& session_id,
|
||||
CdmQueryMap* query_response) {
|
||||
LOGI("CdmEngine::QuerySessionStatus");
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
return iter->second->QueryStatus(query_response);
|
||||
return session->QueryStatus(query_response);
|
||||
}
|
||||
|
||||
bool CdmEngine::IsReleaseSession(const CdmSessionId& session_id) {
|
||||
LOGI("CdmEngine::IsReleaseSession");
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
return iter->second->is_release();
|
||||
return session->is_release();
|
||||
}
|
||||
|
||||
bool CdmEngine::IsOfflineSession(const CdmSessionId& session_id) {
|
||||
LOGI("CdmEngine::IsOfflineSession");
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
return iter->second->is_offline();
|
||||
return session->is_offline();
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::QueryKeyStatus(const CdmSessionId& session_id,
|
||||
CdmQueryMap* query_response) {
|
||||
LOGI("CdmEngine::QueryKeyStatus");
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
return iter->second->QueryKeyStatus(query_response);
|
||||
return session->QueryKeyStatus(query_response);
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::QueryKeyAllowedUsage(const CdmSessionId& session_id,
|
||||
@@ -632,13 +684,13 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const CdmSessionId& session_id,
|
||||
LOGE("CdmEngine::QueryKeyAllowedUsage: no response destination");
|
||||
return INVALID_PARAMETERS_ENG_12;
|
||||
}
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
return iter->second->QueryKeyAllowedUsage(key_id, key_usage);
|
||||
return session->QueryKeyAllowedUsage(key_id, key_usage);
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
|
||||
@@ -652,10 +704,16 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
|
||||
return INVALID_PARAMETERS_ENG_7;
|
||||
}
|
||||
key_usage->Clear();
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
session_sts = iter->second->QueryKeyAllowedUsage(key_id,
|
||||
&found_in_this_session);
|
||||
|
||||
CdmSessionList sessions;
|
||||
session_map_.GetSessionList(sessions);
|
||||
|
||||
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) {
|
||||
// Found another key. If usage settings do not match, fail.
|
||||
@@ -680,13 +738,13 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
|
||||
CdmResponseType CdmEngine::QueryOemCryptoSessionId(
|
||||
const CdmSessionId& session_id, CdmQueryMap* query_response) {
|
||||
LOGI("CdmEngine::QueryOemCryptoSessionId");
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
return iter->second->QueryOemCryptoSessionId(query_response);
|
||||
return session->QueryOemCryptoSessionId(query_response);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -835,19 +893,73 @@ CdmResponseType CdmEngine::ListStoredLicenses(
|
||||
CdmSecurityLevel security_level, std::vector<std::string>* key_set_ids) {
|
||||
DeviceFiles handle(file_system_);
|
||||
if (!key_set_ids) {
|
||||
LOGE("CdmEngine::QueryStoredLicenses: no response destination");
|
||||
LOGE("CdmEngine::ListStoredLicenses: no response destination");
|
||||
return INVALID_PARAMETERS_ENG_17;
|
||||
}
|
||||
if (!handle.Init(security_level)) {
|
||||
LOGE("CdmEngine::ListStoredLicenses: unable to initialize device files");
|
||||
return STORE_LICENSE_ERROR_3;
|
||||
return LIST_LICENSE_ERROR_1;
|
||||
}
|
||||
if (!handle.ListLicenses(key_set_ids)) {
|
||||
return UNKNOWN_ERROR;
|
||||
LOGE("CdmEngine::ListStoredLicenses: ListLicenses call failed");
|
||||
return LIST_LICENSE_ERROR_2;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ListUsageRecords(const std::string& app_id,
|
||||
CdmSecurityLevel security_level,
|
||||
std::vector<std::string>* ksids) {
|
||||
DeviceFiles handle(file_system_);
|
||||
if (!ksids) {
|
||||
LOGE("CdmEngine::ListUsageRecords: no response destination");
|
||||
return INVALID_PARAMETERS_ENG_18;
|
||||
}
|
||||
if (!handle.Init(security_level)) {
|
||||
LOGE("CdmEngine::ListUsageRecords: unable to initialize device files");
|
||||
return LIST_USAGE_ERROR_1;
|
||||
}
|
||||
if (!handle.ListUsageRecords(app_id, ksids)) {
|
||||
LOGE("CdmEngine::ListUsageRecords: ListUsageRecords call failed");
|
||||
return LIST_USAGE_ERROR_2;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::DeleteUsageRecord(const std::string& app_id,
|
||||
CdmSecurityLevel security_level,
|
||||
const std::string& key_set_id) {
|
||||
std::string provider_session_token;
|
||||
|
||||
DeviceFiles handle(file_system_);
|
||||
if (!handle.Init(security_level)) {
|
||||
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");
|
||||
return DELETE_USAGE_ERROR_2;
|
||||
}
|
||||
|
||||
// Got provider token. Remove from OEMCrypto.
|
||||
scoped_ptr<CryptoSession> crypto_session(new CryptoSession());
|
||||
CdmResponseType status = crypto_session->Open(
|
||||
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
|
||||
if (status == NO_ERROR) {
|
||||
status = crypto_session->DeleteUsageInformation(provider_session_token);
|
||||
}
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("CdmEngine::DeleteUsageRecord: OEMCrypto failure");
|
||||
}
|
||||
|
||||
// Remove from file system.
|
||||
if (!handle.DeleteUsageInfo(app_id, provider_session_token)) {
|
||||
LOGE("CdmEngine::DeleteUsageRecord: file system failure");
|
||||
return DELETE_USAGE_ERROR_3;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
const CdmSecureStopId& ssid,
|
||||
CdmUsageInfo* usage_info) {
|
||||
@@ -915,6 +1027,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
usage_info->clear();
|
||||
return status;
|
||||
}
|
||||
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
|
||||
@@ -930,7 +1043,9 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
do {
|
||||
status = GetUsageInfo(app_id, security_level, usage_info);
|
||||
|
||||
if (KEY_MESSAGE == status && !usage_info->empty()) return status;
|
||||
if (KEY_MESSAGE == status && !usage_info->empty()) {
|
||||
return status;
|
||||
}
|
||||
} while (KEY_CANCELED == status);
|
||||
|
||||
security_level = (kLevel3 == security_level) ? kLevelDefault : kLevel3;
|
||||
@@ -1015,6 +1130,37 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ReleaseAllUsageInfo(
|
||||
const std::string& app_id, CdmSecurityLevel security_level) {
|
||||
DeviceFiles handle(file_system_);
|
||||
if (!handle.Init(security_level)) {
|
||||
LOGE("CdmEngine::ReleaseAllUsageInfo: unable to initialize device files");
|
||||
return RELEASE_ALL_USAGE_INFO_ERROR_3;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (provider_session_tokens.size() == 0UL) {
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// Got at least one provider token. Remove from OEMCrypto.
|
||||
scoped_ptr<CryptoSession> crypto_session(new CryptoSession());
|
||||
CdmResponseType status = crypto_session->Open(
|
||||
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
|
||||
if (status == NO_ERROR) {
|
||||
status = crypto_session->
|
||||
DeleteMultipleUsageInformation(provider_session_tokens);
|
||||
}
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("CdmEngine::DeleteUsageRecord: CryptoSession failure");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
|
||||
if (NULL == usage_property_set_.get()) {
|
||||
usage_property_set_.reset(new UsagePropertySet());
|
||||
@@ -1081,8 +1227,8 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
|
||||
return EMPTY_KEYSET_ID_ENG_5;
|
||||
}
|
||||
|
||||
CdmSessionMap::iterator iter = sessions_.find(key_set_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
@@ -1094,13 +1240,13 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
|
||||
}
|
||||
|
||||
DeviceFiles handle(file_system_);
|
||||
if (!handle.Init(iter->second->GetSecurityLevel())) {
|
||||
if (!handle.Init(session->GetSecurityLevel())) {
|
||||
LOGE("CdmEngine::LoadUsageSession: unable to initialize device files");
|
||||
return LOAD_USAGE_INFO_FILE_ERROR;
|
||||
}
|
||||
|
||||
std::string app_id;
|
||||
iter->second->GetApplicationId(&app_id);
|
||||
session->GetApplicationId(&app_id);
|
||||
|
||||
CdmKeyMessage key_message;
|
||||
CdmKeyResponse key_response;
|
||||
@@ -1110,22 +1256,22 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
|
||||
return LOAD_USAGE_INFO_MISSING;
|
||||
}
|
||||
|
||||
CdmResponseType status =
|
||||
iter->second->RestoreUsageSession(key_message, key_response);
|
||||
CdmResponseType status = session->RestoreUsageSession(key_message,
|
||||
key_response);
|
||||
if (KEY_ADDED != status) {
|
||||
LOGE("CdmEngine::LoadUsageSession: usage session error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmKeyRequest request;
|
||||
status = iter->second->GenerateReleaseRequest(&request);
|
||||
status = session->GenerateReleaseRequest(&request);
|
||||
*release_message = request.message;
|
||||
|
||||
switch (status) {
|
||||
case KEY_MESSAGE:
|
||||
break;
|
||||
case KEY_CANCELED: // usage information not present in
|
||||
iter->second->DeleteLicense(); // OEMCrypto, delete and try again
|
||||
session->DeleteLicense(); // OEMCrypto, delete and try again
|
||||
break;
|
||||
default:
|
||||
LOGE("CdmEngine::LoadUsageSession: generate release request error: %d",
|
||||
@@ -1161,45 +1307,55 @@ CdmResponseType CdmEngine::Decrypt(const CdmSessionId& session_id,
|
||||
// else we must be level 1 direct and we don't need to return a buffer.
|
||||
}
|
||||
|
||||
CdmSessionMap::iterator session_iter = sessions_.end();
|
||||
std::shared_ptr<CdmSession> session;
|
||||
if (session_id.empty()) {
|
||||
CdmSessionList sessions;
|
||||
session_map_.GetSessionList(sessions);
|
||||
|
||||
// Loop through the sessions to find the session containing the key_id
|
||||
// with the longest remaining license validity.
|
||||
int64_t seconds_remaining = 0;
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
if (iter->second->IsKeyLoaded(*parameters.key_id)) {
|
||||
int64_t duration = iter->second->GetDurationRemaining();
|
||||
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) {
|
||||
session_iter = iter;
|
||||
session = *iter;
|
||||
seconds_remaining = duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
session_iter = sessions_.find(session_id);
|
||||
session_map_.FindSession(session_id, session);
|
||||
}
|
||||
if (session_iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::Decrypt: session not found: id=%s, id size=%d",
|
||||
session_id.c_str(), session_id.size());
|
||||
|
||||
if (session.get() == NULL) {
|
||||
if (session_id.empty()) {
|
||||
LOGE("CdmEngine::Decrypt: session not found: Empty session ID");
|
||||
} else {
|
||||
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_iter->second->Decrypt(parameters);
|
||||
return session->Decrypt(parameters);
|
||||
}
|
||||
|
||||
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) {
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
return iter->second->GenericEncrypt(in_buffer, key_id, iv, algorithm,
|
||||
out_buffer);
|
||||
return session->GenericEncrypt(in_buffer, key_id, iv, algorithm, out_buffer);
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GenericDecrypt(
|
||||
@@ -1207,46 +1363,51 @@ CdmResponseType CdmEngine::GenericDecrypt(
|
||||
const std::string& key_id, const std::string& iv,
|
||||
CdmEncryptionAlgorithm algorithm,
|
||||
std::string* out_buffer) {
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
return iter->second->GenericDecrypt(in_buffer, key_id, iv, algorithm,
|
||||
out_buffer);
|
||||
return session->GenericDecrypt(in_buffer, key_id, iv, algorithm, out_buffer);
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GenericSign(
|
||||
const std::string& session_id, const std::string& message,
|
||||
const std::string& key_id, CdmSigningAlgorithm algorithm,
|
||||
std::string* signature) {
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
return iter->second->GenericSign(message, key_id, algorithm, signature);
|
||||
return session->GenericSign(message, key_id, algorithm, signature);
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GenericVerify(
|
||||
const std::string& session_id, const std::string& message,
|
||||
const std::string& key_id, CdmSigningAlgorithm algorithm,
|
||||
const std::string& signature) {
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
std::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;
|
||||
}
|
||||
return iter->second->GenericVerify(message, key_id, algorithm, signature);
|
||||
return session->GenericVerify(message, key_id, algorithm, signature);
|
||||
}
|
||||
|
||||
// TODO(gmorgan) Used? Delete if unused.
|
||||
bool CdmEngine::IsKeyLoaded(const KeyId& key_id) {
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
if (iter->second->IsKeyLoaded(key_id)) {
|
||||
CdmSessionList sessions;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1260,18 +1421,23 @@ bool CdmEngine::FindSessionForKey(const KeyId& key_id,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint32_t session_sharing_id = Properties::GetSessionSharingId(*session_id);
|
||||
|
||||
CdmSessionMap::iterator session_iter = sessions_.end();
|
||||
CdmSessionList sessions;
|
||||
session_map_.GetSessionList(sessions);
|
||||
|
||||
CdmSessionList::iterator session_iter = sessions.end();
|
||||
|
||||
int64_t seconds_remaining = 0;
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
CdmSessionId local_session_id = iter->second->session_id();
|
||||
if (Properties::GetSessionSharingId(local_session_id) ==
|
||||
session_sharing_id) {
|
||||
if (iter->second->IsKeyLoaded(key_id)) {
|
||||
int64_t duration = iter->second->GetDurationRemaining();
|
||||
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)) {
|
||||
int64_t duration = (*iter)->GetDurationRemaining();
|
||||
if (duration > seconds_remaining) {
|
||||
session_iter = iter;
|
||||
seconds_remaining = duration;
|
||||
@@ -1280,8 +1446,8 @@ bool CdmEngine::FindSessionForKey(const KeyId& key_id,
|
||||
}
|
||||
}
|
||||
|
||||
if (session_iter != sessions_.end()) {
|
||||
*session_id = session_iter->second->session_id();
|
||||
if (session_iter != sessions.end()) {
|
||||
*session_id = (*session_iter)->session_id();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1289,9 +1455,9 @@ bool CdmEngine::FindSessionForKey(const KeyId& key_id,
|
||||
|
||||
bool CdmEngine::NotifyResolution(const CdmSessionId& session_id, uint32_t width,
|
||||
uint32_t height) {
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter != sessions_.end()) {
|
||||
iter->second->NotifyResolution(width, height);
|
||||
std::shared_ptr<CdmSession> session;
|
||||
if (session_map_.FindSession(session_id, session)) {
|
||||
session->NotifyResolution(width, height);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1304,8 +1470,11 @@ bool CdmEngine::ValidateKeySystem(const CdmKeySystem& key_system) {
|
||||
void CdmEngine::OnTimerEvent() {
|
||||
Clock clock;
|
||||
uint64_t current_time = clock.GetCurrentTime();
|
||||
bool usage_update_period_expired = false;
|
||||
|
||||
CdmSessionList sessions;
|
||||
session_map_.GetSessionList(sessions);
|
||||
|
||||
bool usage_update_period_expired = false;
|
||||
if (current_time - last_usage_information_update_time_ >
|
||||
kUpdateUsageInformationPeriod) {
|
||||
usage_update_period_expired = true;
|
||||
@@ -1315,27 +1484,35 @@ void CdmEngine::OnTimerEvent() {
|
||||
bool is_initial_usage_update = false;
|
||||
bool is_usage_update_needed = false;
|
||||
|
||||
AutoLock lock(session_list_lock_);
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
while (!sessions.empty()) {
|
||||
is_initial_usage_update =
|
||||
is_initial_usage_update || iter->second->is_initial_usage_update();
|
||||
is_initial_usage_update || sessions.front()->is_initial_usage_update();
|
||||
is_usage_update_needed =
|
||||
is_usage_update_needed || iter->second->is_usage_update_needed();
|
||||
is_usage_update_needed || sessions.front()->is_usage_update_needed();
|
||||
|
||||
iter->second->OnTimerEvent(usage_update_period_expired);
|
||||
if (!sessions.front()->IsClosed()) {
|
||||
sessions.front()->OnTimerEvent(usage_update_period_expired);
|
||||
}
|
||||
sessions.pop_front();
|
||||
}
|
||||
|
||||
if (is_usage_update_needed &&
|
||||
(usage_update_period_expired || is_initial_usage_update)) {
|
||||
bool has_usage_been_updated = false;
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
iter->second->reset_usage_flags();
|
||||
|
||||
// Session list may have changed. Rebuild.
|
||||
session_map_.GetSessionList(sessions);
|
||||
|
||||
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->second->UpdateUsageInformation();
|
||||
CdmResponseType status = (*iter)->UpdateUsageInformation();
|
||||
if (NO_ERROR != status) {
|
||||
LOGW("Update usage information failed: %d", status);
|
||||
} else {
|
||||
@@ -1344,15 +1521,18 @@ void CdmEngine::OnTimerEvent() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseExpiredReleaseSessions();
|
||||
}
|
||||
|
||||
void CdmEngine::OnKeyReleaseEvent(const CdmKeySetId& key_set_id) {
|
||||
AutoLock lock(session_list_lock_);
|
||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||
iter != sessions_.end(); ++iter) {
|
||||
iter->second->OnKeyReleaseEvent(key_set_id);
|
||||
CdmSessionList sessions;
|
||||
session_map_.GetSessionList(sessions);
|
||||
|
||||
while (!sessions.empty()) {
|
||||
if (!sessions.front()->IsClosed()) {
|
||||
sessions.front()->OnKeyReleaseEvent(key_set_id);
|
||||
}
|
||||
sessions.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1415,12 +1595,12 @@ void CdmEngine::DeleteAllUsageReportsUponFactoryReset() {
|
||||
status = crypto_session->DeleteAllUsageReports();
|
||||
if (NO_ERROR != status) {
|
||||
LOGW(
|
||||
"CdmEngine::GetProvisioningRequest: "
|
||||
"CdmEngine::DeleteAllUsageReportsUponFactoryReset: "
|
||||
"Fails to delete usage reports: %d", status);
|
||||
}
|
||||
} else {
|
||||
LOGW(
|
||||
"CdmEngine::GetProvisioningRequest: "
|
||||
"CdmEngine::DeleteAllUsageReportsUponFactoryReset: "
|
||||
"Fails to open crypto session: error=%d.\n"
|
||||
"Usage reports are not removed after factory reset.", status);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user