Migration from jb-mr2 to master for Widevine CDM

Android development of the widevine CDM has been done
on the jb-mr2 branch of the cdm code base.  This CL
contains a merge of that jb-mr2 work to CDM master, and
also reflects the evolution of the common Modular DRM
code base since jb-mr2 branched.

Change-Id: I1d7e1a12d092c00044a4298261146cb97808d4ef
This commit is contained in:
Jeff Tinker
2013-07-29 17:29:07 -07:00
parent edb987db07
commit 0190f99fb3
68 changed files with 4754 additions and 3601 deletions

View File

@@ -7,42 +7,22 @@
#include "buffer_reader.h"
#include "cdm_session.h"
#include "clock.h"
#include "crypto_engine.h"
#include "device_files.h"
#include "license_protocol.pb.h"
#include "log.h"
#include "properties.h"
#include "scoped_ptr.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
#include "wv_cdm_event_listener.h"
#ifndef CDM_POLICY_TIMER_DURATION_SECONDS
#define CDM_POLICY_TIMER_DURATION_SECONDS 1
#endif
namespace {
const std::string kDefaultProvisioningServerUrl =
"https://www.googleapis.com/"
"certificateprovisioning/v1/devicecertificates/create"
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
const int kCdmPolicyTimerDurationSeconds = 1;
}
namespace wvcdm {
// Protobuf generated classes.
using video_widevine_server::sdk::ClientIdentification;
using video_widevine_server::sdk::ProvisioningRequest;
using video_widevine_server::sdk::ProvisioningResponse;
using video_widevine_server::sdk::SignedProvisioningMessage;
typedef std::map<CdmSessionId, CdmSession*>::const_iterator CdmSessionIter;
typedef std::map<CdmKeySetId, CdmSessionId>::iterator CdmReleaseKeySetIter;
CdmEngine::CdmEngine() : provisioning_session_(NULL) {
CdmEngine::CdmEngine() {
Properties::Init();
Clock clock;
srand(static_cast<int>(clock.GetCurrentTime() & 0xFFFFFFFF));
}
CdmEngine::~CdmEngine() {
@@ -69,28 +49,21 @@ CdmResponseType CdmEngine::OpenSession(
return KEY_ERROR;
}
CdmSession* new_session = new CdmSession();
if (!new_session) {
LOGE("CdmEngine::OpenSession: session creation failed");
return KEY_ERROR;
}
scoped_ptr<CdmSession> new_session(new CdmSession());
CdmSessionId new_session_id = new_session->session_id();
if (new_session_id.empty()) {
if (new_session->session_id().empty()) {
LOGE("CdmEngine::OpenSession: failure to generate session ID");
delete(new_session);
return UNKNOWN_ERROR;
}
CdmResponseType sts = new_session->Init();
if (sts != NO_ERROR) {
delete(new_session);
LOGE("CdmEngine::OpenSession: bad session init");
return sts;
}
sessions_[new_session_id] = new_session;
*session_id = new_session_id;
*session_id = new_session->session_id();
sessions_[*session_id] = new_session.release();
return NO_ERROR;
}
@@ -98,7 +71,7 @@ CdmResponseType CdmEngine::OpenKeySetSession(const CdmKeySetId& key_set_id) {
LOGI("CdmEngine::OpenKeySetSession");
if (key_set_id.empty()) {
LOGI("CdmEngine::OpenKeySetSession: invalid key set id");
LOGE("CdmEngine::OpenKeySetSession: invalid key set id");
return KEY_ERROR;
}
@@ -115,24 +88,22 @@ CdmResponseType CdmEngine::OpenKeySetSession(const CdmKeySetId& key_set_id) {
CdmResponseType CdmEngine::CloseSession(const CdmSessionId& session_id) {
LOGI("CdmEngine::CloseSession");
CdmSessionIter iter = sessions_.find(session_id);
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;
}
sessions_.erase(session_id);
if (sessions_.size() == 0)
DisablePolicyTimer();
iter->second->DestroySession();
delete iter->second;
sessions_.erase(session_id);
DisablePolicyTimer();
return NO_ERROR;
}
CdmResponseType CdmEngine::CloseKeySetSession(const CdmKeySetId& key_set_id) {
LOGI("CdmEngine::CloseKeySetSession");
CdmReleaseKeySetIter iter = release_key_sets_.find(key_set_id);
CdmReleaseKeySetMap::iterator iter = release_key_sets_.find(key_set_id);
if (iter == release_key_sets_.end()) {
LOGE("CdmEngine::CloseKeySetSession: key set id not found = %s",
key_set_id.c_str());
@@ -169,7 +140,7 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
return UNKNOWN_ERROR;
}
CdmReleaseKeySetIter iter = release_key_sets_.find(key_set_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());
@@ -179,7 +150,7 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
id = iter->second;
}
CdmSessionIter iter = sessions_.find(id);
CdmSessionMap::iterator iter = sessions_.find(id);
if (iter == sessions_.end()) {
LOGE("CdmEngine::GenerateKeyRequest: session_id not found = %s",
id.c_str());
@@ -222,28 +193,33 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
CdmResponseType CdmEngine::AddKey(
const CdmSessionId& session_id,
const CdmKeyResponse& key_data,
CdmKeySetId& key_set_id) {
CdmKeySetId* key_set_id) {
LOGI("CdmEngine::AddKey");
CdmSessionId id = session_id;
bool license_type_release = session_id.empty();
if (license_type_release) {
if (key_set_id.empty()) {
LOGI("CdmEngine::AddKey: invalid key set id");
if (!key_set_id) {
LOGE("CdmEngine::AddKey: no key set id provided");
return KEY_ERROR;
}
CdmReleaseKeySetIter iter = release_key_sets_.find(key_set_id);
if (key_set_id->empty()) {
LOGE("CdmEngine::AddKey: invalid key set id");
return KEY_ERROR;
}
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());
LOGE("CdmEngine::AddKey: key set id not found = %s", key_set_id->c_str());
return KEY_ERROR;
}
id = iter->second;
}
CdmSessionIter iter = sessions_.find(id);
CdmSessionMap::iterator iter = sessions_.find(id);
if (iter == sessions_.end()) {
LOGE("CdmEngine::AddKey: session id not found = %s", id.c_str());
@@ -255,7 +231,7 @@ CdmResponseType CdmEngine::AddKey(
return KEY_ERROR;
}
CdmResponseType sts = iter->second->AddKey(key_data, &key_set_id);
CdmResponseType sts = iter->second->AddKey(key_data, key_set_id);
if (KEY_ADDED != sts) {
LOGE("CdmEngine::AddKey: keys not added, result = %d", (int)sts);
@@ -279,7 +255,7 @@ CdmResponseType CdmEngine::RestoreKey(
return KEY_ERROR;
}
CdmSessionIter iter = sessions_.find(session_id);
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
LOGE("CdmEngine::RestoreKey: session_id not found = %s ",
session_id.c_str());
@@ -298,13 +274,15 @@ CdmResponseType CdmEngine::CancelKeyRequest(const CdmSessionId& session_id) {
// active sessions. Sessions are currently not being destroyed here. We can
// add this logic once the semantics of canceling the key is worked out.
CdmSessionIter iter = sessions_.find(session_id);
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
LOGE("CdmEngine::CancelKeyRequest: session_id not found = %s", session_id.c_str());
return KEY_ERROR;
}
// TODO(edwinwong, rfrias): unload keys here
delete iter->second;
sessions_.erase(session_id);
DisablePolicyTimer();
return NO_ERROR;
}
@@ -315,7 +293,7 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
std::string* server_url) {
LOGI("CdmEngine::GenerateRenewalRequest");
CdmSessionIter iter = sessions_.find(session_id);
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
LOGE("CdmEngine::GenerateRenewalRequest: session_id not found = %s", session_id.c_str());
return KEY_ERROR;
@@ -345,7 +323,7 @@ CdmResponseType CdmEngine::RenewKey(
const CdmKeyResponse& key_data) {
LOGI("CdmEngine::RenewKey");
CdmSessionIter iter = sessions_.find(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;
@@ -367,22 +345,19 @@ CdmResponseType CdmEngine::RenewKey(
CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) {
LOGI("CdmEngine::QueryStatus");
CryptoEngine* crypto_engine = CryptoEngine::GetInstance();
if (!crypto_engine) {
return KEY_ERROR;
}
switch (crypto_engine->GetSecurityLevel()) {
case CryptoEngine::kSecurityLevelL1:
CryptoSession crypto_session;
switch (crypto_session.GetSecurityLevel()) {
case CryptoSession::kSecurityLevelL1:
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1;
break;
case CryptoEngine::kSecurityLevelL2:
case CryptoSession::kSecurityLevelL2:
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L2;
break;
case CryptoEngine::kSecurityLevelL3:
case CryptoSession::kSecurityLevelL3:
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
break;
case CryptoEngine::kSecurityLevelUnknown:
case CryptoSession::kSecurityLevelUninitialized:
case CryptoSession::kSecurityLevelUnknown:
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_Unknown;
break;
default:
@@ -390,13 +365,13 @@ CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) {
}
std::string deviceId;
bool success = crypto_engine->GetDeviceUniqueId(&deviceId);
bool success = crypto_session.GetDeviceUniqueId(&deviceId);
if (success) {
(*key_info)[QUERY_KEY_DEVICE_ID] = deviceId;
}
uint32_t system_id;
success = crypto_engine->GetSystemId(&system_id);
success = crypto_session.GetSystemId(&system_id);
if (success) {
std::ostringstream system_id_stream;
system_id_stream << system_id;
@@ -404,7 +379,7 @@ CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) {
}
std::string provisioning_id;
success = crypto_engine->GetProvisioningId(&provisioning_id);
success = crypto_session.GetProvisioningId(&provisioning_id);
if (success) {
(*key_info)[QUERY_KEY_PROVISIONING_ID] = provisioning_id;
}
@@ -416,7 +391,7 @@ CdmResponseType CdmEngine::QueryKeyStatus(
const CdmSessionId& session_id,
CdmQueryMap* key_info) {
LOGI("CdmEngine::QueryKeyStatus");
CdmSessionIter iter = sessions_.find(session_id);
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
LOGE("CdmEngine::QueryKeyStatus: session_id not found = %s", session_id.c_str());
return KEY_ERROR;
@@ -428,7 +403,7 @@ CdmResponseType CdmEngine::QueryKeyControlInfo(
const CdmSessionId& session_id,
CdmQueryMap* key_info) {
LOGI("CdmEngine::QueryKeyControlInfo");
CdmSessionIter iter = sessions_.find(session_id);
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
LOGE("CdmEngine::QueryKeyControlInfo: session_id not found = %s", session_id.c_str());
return KEY_ERROR;
@@ -436,63 +411,6 @@ CdmResponseType CdmEngine::QueryKeyControlInfo(
return iter->second->QueryKeyControlInfo(key_info);
}
/*
* The certificate provisioning process creates a cdm and a crypto session.
* The lives of these sessions are short and therefore, not added to the
* CdmSessionMap. We need to explicitly delete these objects when error occurs
* or when we are done with provisioning.
*/
void CdmEngine::CleanupProvisioningSession() {
if (provisioning_session_) {
CryptoEngine* crypto_engine = CryptoEngine::GetInstance();
if (crypto_engine) {
CdmSessionId cdm_session_id = provisioning_session_->session_id();
CryptoSession* crypto_session =
crypto_engine->FindSession(cdm_session_id);
if (crypto_session) {
LOGV("delete crypto session for id=%s", cdm_session_id.c_str());
delete crypto_session;
} else {
LOGE("CleanupProvisioningSession: cannot find crypto_session");
}
}
delete provisioning_session_;
provisioning_session_ = NULL;
}
}
/*
* This function converts SignedProvisioningRequest into base64 string.
* It then wraps it in JSON format expected by the Apiary frontend.
* Apiary requires the base64 encoding to replace '+' with minus '-',
* and '/' with underscore '_'; opposite to stubby's.
*
* Returns the JSON formated string in *request. The JSON string will be
* appended as a query parameter, i.e. signedRequest=<base 64 encoded
* SignedProvisioningRequest>. All base64 '=' padding chars must be removed.
*
* The JSON formated request takes the following format:
*
* base64 encoded message
*/
void CdmEngine::ComposeJsonRequestAsQueryString(
const std::string& message,
CdmProvisioningRequest* request) {
// performs base64 encoding for message
std::vector<uint8_t> message_vector(message.begin(), message.end());
std::string message_b64 = Base64SafeEncode(message_vector);
// removes trailing '=' padding characters;
// the encoded string can have at most 2 '=' padding chars, so start
// searching at the end minus four characters
size_t found_pos = message_b64.find("=", message_b64.size() - 4);
if (std::string::npos != found_pos) {
message_b64.resize(found_pos);
}
request->assign(message_b64);
}
/*
* Composes a device provisioning request and output the request in JSON format
* in *request. It also returns the default url for the provisioning server
@@ -504,143 +422,10 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
CdmProvisioningRequest* request,
std::string* default_url) {
if (!request || !default_url) {
LOGE("GetProvisioningRequest: invalid input parameters");
LOGE("CdmEngine::GetProvisioningRequest: invalid input parameters");
return UNKNOWN_ERROR;
}
default_url->assign(kDefaultProvisioningServerUrl);
if (provisioning_session_) {
CleanupProvisioningSession();
}
//
//---------------------------------------------------------------------------
// This function can be called before a cdm session is created.
// First creates a cdm session, then creates a crypto session.
//
CdmSession* cdm_session = new CdmSession();
if (!cdm_session) {
LOGE("GetProvisioningRequest: fails to create a cdm session");
return UNKNOWN_ERROR;
}
if (cdm_session->session_id().empty()) {
LOGE("GetProvisioningRequest: fails to generate session ID");
delete cdm_session;
return UNKNOWN_ERROR;
}
CryptoEngine* crypto_engine = CryptoEngine::GetInstance();
if (!crypto_engine) {
LOGE("GetProvisioningRequest: fails to create a crypto engine");
delete cdm_session;
return UNKNOWN_ERROR;
}
CdmSessionId cdm_session_id = cdm_session->session_id();
CryptoSession* crypto_session = crypto_engine->CreateSession(cdm_session_id);
if (!crypto_session) {
LOGE("GetProvisioningRequest: fails to create a crypto session");
delete cdm_session;
return UNKNOWN_ERROR;
}
// TODO(edwinwong): replace this cdm session pointer with crypto session
// pointer if feasible
provisioning_session_ = cdm_session;
LOGV("provisioning session id=%s", cdm_session_id.c_str());
//
//---------------------------------------------------------------------------
// Prepares device provisioning request.
//
ProvisioningRequest provisioning_request;
ClientIdentification* client_id = provisioning_request.mutable_client_id();
client_id->set_type(ClientIdentification::KEYBOX);
std::string token;
if (!crypto_engine->GetToken(&token)) {
LOGE("GetProvisioningRequest: fails to get token");
CleanupProvisioningSession();
return UNKNOWN_ERROR;
}
client_id->set_token(token);
uint32_t nonce;
if (!crypto_session->GenerateNonce(&nonce)) {
LOGE("GetProvisioningRequest: fails to generate a nonce");
CleanupProvisioningSession();
return UNKNOWN_ERROR;
}
// The provisioning server does not convert the nonce to uint32_t, it just
// passes the binary data to the response message.
std::string the_nonce(reinterpret_cast<char*>(&nonce), sizeof(nonce));
provisioning_request.set_nonce(the_nonce);
std::string serialized_message;
provisioning_request.SerializeToString(&serialized_message);
// Derives signing and encryption keys and constructs signature.
std::string request_signature;
if (!crypto_session->PrepareRequest(serialized_message,
&request_signature, true)) {
request->clear();
CleanupProvisioningSession();
return UNKNOWN_ERROR;
}
if (request_signature.empty()) {
request->clear();
CleanupProvisioningSession();
return UNKNOWN_ERROR;
}
SignedProvisioningMessage signed_provisioning_msg;
signed_provisioning_msg.set_message(serialized_message);
signed_provisioning_msg.set_signature(request_signature);
std::string serialized_request;
signed_provisioning_msg.SerializeToString(&serialized_request);
// converts request into JSON string
ComposeJsonRequestAsQueryString(serialized_request, request);
return NO_ERROR;
}
/*
* Parses the input json_str and locates substring using start_substr and
* end_stubstr. The found base64 substring is then decoded and returns
* in *result.
*
* Returns true for success and false if fails.
*/
bool CdmEngine::ParseJsonResponse(
const CdmProvisioningResponse& json_str,
const std::string& start_substr,
const std::string& end_substr,
std::string* result) {
std::string b64_string;
size_t start = json_str.find(start_substr);
if (start == json_str.npos) {
LOGE("ParseJsonResponse: cannot find start substring");
return false;
} else {
size_t end = json_str.find(end_substr, start + start_substr.length());
if (end == json_str.npos) {
LOGE("ParseJsonResponse cannot locate end substring");
return false;
}
size_t b64_string_size = end - start - start_substr.length();
b64_string.assign(json_str, start + start_substr.length(), b64_string_size);
}
// Decodes base64 substring and returns it in *result
std::vector<uint8_t> result_vector = Base64SafeDecode(b64_string);
result->assign(result_vector.begin(), result_vector.end());
return true;
return cert_provisioning_.GetProvisioningRequest(request, default_url);
}
/*
@@ -653,103 +438,10 @@ bool CdmEngine::ParseJsonResponse(
CdmResponseType CdmEngine::HandleProvisioningResponse(
CdmProvisioningResponse& response) {
if (response.empty()) {
LOGE("Empty provisioning response.");
LOGE("CdmEngine::HandleProvisioningResponse: Empty provisioning response.");
return UNKNOWN_ERROR;
}
//---------------------------------------------------------------------------
// Extracts signed response from JSON string, decodes base64 signed response
const std::string kMessageStart = "\"signedResponse\": \"";
const std::string kMessageEnd = "\"";
std::string serialized_signed_response;
if (!ParseJsonResponse(response, kMessageStart, kMessageEnd,
&serialized_signed_response)) {
LOGE("Fails to extract signed serialized response from JSON response");
return UNKNOWN_ERROR;
}
//
//---------------------------------------------------------------------------
// Creates a crypto session using provisioning_session_.
//
if (!provisioning_session_) {
LOGE("HandleProvisioningResponse: invalid provisioning session");
return UNKNOWN_ERROR;
}
CryptoEngine* crypto_engine = CryptoEngine::GetInstance();
if (!crypto_engine) {
LOGE("HandleProvisioningResponse: fails to create a crypto engine");
return UNKNOWN_ERROR;
}
CdmSessionId cdm_session_id = provisioning_session_->session_id();
CryptoSession* crypto_session = crypto_engine->FindSession(cdm_session_id);
if (!crypto_session) {
LOGE("HandleProvisioningResponse: fails to find %s",
cdm_session_id.c_str());
return UNKNOWN_ERROR;
}
//---------------------------------------------------------------------------
// Authenticates provisioning response using D1s (server key derived from
// the provisioing request's input). Validate provisioning response and
// stores private device RSA key and certificate.
SignedProvisioningMessage signed_response;
if (!signed_response.ParseFromString(serialized_signed_response)) {
LOGE("Fails to parse signed serialized response");
CleanupProvisioningSession();
return UNKNOWN_ERROR;
}
if (!signed_response.has_signature() || !signed_response.has_message()) {
LOGE("Invalid response - signature or message not found");
CleanupProvisioningSession();
return UNKNOWN_ERROR;
}
const std::string& signed_message = signed_response.message();
ProvisioningResponse provisioning_response;
if (!provisioning_response.ParseFromString(signed_message)) {
LOGE("Fails to parse signed message");
CleanupProvisioningSession();
return UNKNOWN_ERROR;
}
if (!provisioning_response.has_device_rsa_key()) {
LOGE("Invalid response - key not found");
CleanupProvisioningSession();
return UNKNOWN_ERROR;
}
const std::string& enc_rsa_key = provisioning_response.device_rsa_key();
const std::string& nonce = provisioning_response.nonce();
const std::string& rsa_key_iv = provisioning_response.device_rsa_key_iv();
const std::string& signature = signed_response.signature();
std::string wrapped_rsa_key;
if (!crypto_session->RewrapDeviceRSAKey(signed_message,
signature,
nonce,
enc_rsa_key,
enc_rsa_key.size(),
rsa_key_iv,
&wrapped_rsa_key)) {
LOGE("HandleProvisioningResponse: RewrapDeviceRSAKey fails");
CleanupProvisioningSession();
return UNKNOWN_ERROR;
}
const std::string& device_certificate = provisioning_response.device_certificate();
DeviceFiles::StoreCertificate(device_certificate, wrapped_rsa_key);
//
//---------------------------------------------------------------------------
// Deletes cdm and crypto sessions created for provisioning.
//
CleanupProvisioningSession();
return NO_ERROR;
return cert_provisioning_.HandleProvisioningResponse(response);
}
CdmResponseType CdmEngine::GetSecureStops(
@@ -776,7 +468,7 @@ CdmResponseType CdmEngine::Decrypt(
void* decrypt_buffer,
size_t decrypt_buffer_offset,
bool is_video) {
CdmSessionIter iter = sessions_.find(session_id);
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
LOGW("CdmEngine::Decrypt: session_id not found = %s", session_id.c_str());
return KEY_ERROR;
@@ -789,7 +481,7 @@ CdmResponseType CdmEngine::Decrypt(
}
bool CdmEngine::IsKeyValid(const KeyId& key_id) {
for (CdmSessionIter iter = sessions_.begin();
for (CdmSessionMap::iterator iter = sessions_.begin();
iter != sessions_.end(); ++iter) {
if (iter->second->IsKeyValid(key_id)) {
return true;
@@ -802,7 +494,7 @@ bool CdmEngine::AttachEventListener(
const CdmSessionId& session_id,
WvCdmEventListener* listener) {
CdmSessionIter iter = sessions_.find(session_id);
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
return false;
}
@@ -814,7 +506,7 @@ bool CdmEngine::DetachEventListener(
const CdmSessionId& session_id,
WvCdmEventListener* listener) {
CdmSessionIter iter = sessions_.find(session_id);
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
return false;
}
@@ -923,28 +615,25 @@ bool CdmEngine::ExtractWidevinePssh(
}
void CdmEngine::EnablePolicyTimer() {
if (!policy_timer_.IsRunning())
policy_timer_.Start(this, CDM_POLICY_TIMER_DURATION_SECONDS);
policy_timer_.Start(this, kCdmPolicyTimerDurationSeconds);
}
void CdmEngine::DisablePolicyTimer() {
if (policy_timer_.IsRunning())
if (sessions_.size() == 0 && policy_timer_.IsRunning())
policy_timer_.Stop();
}
void CdmEngine::OnTimerEvent() {
for (CdmSessionIter iter = sessions_.begin();
for (CdmSessionMap::iterator iter = sessions_.begin();
iter != sessions_.end(); ++iter) {
iter->second->OnTimerEvent();
}
}
void CdmEngine::OnKeyReleaseEvent(CdmKeySetId key_set_id) {
void CdmEngine::OnKeyReleaseEvent(const CdmKeySetId& key_set_id) {
for (CdmSessionIter iter = sessions_.begin();
for (CdmSessionMap::iterator iter = sessions_.begin();
iter != sessions_.end(); ++iter) {
iter->second->OnKeyReleaseEvent(key_set_id);
}