Source release v3.0.0-0-g8d3792b-ce + third_party
Change-Id: I399e71ddfffcd436171d1c60283c63ab4658e0b1
This commit is contained in:
@@ -21,16 +21,43 @@
|
||||
namespace {
|
||||
const uint32_t kUpdateUsageInformationPeriod = 60; // seconds
|
||||
const size_t kUsageReportsPerRequest = 1;
|
||||
} // unnamed namespace
|
||||
} // namespace
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
class UsagePropertySet : public CdmClientPropertySet {
|
||||
public:
|
||||
UsagePropertySet() {}
|
||||
virtual ~UsagePropertySet() {}
|
||||
void set_security_level(SecurityLevel security_level) {
|
||||
if (kLevel3 == security_level)
|
||||
security_level_ = QUERY_VALUE_SECURITY_LEVEL_L3;
|
||||
else
|
||||
security_level_.clear();
|
||||
}
|
||||
virtual const std::string& security_level() const { return security_level_; }
|
||||
virtual bool use_privacy_mode() const { return false; }
|
||||
virtual const std::string& service_certificate() const { return empty_; }
|
||||
virtual void set_service_certificate(const std::string&) {}
|
||||
virtual bool is_session_sharing_enabled() const { return false; }
|
||||
virtual uint32_t session_sharing_id() const { return 0; }
|
||||
virtual void set_session_sharing_id(uint32_t /* id */) {}
|
||||
virtual const std::string& app_id() const { return app_id_; }
|
||||
void set_app_id(const std::string& appId) { app_id_ = appId; }
|
||||
|
||||
private:
|
||||
std::string app_id_;
|
||||
std::string security_level_;
|
||||
const std::string empty_;
|
||||
};
|
||||
|
||||
bool CdmEngine::seeded_ = false;
|
||||
|
||||
CdmEngine::CdmEngine()
|
||||
: cert_provisioning_requested_security_level_(kLevelDefault),
|
||||
: cert_provisioning_(NULL),
|
||||
cert_provisioning_requested_security_level_(kLevelDefault),
|
||||
usage_session_(NULL),
|
||||
last_usage_information_update_time(0) {
|
||||
last_usage_information_update_time_(0) {
|
||||
Properties::Init();
|
||||
if (!seeded_) {
|
||||
Clock clock;
|
||||
@@ -40,6 +67,7 @@ CdmEngine::CdmEngine()
|
||||
}
|
||||
|
||||
CdmEngine::~CdmEngine() {
|
||||
AutoLock lock(session_list_lock_);
|
||||
CdmSessionMap::iterator i(sessions_.begin());
|
||||
for (; i != sessions_.end(); ++i) {
|
||||
delete i->second;
|
||||
@@ -48,24 +76,34 @@ CdmEngine::~CdmEngine() {
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::OpenSession(const CdmKeySystem& key_system,
|
||||
const CdmClientPropertySet* property_set,
|
||||
CdmClientPropertySet* property_set,
|
||||
const std::string& origin,
|
||||
WvCdmEventListener* event_listener,
|
||||
const CdmSessionId* forced_session_id,
|
||||
CdmSessionId* session_id) {
|
||||
LOGI("CdmEngine::OpenSession");
|
||||
|
||||
if (!ValidateKeySystem(key_system)) {
|
||||
LOGI("CdmEngine::OpenSession: invalid key_system = %s", key_system.c_str());
|
||||
return KEY_ERROR;
|
||||
return INVALID_KEY_SYSTEM;
|
||||
}
|
||||
|
||||
if (!session_id) {
|
||||
LOGE("CdmEngine::OpenSession: no session ID destination provided");
|
||||
return KEY_ERROR;
|
||||
return INVALID_PARAMETERS_ENG_1;
|
||||
}
|
||||
|
||||
scoped_ptr<CdmSession> new_session(new CdmSession(property_set));
|
||||
if (forced_session_id) {
|
||||
if (sessions_.find(*forced_session_id) != sessions_.end()) {
|
||||
return DUPLICATE_SESSION_ID_SPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
scoped_ptr<CdmSession> new_session(
|
||||
new CdmSession(property_set, origin, event_listener, forced_session_id));
|
||||
if (new_session->session_id().empty()) {
|
||||
LOGE("CdmEngine::OpenSession: failure to generate session ID");
|
||||
return UNKNOWN_ERROR;
|
||||
return EMPTY_SESSION_ID;
|
||||
}
|
||||
|
||||
CdmResponseType sts = new_session->Init();
|
||||
@@ -74,25 +112,30 @@ CdmResponseType CdmEngine::OpenSession(const CdmKeySystem& key_system,
|
||||
cert_provisioning_requested_security_level_ =
|
||||
new_session->GetRequestedSecurityLevel();
|
||||
} else {
|
||||
LOGE("CdmEngine::OpenSession: bad session init: %u", sts);
|
||||
LOGE("CdmEngine::OpenSession: bad session init: %d", sts);
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
*session_id = new_session->session_id();
|
||||
AutoLock lock(session_list_lock_);
|
||||
sessions_[*session_id] = new_session.release();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::OpenKeySetSession(const CdmKeySetId& key_set_id) {
|
||||
CdmResponseType CdmEngine::OpenKeySetSession(
|
||||
const CdmKeySetId& key_set_id, CdmClientPropertySet* property_set,
|
||||
const std::string& origin, WvCdmEventListener* event_listener) {
|
||||
LOGI("CdmEngine::OpenKeySetSession");
|
||||
|
||||
if (key_set_id.empty()) {
|
||||
LOGE("CdmEngine::OpenKeySetSession: invalid key set id");
|
||||
return KEY_ERROR;
|
||||
return EMPTY_KEYSET_ID_ENG_1;
|
||||
}
|
||||
|
||||
CdmSessionId session_id;
|
||||
CdmResponseType sts = OpenSession(KEY_SYSTEM, NULL, &session_id);
|
||||
CdmResponseType sts =
|
||||
OpenSession(KEY_SYSTEM, property_set, origin, event_listener,
|
||||
NULL /* forced_session_id */, &session_id);
|
||||
|
||||
if (sts != NO_ERROR) return sts;
|
||||
|
||||
@@ -102,13 +145,12 @@ CdmResponseType CdmEngine::OpenKeySetSession(const CdmKeySetId& key_set_id) {
|
||||
|
||||
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()) {
|
||||
LOGE("CdmEngine::CloseSession: session not found = %s", session_id.c_str());
|
||||
return KEY_ERROR;
|
||||
return SESSION_NOT_FOUND_1;
|
||||
}
|
||||
|
||||
CdmSession* session = iter->second;
|
||||
sessions_.erase(session_id);
|
||||
delete session;
|
||||
@@ -122,7 +164,7 @@ CdmResponseType CdmEngine::CloseKeySetSession(const CdmKeySetId& key_set_id) {
|
||||
if (iter == release_key_sets_.end()) {
|
||||
LOGE("CdmEngine::CloseKeySetSession: key set id not found = %s",
|
||||
key_set_id.c_str());
|
||||
return KEY_ERROR;
|
||||
return KEYSET_ID_NOT_FOUND_1;
|
||||
}
|
||||
|
||||
CdmResponseType sts = CloseSession(iter->second);
|
||||
@@ -130,33 +172,42 @@ CdmResponseType CdmEngine::CloseKeySetSession(const CdmKeySetId& key_set_id) {
|
||||
return sts;
|
||||
}
|
||||
|
||||
bool CdmEngine::IsOpenSession(const CdmSessionId& session_id) {
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
return iter != sessions_.end();
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GenerateKeyRequest(
|
||||
const CdmSessionId& session_id, const CdmKeySetId& key_set_id,
|
||||
const InitializationData& init_data, const CdmLicenseType license_type,
|
||||
CdmAppParameterMap& app_parameters, CdmKeyMessage* key_request,
|
||||
std::string* server_url, CdmKeySetId* key_set_id_out) {
|
||||
CdmKeyRequestType* key_request_type, std::string* server_url,
|
||||
CdmKeySetId* key_set_id_out) {
|
||||
LOGI("CdmEngine::GenerateKeyRequest");
|
||||
|
||||
CdmSessionId id = session_id;
|
||||
CdmResponseType sts;
|
||||
|
||||
if (license_type == kLicenseTypeRelease) {
|
||||
// NOTE: If AlwaysUseKeySetIds() is true, there is no need to consult the
|
||||
// release_key_sets_ map for release licenses.
|
||||
if (license_type == kLicenseTypeRelease &&
|
||||
!Properties::AlwaysUseKeySetIds()) {
|
||||
if (key_set_id.empty()) {
|
||||
LOGE("CdmEngine::GenerateKeyRequest: invalid key set ID");
|
||||
return UNKNOWN_ERROR;
|
||||
return EMPTY_KEYSET_ID_ENG_2;
|
||||
}
|
||||
|
||||
if (!session_id.empty()) {
|
||||
LOGE("CdmEngine::GenerateKeyRequest: invalid session ID = %s",
|
||||
session_id.c_str());
|
||||
return UNKNOWN_ERROR;
|
||||
return INVALID_SESSION_ID;
|
||||
}
|
||||
|
||||
CdmReleaseKeySetMap::iterator iter = release_key_sets_.find(key_set_id);
|
||||
if (iter == release_key_sets_.end()) {
|
||||
LOGE("CdmEngine::GenerateKeyRequest: key set ID not found = %s",
|
||||
key_set_id.c_str());
|
||||
return UNKNOWN_ERROR;
|
||||
return KEYSET_ID_NOT_FOUND_2;
|
||||
}
|
||||
|
||||
id = iter->second;
|
||||
@@ -166,12 +217,12 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::GenerateKeyRequest: session_id not found = %s",
|
||||
id.c_str());
|
||||
return KEY_ERROR;
|
||||
return SESSION_NOT_FOUND_2;
|
||||
}
|
||||
|
||||
if (!key_request) {
|
||||
LOGE("CdmEngine::GenerateKeyRequest: no key request destination provided");
|
||||
return KEY_ERROR;
|
||||
return INVALID_PARAMETERS_ENG_2;
|
||||
}
|
||||
|
||||
key_request->clear();
|
||||
@@ -179,27 +230,23 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
|
||||
if (license_type == kLicenseTypeRelease) {
|
||||
sts = iter->second->RestoreOfflineSession(key_set_id, kLicenseTypeRelease);
|
||||
if (sts != KEY_ADDED) {
|
||||
LOGE(
|
||||
"CdmEngine::GenerateKeyRequest: key release restoration failed,"
|
||||
"sts = %d",
|
||||
(int)sts);
|
||||
LOGE("CdmEngine::GenerateKeyRequest: key release restoration failed,"
|
||||
"sts = %d", static_cast<int>(sts));
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
|
||||
sts = iter->second->GenerateKeyRequest(
|
||||
init_data, license_type, app_parameters, key_request, server_url,
|
||||
key_set_id_out);
|
||||
init_data, license_type, app_parameters, key_request, key_request_type,
|
||||
server_url, key_set_id_out);
|
||||
|
||||
if (KEY_MESSAGE != sts) {
|
||||
if (sts == NEED_PROVISIONING) {
|
||||
cert_provisioning_requested_security_level_ =
|
||||
iter->second->GetRequestedSecurityLevel();
|
||||
}
|
||||
LOGE(
|
||||
"CdmEngine::GenerateKeyRequest: key request generation failed, "
|
||||
"sts = %d",
|
||||
(int)sts);
|
||||
LOGE("CdmEngine::GenerateKeyRequest: key request generation failed, "
|
||||
"sts = %d", static_cast<int>(sts));
|
||||
return sts;
|
||||
}
|
||||
|
||||
@@ -221,18 +268,18 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id,
|
||||
if (license_type_release) {
|
||||
if (!key_set_id) {
|
||||
LOGE("CdmEngine::AddKey: no key set id provided");
|
||||
return KEY_ERROR;
|
||||
return INVALID_PARAMETERS_ENG_3;
|
||||
}
|
||||
|
||||
if (key_set_id->empty()) {
|
||||
LOGE("CdmEngine::AddKey: invalid key set id");
|
||||
return KEY_ERROR;
|
||||
return EMPTY_KEYSET_ID_ENG_3;
|
||||
}
|
||||
|
||||
CdmReleaseKeySetMap::iterator iter = release_key_sets_.find(*key_set_id);
|
||||
if (iter == release_key_sets_.end()) {
|
||||
LOGE("CdmEngine::AddKey: key set id not found = %s", key_set_id->c_str());
|
||||
return KEY_ERROR;
|
||||
return KEYSET_ID_NOT_FOUND_3;
|
||||
}
|
||||
|
||||
id = iter->second;
|
||||
@@ -242,18 +289,18 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id,
|
||||
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::AddKey: session id not found = %s", id.c_str());
|
||||
return KEY_ERROR;
|
||||
return SESSION_NOT_FOUND_3;
|
||||
}
|
||||
|
||||
if (key_data.empty()) {
|
||||
LOGE("CdmEngine::AddKey: no key_data");
|
||||
return KEY_ERROR;
|
||||
return EMPTY_KEY_DATA_1;
|
||||
}
|
||||
|
||||
CdmResponseType sts = iter->second->AddKey(key_data, key_set_id);
|
||||
|
||||
if (KEY_ADDED != sts) {
|
||||
LOGE("CdmEngine::AddKey: keys not added, result = %d", (int)sts);
|
||||
LOGE("CdmEngine::AddKey: keys not added, result = %d", sts);
|
||||
return sts;
|
||||
}
|
||||
|
||||
@@ -266,14 +313,14 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id,
|
||||
|
||||
if (key_set_id.empty()) {
|
||||
LOGI("CdmEngine::RestoreKey: invalid key set id");
|
||||
return KEY_ERROR;
|
||||
return EMPTY_KEYSET_ID_ENG_4;
|
||||
}
|
||||
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::RestoreKey: session_id not found = %s ",
|
||||
session_id.c_str());
|
||||
return UNKNOWN_ERROR;
|
||||
return SESSION_NOT_FOUND_4;
|
||||
}
|
||||
|
||||
CdmResponseType sts =
|
||||
@@ -282,10 +329,10 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id,
|
||||
cert_provisioning_requested_security_level_ =
|
||||
iter->second->GetRequestedSecurityLevel();
|
||||
}
|
||||
if (sts != KEY_ADDED) {
|
||||
if (sts != KEY_ADDED && sts != GET_RELEASED_LICENSE_ERROR) {
|
||||
LOGE("CdmEngine::RestoreKey: restore offline session failed = %d", sts);
|
||||
}
|
||||
return sts;
|
||||
return sts; // TODO ewew
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::RemoveKeys(const CdmSessionId& session_id) {
|
||||
@@ -295,7 +342,7 @@ CdmResponseType CdmEngine::RemoveKeys(const CdmSessionId& session_id) {
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::RemoveKeys: session_id not found = %s",
|
||||
session_id.c_str());
|
||||
return KEY_ERROR;
|
||||
return SESSION_NOT_FOUND_5;
|
||||
}
|
||||
|
||||
iter->second->ReleaseCrypto();
|
||||
@@ -311,12 +358,12 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::GenerateRenewalRequest: session_id not found = %s",
|
||||
session_id.c_str());
|
||||
return KEY_ERROR;
|
||||
return SESSION_NOT_FOUND_6;
|
||||
}
|
||||
|
||||
if (!key_request) {
|
||||
LOGE("CdmEngine::GenerateRenewalRequest: no key request destination");
|
||||
return KEY_ERROR;
|
||||
return INVALID_PARAMETERS_ENG_4;
|
||||
}
|
||||
|
||||
key_request->clear();
|
||||
@@ -326,7 +373,7 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
|
||||
|
||||
if (KEY_MESSAGE != sts) {
|
||||
LOGE("CdmEngine::GenerateRenewalRequest: key request gen. failed, sts=%d",
|
||||
(int)sts);
|
||||
sts);
|
||||
return sts;
|
||||
}
|
||||
|
||||
@@ -340,26 +387,31 @@ CdmResponseType CdmEngine::RenewKey(const CdmSessionId& session_id,
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::RenewKey: session_id not found = %s", session_id.c_str());
|
||||
return KEY_ERROR;
|
||||
return SESSION_NOT_FOUND_7;
|
||||
}
|
||||
|
||||
if (key_data.empty()) {
|
||||
LOGE("CdmEngine::RenewKey: no key_data");
|
||||
return KEY_ERROR;
|
||||
return EMPTY_KEY_DATA_2;
|
||||
}
|
||||
|
||||
CdmResponseType sts = iter->second->RenewKey(key_data);
|
||||
if (KEY_ADDED != sts) {
|
||||
LOGE("CdmEngine::RenewKey: keys not added, sts=%d", (int)sts);
|
||||
LOGE("CdmEngine::RenewKey: keys not added, sts=%d", static_cast<int>(sts));
|
||||
return sts;
|
||||
}
|
||||
|
||||
return KEY_ADDED;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) {
|
||||
CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
CdmQueryMap* key_info) {
|
||||
LOGI("CdmEngine::QueryStatus");
|
||||
CryptoSession crypto_session;
|
||||
if (security_level == kLevel3) {
|
||||
CdmResponseType status = crypto_session.Open(kLevel3);
|
||||
if (NO_ERROR != status) return INVALID_QUERY_STATUS;
|
||||
}
|
||||
switch (crypto_session.GetSecurityLevel()) {
|
||||
case kSecurityLevelL1:
|
||||
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1;
|
||||
@@ -376,7 +428,7 @@ CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) {
|
||||
QUERY_VALUE_SECURITY_LEVEL_UNKNOWN;
|
||||
break;
|
||||
default:
|
||||
return KEY_ERROR;
|
||||
return INVALID_QUERY_KEY;
|
||||
}
|
||||
|
||||
std::string deviceId;
|
||||
@@ -399,6 +451,39 @@ CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) {
|
||||
(*key_info)[QUERY_KEY_PROVISIONING_ID] = provisioning_id;
|
||||
}
|
||||
|
||||
CryptoSession::HdcpCapability current_hdcp;
|
||||
CryptoSession::HdcpCapability max_hdcp;
|
||||
success = crypto_session.GetHdcpCapabilities(¤t_hdcp, &max_hdcp);
|
||||
if (success) {
|
||||
(*key_info)[QUERY_KEY_CURRENT_HDCP_LEVEL] = MapHdcpVersion(current_hdcp);
|
||||
(*key_info)[QUERY_KEY_MAX_HDCP_LEVEL] = MapHdcpVersion(max_hdcp);
|
||||
}
|
||||
|
||||
bool supports_usage_reporting;
|
||||
success = crypto_session.UsageInformationSupport(&supports_usage_reporting);
|
||||
if (success) {
|
||||
(*key_info)[QUERY_KEY_USAGE_SUPPORT] =
|
||||
supports_usage_reporting ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
|
||||
}
|
||||
|
||||
size_t number_of_open_sessions;
|
||||
success = crypto_session.GetNumberOfOpenSessions(&number_of_open_sessions);
|
||||
if (success) {
|
||||
std::ostringstream open_sessions_stream;
|
||||
open_sessions_stream << number_of_open_sessions;
|
||||
(*key_info)[QUERY_KEY_NUMBER_OF_OPEN_SESSIONS] =
|
||||
open_sessions_stream.str();
|
||||
}
|
||||
|
||||
size_t maximum_number_of_sessions;
|
||||
success = crypto_session.GetMaxNumberOfSessions(&maximum_number_of_sessions);
|
||||
if (success) {
|
||||
std::ostringstream max_sessions_stream;
|
||||
max_sessions_stream << maximum_number_of_sessions;
|
||||
(*key_info)[QUERY_KEY_MAX_NUMBER_OF_SESSIONS] =
|
||||
max_sessions_stream.str();
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -409,11 +494,33 @@ CdmResponseType CdmEngine::QuerySessionStatus(const CdmSessionId& session_id,
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::QuerySessionStatus: session_id not found = %s",
|
||||
session_id.c_str());
|
||||
return KEY_ERROR;
|
||||
return SESSION_NOT_FOUND_8;
|
||||
}
|
||||
return iter->second->QueryStatus(key_info);
|
||||
}
|
||||
|
||||
bool CdmEngine::IsReleaseSession(const CdmSessionId& session_id) {
|
||||
LOGI("CdmEngine::IsReleaseSession");
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::IsReleaseSession: session_id not found = %s",
|
||||
session_id.c_str());
|
||||
return false;
|
||||
}
|
||||
return iter->second->is_release();
|
||||
}
|
||||
|
||||
bool CdmEngine::IsOfflineSession(const CdmSessionId& session_id) {
|
||||
LOGI("CdmEngine::IsOfflineSession");
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::IsOfflineSession: session_id not found = %s",
|
||||
session_id.c_str());
|
||||
return false;
|
||||
}
|
||||
return iter->second->is_offline();
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::QueryKeyStatus(const CdmSessionId& session_id,
|
||||
CdmQueryMap* key_info) {
|
||||
LOGI("CdmEngine::QueryKeyStatus");
|
||||
@@ -421,7 +528,7 @@ CdmResponseType CdmEngine::QueryKeyStatus(const CdmSessionId& session_id,
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::QueryKeyStatus: session_id not found = %s",
|
||||
session_id.c_str());
|
||||
return KEY_ERROR;
|
||||
return SESSION_NOT_FOUND_9;
|
||||
}
|
||||
return iter->second->QueryKeyStatus(key_info);
|
||||
}
|
||||
@@ -433,7 +540,7 @@ CdmResponseType CdmEngine::QueryKeyControlInfo(const CdmSessionId& session_id,
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::QueryKeyControlInfo: session_id not found = %s",
|
||||
session_id.c_str());
|
||||
return KEY_ERROR;
|
||||
return SESSION_NOT_FOUND_10;
|
||||
}
|
||||
return iter->second->QueryKeyControlInfo(key_info);
|
||||
}
|
||||
@@ -443,18 +550,30 @@ CdmResponseType CdmEngine::QueryKeyControlInfo(const CdmSessionId& session_id,
|
||||
* in *request. It also returns the default url for the provisioning server
|
||||
* in *default_url.
|
||||
*
|
||||
* Returns NO_ERROR for success and UNKNOWN_ERROR if fails.
|
||||
* Returns NO_ERROR for success and CdmResponseType error code if fails.
|
||||
*/
|
||||
CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
CdmCertificateType cert_type, const std::string& cert_authority,
|
||||
CdmProvisioningRequest* request, std::string* default_url) {
|
||||
if (!request || !default_url) {
|
||||
LOGE("CdmEngine::GetProvisioningRequest: invalid input parameters");
|
||||
return UNKNOWN_ERROR;
|
||||
const std::string& origin, CdmProvisioningRequest* request,
|
||||
std::string* default_url) {
|
||||
if (!request) {
|
||||
LOGE("CdmEngine::GetProvisioningRequest: invalid output parameters");
|
||||
return INVALID_PROVISIONING_REQUEST_PARAM_1;
|
||||
}
|
||||
return cert_provisioning_.GetProvisioningRequest(
|
||||
if (!default_url) {
|
||||
LOGE("CdmEngine::GetProvisioningRequest: invalid output parameters");
|
||||
return INVALID_PROVISIONING_REQUEST_PARAM_2;
|
||||
}
|
||||
if (NULL == cert_provisioning_.get()) {
|
||||
cert_provisioning_.reset(new CertificateProvisioning());
|
||||
}
|
||||
CdmResponseType ret = cert_provisioning_->GetProvisioningRequest(
|
||||
cert_provisioning_requested_security_level_, cert_type, cert_authority,
|
||||
request, default_url);
|
||||
origin, request, default_url);
|
||||
if (ret != NO_ERROR) {
|
||||
cert_provisioning_.reset(NULL); // Release resources.
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -462,47 +581,183 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
* The device RSA key is stored in the T.E.E. The device certificate is stored
|
||||
* in the device.
|
||||
*
|
||||
* Returns NO_ERROR for success and UNKNOWN_ERROR if fails.
|
||||
* Returns NO_ERROR for success and CdmResponseType error code if fails.
|
||||
*/
|
||||
CdmResponseType CdmEngine::HandleProvisioningResponse(
|
||||
CdmProvisioningResponse& response, std::string* cert,
|
||||
std::string* wrapped_key) {
|
||||
const std::string& origin, const CdmProvisioningResponse& response,
|
||||
std::string* cert, std::string* wrapped_key) {
|
||||
if (response.empty()) {
|
||||
LOGE("CdmEngine::HandleProvisioningResponse: Empty provisioning response.");
|
||||
return UNKNOWN_ERROR;
|
||||
cert_provisioning_.reset(NULL);
|
||||
return EMPTY_PROVISIONING_RESPONSE;
|
||||
}
|
||||
if (NULL == cert) {
|
||||
LOGE(
|
||||
"CdmEngine::HandleProvisioningResponse: invalid certificate "
|
||||
"destination");
|
||||
return UNKNOWN_ERROR;
|
||||
cert_provisioning_.reset(NULL);
|
||||
return INVALID_PROVISIONING_PARAMETERS_1;
|
||||
}
|
||||
if (NULL == wrapped_key) {
|
||||
LOGE(
|
||||
"CdmEngine::HandleProvisioningResponse: invalid wrapped key "
|
||||
"destination");
|
||||
return UNKNOWN_ERROR;
|
||||
LOGE("CdmEngine::HandleProvisioningResponse: invalid wrapped key "
|
||||
"destination");
|
||||
cert_provisioning_.reset(NULL);
|
||||
return INVALID_PROVISIONING_PARAMETERS_2;
|
||||
}
|
||||
return cert_provisioning_.HandleProvisioningResponse(response, cert,
|
||||
wrapped_key);
|
||||
if (NULL == cert_provisioning_.get()) {
|
||||
LOGE("CdmEngine::HandleProvisioningResponse: provisioning object missing.");
|
||||
return EMPTY_PROVISIONING_CERTIFICATE;
|
||||
}
|
||||
CdmResponseType ret = cert_provisioning_->HandleProvisioningResponse(
|
||||
origin, response, cert, wrapped_key);
|
||||
cert_provisioning_.reset(NULL); // Release resources.
|
||||
return ret;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
|
||||
bool CdmEngine::IsProvisioned(CdmSecurityLevel security_level,
|
||||
const std::string& origin) {
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(security_level)) {
|
||||
LOGE("CdmEngine::IsProvisioned: unable to initialize device files");
|
||||
return false;
|
||||
}
|
||||
return handle.HasCertificate(origin);
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level,
|
||||
const std::string& origin) {
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(security_level)) {
|
||||
LOGE("CdmEngine::Unprovision: unable to initialize device files");
|
||||
return UNKNOWN_ERROR;
|
||||
return UNPROVISION_ERROR_1;
|
||||
}
|
||||
|
||||
if (!handle.DeleteAllFiles()) {
|
||||
LOGE("CdmEngine::Unprovision: unable to delete files");
|
||||
return UNKNOWN_ERROR;
|
||||
if (origin != EMPTY_ORIGIN) {
|
||||
if (!handle.RemoveCertificate(origin)) {
|
||||
LOGE("CdmEngine::Unprovision: unable to delete certificate for origin %s",
|
||||
origin.c_str());
|
||||
return UNPROVISION_ERROR_2;
|
||||
}
|
||||
return NO_ERROR;
|
||||
} else {
|
||||
if (!handle.DeleteAllFiles()) {
|
||||
LOGE("CdmEngine::Unprovision: unable to delete files");
|
||||
return UNPROVISION_ERROR_3;
|
||||
}
|
||||
|
||||
scoped_ptr<CryptoSession> crypto_session(new CryptoSession());
|
||||
CdmResponseType status = crypto_session->Open(
|
||||
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("CdmEngine::Unprovision: error opening crypto session: %d", status);
|
||||
return UNPROVISION_ERROR_4;
|
||||
}
|
||||
status = crypto_session->DeleteAllUsageReports();
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("CdmEngine::Unprovision: error deleteing usage reports: %d", status);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GetUsageInfo(CdmUsageInfo* usage_info) {
|
||||
usage_session_.reset(new CdmSession(NULL));
|
||||
CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
const CdmSecureStopId& ssid,
|
||||
CdmUsageInfo* usage_info) {
|
||||
if (NULL == usage_property_set_.get()) {
|
||||
usage_property_set_.reset(new UsagePropertySet());
|
||||
}
|
||||
usage_property_set_->set_security_level(kLevelDefault);
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
usage_session_.reset(
|
||||
new CdmSession(usage_property_set_.get(), EMPTY_ORIGIN, NULL, NULL));
|
||||
CdmResponseType status = usage_session_->Init();
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: session init error");
|
||||
return status;
|
||||
}
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(usage_session_->GetSecurityLevel())) {
|
||||
LOGE("CdmEngine::GetUsageInfo: device file init error");
|
||||
return GET_USAGE_INFO_ERROR_1;
|
||||
}
|
||||
|
||||
CdmKeyMessage license_request;
|
||||
CdmKeyResponse license_response;
|
||||
if (!handle.RetrieveUsageInfo(app_id, ssid, &license_request,
|
||||
&license_response)) {
|
||||
usage_property_set_->set_security_level(kLevel3);
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
usage_session_.reset(
|
||||
new CdmSession(usage_property_set_.get(), EMPTY_ORIGIN, NULL, NULL));
|
||||
status = usage_session_->Init();
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: session init error");
|
||||
return status;
|
||||
}
|
||||
if (!handle.Reset(usage_session_->GetSecurityLevel())) {
|
||||
LOGE("CdmEngine::GetUsageInfo: device file init error");
|
||||
return GET_USAGE_INFO_ERROR_2;
|
||||
}
|
||||
if (!handle.RetrieveUsageInfo(app_id, ssid, &license_request,
|
||||
&license_response)) {
|
||||
// No entry found for that ssid.
|
||||
return USAGE_INFO_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
std::string server_url;
|
||||
usage_info->resize(1);
|
||||
status =
|
||||
usage_session_->RestoreUsageSession(license_request, license_response);
|
||||
if (KEY_ADDED != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: restore usage session error %d", status);
|
||||
usage_info->clear();
|
||||
return status;
|
||||
}
|
||||
|
||||
status =
|
||||
usage_session_->GenerateReleaseRequest(&(*usage_info)[0], &server_url);
|
||||
|
||||
if (KEY_MESSAGE != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: generate release request error: %d", status);
|
||||
usage_info->clear();
|
||||
return status;
|
||||
}
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
CdmUsageInfo* usage_info) {
|
||||
// Return a random usage report from a random security level
|
||||
SecurityLevel security_level = ((rand() % 2) == 0) ? kLevelDefault : kLevel3;
|
||||
CdmResponseType status = UNKNOWN_ERROR;
|
||||
do {
|
||||
status = GetUsageInfo(app_id, security_level, usage_info);
|
||||
|
||||
if (KEY_MESSAGE == status && !usage_info->empty()) return status;
|
||||
} while (KEY_CANCELED == status);
|
||||
|
||||
security_level = (kLevel3 == security_level) ? kLevelDefault : kLevel3;
|
||||
do {
|
||||
status = GetUsageInfo(app_id, security_level, usage_info);
|
||||
if (NEED_PROVISIONING == status)
|
||||
return NO_ERROR; // Valid scenario that one of the security
|
||||
// levels has not been provisioned
|
||||
} while (KEY_CANCELED == status);
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
SecurityLevel requested_security_level,
|
||||
CdmUsageInfo* usage_info) {
|
||||
if (NULL == usage_property_set_.get()) {
|
||||
usage_property_set_.reset(new UsagePropertySet());
|
||||
}
|
||||
usage_property_set_->set_security_level(requested_security_level);
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
|
||||
usage_session_.reset(
|
||||
new CdmSession(usage_property_set_.get(), EMPTY_ORIGIN, NULL, NULL));
|
||||
|
||||
CdmResponseType status = usage_session_->Init();
|
||||
if (NO_ERROR != status) {
|
||||
@@ -513,13 +768,13 @@ CdmResponseType CdmEngine::GetUsageInfo(CdmUsageInfo* usage_info) {
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(usage_session_->GetSecurityLevel())) {
|
||||
LOGE("CdmEngine::GetUsageInfo: unable to initialize device files");
|
||||
return status;
|
||||
return GET_USAGE_INFO_ERROR_3;
|
||||
}
|
||||
|
||||
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> > license_info;
|
||||
if (!handle.RetrieveUsageInfo(&license_info)) {
|
||||
if (!handle.RetrieveUsageInfo(app_id, &license_info)) {
|
||||
LOGE("CdmEngine::GetUsageInfo: unable to read usage information");
|
||||
return UNKNOWN_ERROR;
|
||||
return GET_USAGE_INFO_ERROR_4;
|
||||
}
|
||||
|
||||
if (0 == license_info.size()) {
|
||||
@@ -543,25 +798,59 @@ CdmResponseType CdmEngine::GetUsageInfo(CdmUsageInfo* usage_info) {
|
||||
status =
|
||||
usage_session_->GenerateReleaseRequest(&(*usage_info)[0], &server_url);
|
||||
|
||||
if (KEY_MESSAGE != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: generate release request error: %ld",
|
||||
status);
|
||||
usage_info->clear();
|
||||
return status;
|
||||
switch (status) {
|
||||
case KEY_MESSAGE:
|
||||
break;
|
||||
case KEY_CANCELED: // usage information not present in
|
||||
usage_session_->DeleteLicense(); // OEMCrypto, delete and try again
|
||||
usage_info->clear();
|
||||
break;
|
||||
default:
|
||||
LOGE("CdmEngine::GetUsageInfo: generate release request error: %d",
|
||||
status);
|
||||
usage_info->clear();
|
||||
break;
|
||||
}
|
||||
return KEY_MESSAGE;
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
|
||||
CdmResponseType status = NO_ERROR;
|
||||
for (int j = kSecurityLevelL1; j < kSecurityLevelUnknown; ++j) {
|
||||
DeviceFiles handle;
|
||||
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 {
|
||||
CdmResponseType status2 = usage_session_->
|
||||
DeleteMultipleUsageInformation(provider_session_tokens);
|
||||
if (status2 != NO_ERROR) {
|
||||
status = status2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to initialize L%d device"
|
||||
"files", j);
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_2;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ReleaseUsageInfo(
|
||||
const CdmUsageInfoReleaseMessage& message) {
|
||||
if (NULL == usage_session_.get()) {
|
||||
LOGE("CdmEngine::ReleaseUsageInfo: cdm session not initialized");
|
||||
return UNKNOWN_ERROR;
|
||||
return RELEASE_USAGE_INFO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType status = usage_session_->ReleaseKey(message);
|
||||
usage_session_.reset(NULL);
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("CdmEngine::ReleaseUsageInfo: release key error: %ld", status);
|
||||
LOGE("CdmEngine::ReleaseUsageInfo: release key error: %d", status);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -570,25 +859,26 @@ CdmResponseType CdmEngine::Decrypt(const CdmSessionId& session_id,
|
||||
const CdmDecryptionParameters& parameters) {
|
||||
if (parameters.key_id == NULL) {
|
||||
LOGE("CdmEngine::Decrypt: no key_id");
|
||||
return KEY_ERROR;
|
||||
return INVALID_DECRYPT_PARAMETERS_ENG_1;
|
||||
}
|
||||
|
||||
if (parameters.encrypt_buffer == NULL) {
|
||||
LOGE("CdmEngine::Decrypt: no src encrypt buffer");
|
||||
return KEY_ERROR;
|
||||
return INVALID_DECRYPT_PARAMETERS_ENG_2;
|
||||
}
|
||||
|
||||
if (parameters.iv == NULL) {
|
||||
LOGE("CdmEngine::Decrypt: no iv");
|
||||
return KEY_ERROR;
|
||||
return INVALID_DECRYPT_PARAMETERS_ENG_3;
|
||||
}
|
||||
|
||||
if (parameters.decrypt_buffer == NULL) {
|
||||
if (!parameters.is_secure &&
|
||||
!Properties::Properties::oem_crypto_use_fifo()) {
|
||||
LOGE("CdmEngine::Decrypt: no dest decrypt buffer");
|
||||
return KEY_ERROR;
|
||||
} // else we must be level 1 direct and we don't need to return a buffer.
|
||||
return INVALID_DECRYPT_PARAMETERS_ENG_4;
|
||||
}
|
||||
// else we must be level 1 direct and we don't need to return a buffer.
|
||||
}
|
||||
|
||||
CdmSessionMap::iterator iter;
|
||||
@@ -605,7 +895,7 @@ CdmResponseType CdmEngine::Decrypt(const CdmSessionId& session_id,
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::Decrypt: session not found: id=%s, id size=%d",
|
||||
session_id.c_str(), session_id.size());
|
||||
return KEY_ERROR;
|
||||
return SESSION_NOT_FOUND_FOR_DECRYPT;
|
||||
}
|
||||
|
||||
return iter->second->Decrypt(parameters);
|
||||
@@ -650,24 +940,12 @@ bool CdmEngine::FindSessionForKey(const KeyId& key_id,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CdmEngine::AttachEventListener(const CdmSessionId& session_id,
|
||||
WvCdmEventListener* listener) {
|
||||
void CdmEngine::NotifyResolution(const CdmSessionId& session_id, uint32_t width,
|
||||
uint32_t height) {
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
return false;
|
||||
if (iter != sessions_.end()) {
|
||||
iter->second->NotifyResolution(width, height);
|
||||
}
|
||||
|
||||
return iter->second->AttachEventListener(listener);
|
||||
}
|
||||
|
||||
bool CdmEngine::DetachEventListener(const CdmSessionId& session_id,
|
||||
WvCdmEventListener* listener) {
|
||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return iter->second->DetachEventListener(listener);
|
||||
}
|
||||
|
||||
bool CdmEngine::ValidateKeySystem(const CdmKeySystem& key_system) {
|
||||
@@ -677,37 +955,73 @@ bool CdmEngine::ValidateKeySystem(const CdmKeySystem& key_system) {
|
||||
void CdmEngine::OnTimerEvent() {
|
||||
Clock clock;
|
||||
uint64_t current_time = clock.GetCurrentTime();
|
||||
bool update_usage_information = false;
|
||||
bool usage_update_period_expired = false;
|
||||
|
||||
if (current_time - last_usage_information_update_time >
|
||||
if (current_time - last_usage_information_update_time_ >
|
||||
kUpdateUsageInformationPeriod) {
|
||||
update_usage_information = true;
|
||||
last_usage_information_update_time = current_time;
|
||||
usage_update_period_expired = true;
|
||||
last_usage_information_update_time_ = current_time;
|
||||
}
|
||||
|
||||
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) {
|
||||
iter->second->OnTimerEvent();
|
||||
is_initial_usage_update =
|
||||
is_initial_usage_update || iter->second->is_initial_usage_update();
|
||||
is_usage_update_needed =
|
||||
is_usage_update_needed || iter->second->is_usage_update_needed();
|
||||
|
||||
if (update_usage_information && iter->second->is_usage_update_needed()) {
|
||||
// usage is updated for all sessions so this needs to be
|
||||
// called only once per update usage information period
|
||||
CdmResponseType status = iter->second->UpdateUsageInformation();
|
||||
if (NO_ERROR != status) {
|
||||
LOGW("Update usage information failed: %u", status);
|
||||
} else {
|
||||
update_usage_information = false;
|
||||
iter->second->OnTimerEvent(usage_update_period_expired);
|
||||
}
|
||||
|
||||
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();
|
||||
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();
|
||||
if (NO_ERROR != status) {
|
||||
LOGW("Update usage information failed: %d", status);
|
||||
} else {
|
||||
has_usage_been_updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
iter->second->reset_is_usage_update_needed();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
std::string CdmEngine::MapHdcpVersion(
|
||||
CryptoSession::HdcpCapability version) {
|
||||
switch (version) {
|
||||
case HDCP_NONE:
|
||||
return QUERY_VALUE_UNPROTECTED;
|
||||
case HDCP_V1:
|
||||
return QUERY_VALUE_HDCP_V1;
|
||||
case HDCP_V2:
|
||||
return QUERY_VALUE_HDCP_V2_0;
|
||||
case HDCP_V2_1:
|
||||
return QUERY_VALUE_HDCP_V2_1;
|
||||
case HDCP_V2_2:
|
||||
return QUERY_VALUE_HDCP_V2_2;
|
||||
case HDCP_NO_DIGITAL_OUTPUT:
|
||||
return QUERY_VALUE_DISCONNECTED;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
Reference in New Issue
Block a user