Fixes metrics collection during CdmEngine close.

This fixes a problem where a CdmEngine instance (and its sessions) could
be closed before its metrics could be collected. The change allows the
wv_content_decryption_module to extract metrics from instances about to
be closed. These are held until reported to the caller.

Test: Manually verified that collection is now occurring correctly. Also
added unit test: wv_cdm_metric_test.

This is a merge from wvgerrit/29069

Change-Id: If82bfd5cae3b72b9d14ab4741424a7ae7cc0a3a6
This commit is contained in:
Adam Stone
2017-06-16 14:00:30 -07:00
parent efad3eea21
commit 457aceb859
11 changed files with 220 additions and 34 deletions

View File

@@ -7,7 +7,6 @@
#include "initialization_data.h"
#include "license.h"
#include "log.h"
#include "metrics.pb.h"
#include "properties.h"
#include "service_certificate.h"
#include "wv_cdm_constants.h"
@@ -24,7 +23,7 @@ Lock WvContentDecryptionModule::session_sharing_id_generation_lock_;
WvContentDecryptionModule::WvContentDecryptionModule() {}
WvContentDecryptionModule::~WvContentDecryptionModule() {
DisablePolicyTimer(true);
DisablePolicyTimer(true /* Force. */);
}
bool WvContentDecryptionModule::IsSupported(const std::string& init_data_type) {
@@ -72,6 +71,7 @@ CdmResponseType WvContentDecryptionModule::OpenSession(
CdmResponseType WvContentDecryptionModule::CloseSession(
const CdmSessionId& session_id) {
LOGV("WvContentDecryptionModule::CloseSession. id: %s", session_id.c_str());
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
// TODO(rfrias): Avoid reusing the error codes from CdmEngine.
if (!cdm_engine) return SESSION_NOT_FOUND_1;
@@ -85,7 +85,9 @@ CdmResponseType WvContentDecryptionModule::CloseSession(
if (sts == NO_ERROR) {
cdm_by_session_id_.erase(session_id);
}
DisablePolicyTimer(false);
DisablePolicyTimer(false /* Do not force. */);
return sts;
}
@@ -399,21 +401,10 @@ bool WvContentDecryptionModule::IsValidServiceCertificate(
void WvContentDecryptionModule::GetSerializedMetrics(
std::string* serialized_metrics) {
drm_metrics::MetricsGroup metric_group;
{
AutoLock auto_lock(cdms_lock_);
for (auto it = cdms_.begin(); it != cdms_.end(); it++) {
metrics::EngineMetrics* engine_metrics =
it->second.cdm_engine->GetMetrics();
if (engine_metrics) {
// Serialize the metrics from the engine and any completed sessions.
// Clear the metrics from any completed sessions.
engine_metrics->Serialize(
metric_group.add_metric_sub_group(), true, true);
}
}
}
metric_group.SerializeToString(serialized_metrics);
AutoLock auto_lock(cdms_lock_);
CloseCdmsWithoutSessions();
metrics_.SerializeToString(serialized_metrics);
metrics_.Clear();
}
WvContentDecryptionModule::CdmInfo::CdmInfo()
@@ -444,6 +435,34 @@ 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_.add_metric_sub_group(),
false, // Report complete AND incomplete sessions.
true); // Clear session metrics after reporting.
} 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);
}
}
}
void WvContentDecryptionModule::EnablePolicyTimer() {
AutoLock auto_lock(policy_timer_lock_);
if (!policy_timer_.IsRunning())
@@ -451,23 +470,19 @@ void WvContentDecryptionModule::EnablePolicyTimer() {
}
void WvContentDecryptionModule::DisablePolicyTimer(bool force) {
bool has_sessions = false;
bool cdms_is_empty = false;
{
AutoLock auto_lock(cdms_lock_);
for (auto it = cdms_.begin(); it != cdms_.end();) {
if (it->second.cdm_engine->SessionSize() != 0) {
has_sessions = true;
++it;
} else {
// The CDM is no longer used for this identifier, delete it.
it = cdms_.erase(it);
}
}
CloseCdmsWithoutSessions();
cdms_is_empty = cdms_.empty();
}
AutoLock auto_lock(policy_timer_lock_);
if ((!has_sessions || force) && policy_timer_.IsRunning())
policy_timer_.Stop();
if(force || cdms_is_empty) {
if (policy_timer_.IsRunning()) {
policy_timer_.Stop();
}
}
}
void WvContentDecryptionModule::OnTimerEvent() {