Create unique cdm engines per WVDrmPlugin instance

This change creates a unique id in the cdm identifier in order to force
a one-to-one mapping between WVDrmPlugin instances and CDM Engines. This
change simplifies some assumptions. This includes ensuring that the
metrics for a given MediaDrm instance map to a given CdmEngine instance.

Bug: 73724453
Test: Updated unit tests. GTS test pass. Shaka Player, Netflix and Google Play test.
Change-Id: I7e041b6cdf3e272d067da49d25a297b4a4663f1f
This commit is contained in:
Adam Stone
2018-03-29 12:28:57 -07:00
parent 084c370db6
commit 58234a69f2
11 changed files with 339 additions and 199 deletions

View File

@@ -24,6 +24,7 @@ Lock WvContentDecryptionModule::session_sharing_id_generation_lock_;
WvContentDecryptionModule::WvContentDecryptionModule() {}
WvContentDecryptionModule::~WvContentDecryptionModule() {
CloseAllCdms();
ForceDisablePolicyTimer();
}
@@ -75,8 +76,6 @@ CdmResponseType WvContentDecryptionModule::CloseSession(
cdm_by_session_id_.erase(session_id);
}
DisablePolicyTimer();
return sts;
}
@@ -330,12 +329,21 @@ bool WvContentDecryptionModule::IsValidServiceCertificate(
return cert.has_certificate();
}
void WvContentDecryptionModule::GetSerializedMetrics(
std::string* serialized_metrics) {
CdmResponseType WvContentDecryptionModule::GetMetrics(
const CdmIdentifier& identifier, drm_metrics::WvCdmMetrics* metrics) {
if (!metrics) {
return PARAMETER_NULL;
}
AutoLock auto_lock(cdms_lock_);
CloseCdmsWithoutSessions();
metrics_group_.SerializeToString(serialized_metrics);
metrics_group_.Clear();
auto it = cdms_.find(identifier);
if (it == cdms_.end()) {
LOGE("WVContentDecryptionModule::Close. cdm_identifier not found");
// TODO(blueeyes): Add a better error.
return UNKNOWN_ERROR;
}
it->second.cdm_engine->GetMetrics()->Serialize(metrics);
return NO_ERROR;
}
WvContentDecryptionModule::CdmInfo::CdmInfo()
@@ -371,60 +379,44 @@ CdmEngine* WvContentDecryptionModule::GetCdmForSessionId(
return it->second;
}
// This method requires that the caller first acquire cdms_lock_.
void WvContentDecryptionModule::CloseCdmsWithoutSessions() {
void WvContentDecryptionModule::CloseAllCdms() {
AutoLock auto_lock(cdms_lock_);
for (auto it = cdms_.begin(); it != cdms_.end();) {
if (it->second.cdm_engine->SessionSize() != 0) {
++it;
} else {
// Retrieve the metrics from the engine and any completed
// sessions. Clear the metrics from any completed sessions.
metrics::EngineMetrics* engine_metrics =
it->second.cdm_engine->GetMetrics();
// engine_metrics should never be null.
if (engine_metrics != NULL) {
engine_metrics->Serialize(metrics_group_.add_metrics());
} else {
// Engine metrics should never be null.
LOGI(
"WvContentDecryptionModule::CloseCdmsWithoutSessions."
"engine_metrics was unexpectedly NULL.");
}
// The CDM is no longer used for this identifier, delete it.
it = cdms_.erase(it);
}
it = cdms_.erase(it);
}
}
CdmResponseType WvContentDecryptionModule::CloseCdm(
const CdmIdentifier& cdm_identifier) {
AutoLock auto_lock(cdms_lock_);
auto it = cdms_.find(cdm_identifier);
if (it == cdms_.end()) {
LOGE("WVContentDecryptionModule::Close. cdm_identifier not found");
// TODO(blueeyes): Create a better error.
return UNKNOWN_ERROR;
}
cdms_.erase(it);
DisablePolicyTimer();
return NO_ERROR;
}
void WvContentDecryptionModule::EnablePolicyTimer() {
AutoLock auto_lock(policy_timer_lock_);
if (!policy_timer_.IsRunning())
policy_timer_.Start(this, kCdmPolicyTimerDurationSeconds);
}
// This implementation assumes that the caller has already acquired the
// cdms_lock_.
void WvContentDecryptionModule::DisablePolicyTimer() {
bool cdms_is_empty = false;
{
AutoLock auto_lock(cdms_lock_);
CloseCdmsWithoutSessions();
cdms_is_empty = cdms_.empty();
}
AutoLock auto_lock(policy_timer_lock_);
if (cdms_is_empty) {
if (policy_timer_.IsRunning()) {
policy_timer_.Stop();
}
if (cdms_.empty() && policy_timer_.IsRunning()) {
policy_timer_.Stop();
}
}
void WvContentDecryptionModule::ForceDisablePolicyTimer() {
{
AutoLock auto_lock(cdms_lock_);
CloseCdmsWithoutSessions();
}
AutoLock auto_lock(policy_timer_lock_);
if (policy_timer_.IsRunning()) {
policy_timer_.Stop();