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. This change contains the original change go/ag/3819203 and a fix to the deadlock that was seen on Marlin and Taimen. Bug: 73724453 Test: Updated unit tests. GTS test pass. Shaka Player, Netflix and Google Play test. Change-Id: Ib208204a1b794df9f306fa11d13a8bb6cd6889f7
This commit is contained in:
@@ -26,7 +26,8 @@ Lock WvContentDecryptionModule::session_sharing_id_generation_lock_;
|
||||
WvContentDecryptionModule::WvContentDecryptionModule() {}
|
||||
|
||||
WvContentDecryptionModule::~WvContentDecryptionModule() {
|
||||
ForceDisablePolicyTimer();
|
||||
CloseAllCdms();
|
||||
DisablePolicyTimer();
|
||||
}
|
||||
|
||||
bool WvContentDecryptionModule::IsSupported(const std::string& init_data_type) {
|
||||
@@ -77,8 +78,6 @@ CdmResponseType WvContentDecryptionModule::CloseSession(
|
||||
cdm_by_session_id_.erase(session_id);
|
||||
}
|
||||
|
||||
DisablePolicyTimer();
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
@@ -336,12 +335,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::GetMetrics. 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()
|
||||
@@ -377,32 +385,45 @@ CdmEngine* WvContentDecryptionModule::GetCdmForSessionId(
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// This method requires that the caller first acquire cdms_lock_.
|
||||
void WvContentDecryptionModule::CloseCdmsWithoutSessions() {
|
||||
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.");
|
||||
}
|
||||
void WvContentDecryptionModule::CloseAllCdms() {
|
||||
AutoLock auto_lock(cdms_lock_);
|
||||
|
||||
// The CDM is no longer used for this identifier, delete it.
|
||||
it = cdms_.erase(it);
|
||||
}
|
||||
for (auto it = cdms_.begin(); it != cdms_.end();) {
|
||||
it = cdms_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::CloseCdm(
|
||||
const CdmIdentifier& cdm_identifier) {
|
||||
// The policy timer ultimately calls OnTimerEvent (which wants to
|
||||
// acquire cdms_lock_). Therefore, we cannot acquire cdms_lock_ and then the
|
||||
// policy_timer_lock_ (via DisablePolicyTimer) at the same time.
|
||||
// Acquire the cdms_lock_ first, in its own scope.
|
||||
bool cdms_empty = false;
|
||||
{
|
||||
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;
|
||||
}
|
||||
// Remove any sessions that point to this engine.
|
||||
for (auto session_it : cdm_by_session_id_) {
|
||||
if (session_it.second == it->second.cdm_engine.get()) {
|
||||
cdm_by_session_id_.erase(session_it.first);
|
||||
}
|
||||
}
|
||||
cdms_.erase(it);
|
||||
cdms_empty = cdms_.empty();
|
||||
}
|
||||
|
||||
if (cdms_empty) {
|
||||
DisablePolicyTimer();
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void WvContentDecryptionModule::EnablePolicyTimer() {
|
||||
AutoLock auto_lock(policy_timer_lock_);
|
||||
if (!policy_timer_.IsRunning())
|
||||
@@ -410,27 +431,6 @@ void WvContentDecryptionModule::EnablePolicyTimer() {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WvContentDecryptionModule::ForceDisablePolicyTimer() {
|
||||
{
|
||||
AutoLock auto_lock(cdms_lock_);
|
||||
CloseCdmsWithoutSessions();
|
||||
}
|
||||
|
||||
AutoLock auto_lock(policy_timer_lock_);
|
||||
if (policy_timer_.IsRunning()) {
|
||||
policy_timer_.Stop();
|
||||
|
||||
Reference in New Issue
Block a user