Merge changes I2618c2be,Ie8b9d8b9,I2f39f99c

* changes:
  Support GetPropertyByteArray for getting metrics.
  CDM Metrics Protocol buffer serialization.
  Refactored metrics to support pull model.
This commit is contained in:
Adam Stone
2017-06-26 20:32:10 +00:00
committed by Android (Google) Code Review
34 changed files with 1258 additions and 545 deletions

View File

@@ -79,7 +79,9 @@ include $(CLEAR_VARS)
LOCAL_MODULE := libcdm_protos
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
LOCAL_SRC_FILES := $(call all-proto-files-under, cdm/core/src)
CORE_PROTO_SRC_FILES := $(call all-proto-files-under, cdm/core/src)
METRICS_PROTO_SRC_FILES := $(call all-proto-files-under, cdm/metrics/src)
LOCAL_SRC_FILES := $(CORE_PROTO_SRC_FILES) $(METRICS_PROTO_SRC_FILES)
generated_sources_dir := $(call local-generated-sources-dir)
@@ -91,7 +93,8 @@ generated_sources_dir := $(call local-generated-sources-dir)
# with this path.
LOCAL_EXPORT_C_INCLUDE_DIRS := \
$(generated_sources_dir)/proto \
$(generated_sources_dir)/proto/$(LOCAL_PATH)/cdm/core/src
$(generated_sources_dir)/proto/$(LOCAL_PATH)/cdm/core/src \
$(generated_sources_dir)/proto/$(LOCAL_PATH)/cdm/metrics/src
include $(BUILD_STATIC_LIBRARY)

View File

@@ -39,8 +39,7 @@ LOCAL_SRC_FILES := \
$(SRC_DIR)/wv_content_decryption_module.cpp \
$(METRICS_SRC_DIR)/distribution.cpp \
$(METRICS_SRC_DIR)/event_metric.cpp \
$(METRICS_SRC_DIR)/metrics_front_end.cpp \
$(METRICS_SRC_DIR)/metrics_group.cpp \
$(METRICS_SRC_DIR)/metrics_collections.cpp \
$(METRICS_SRC_DIR)/timer_metric.cpp \

View File

@@ -12,6 +12,7 @@
#include "file_store.h"
#include "initialization_data.h"
#include "lock.h"
#include "metrics_collections.h"
#include "oemcrypto_adapter.h"
#include "scoped_ptr.h"
#include "timer_metric.h"
@@ -241,7 +242,7 @@ class CdmEngine {
// dead lock.
virtual void OnTimerEvent();
virtual metrics::MetricsGroup* GetMetrics() { return &metrics_; }
virtual metrics::EngineMetrics* GetMetrics() { return &metrics_; }
private:
// private methods
@@ -273,7 +274,7 @@ class CdmEngine {
* ensure that all data has been properly recorded in the group before
* it is published.
*/
metrics::MetricsGroup metrics_;
metrics::EngineMetrics metrics_;
metrics::TimerMetric life_span_;
CdmSessionMap sessions_;

View File

@@ -12,7 +12,7 @@
#include "file_store.h"
#include "initialization_data.h"
#include "license.h"
#include "metrics_group.h"
#include "metrics_collections.h"
#include "oemcrypto_adapter.h"
#include "policy_engine.h"
#include "scoped_ptr.h"
@@ -27,10 +27,24 @@ class UsageTableHeader;
class CdmSession {
public:
CdmSession(FileSystem* file_system);
// Creates a new instance of the CdmSession with the given |file_system|
// and |metrics| parameters. Both parameters are owned by the caller and
// must remain in scope througout the scope of the new instance.
CdmSession(FileSystem* file_system, metrics::SessionMetrics* metrics);
virtual ~CdmSession();
// Initializes this instance of CdmSession with the given property set.
// |cdm_client_property_set| MAY be null, is owned by the caller,
// and must remain in scope throughout the scope of this session.
virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set);
// Initializes this instance of CdmSession with the given parmeters.
// All parameters are owned by the caller.
// |cdm_client_property_set| is caller owned, may be null, but must be
// in scope as long as the session is in scope.
// |forced_session_id| is caller owned and may be null.
// |event_listener| is caller owned, may be null, but must be in scope
// as long as the session is in scope.
virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set,
const CdmSessionId* forced_session_id,
WvCdmEventListener* event_listener);
@@ -166,7 +180,7 @@ class CdmSession {
CdmSigningAlgorithm algorithm,
const std::string& signature);
virtual metrics::MetricsGroup* GetMetrics() { return &metrics_; }
virtual metrics::SessionMetrics* GetMetrics() { return metrics_; }
private:
friend class CdmSessionTest;
@@ -185,19 +199,13 @@ class CdmSession {
void set_file_handle(DeviceFiles* file_handle);
// instance variables
/*
* The metrics group must be the first variable declared to ensure
* that it is the last member destroyed so that no child members
* try to use a reference to it after it is destroyed. This will
* ensure that all data has been properly recorded in the group before
* it is published.
*/
metrics::MetricsGroup metrics_;
metrics::SessionMetrics* metrics_;
metrics::CryptoMetrics* crypto_metrics_;
metrics::TimerMetric life_span_;
bool initialized_;
CdmSessionId session_id_;
FileSystem* file_system_;
scoped_ptr<CdmLicense> license_parser_;
scoped_ptr<CryptoSession> crypto_session_;
scoped_ptr<PolicyEngine> policy_engine_;

View File

@@ -6,7 +6,7 @@
#include <string>
#include "crypto_session.h"
#include "metrics_group.h"
#include "metrics_collections.h"
#include "oemcrypto_adapter.h"
#include "service_certificate.h"
#include "wv_cdm_types.h"
@@ -18,7 +18,7 @@ class FileSystem;
class CertificateProvisioning {
public:
CertificateProvisioning(metrics::MetricsGroup* metrics) :
CertificateProvisioning(metrics::CryptoMetrics* metrics) :
crypto_session_(metrics),
cert_type_(kCertificateWidevine),
service_certificate_(NULL) {};

View File

@@ -9,7 +9,7 @@
#include "OEMCryptoCENC.h"
#include "lock.h"
#include "metrics_group.h"
#include "metrics_collections.h"
#include "oemcrypto_adapter.h"
#include "timer_metric.h"
#include "wv_cdm_types.h"
@@ -36,7 +36,10 @@ class CryptoSession {
bool rsa_cast;
};
CryptoSession(metrics::MetricsGroup* metrics);
// Creates an instance of CryptoSession with the given |crypto_metrics|.
// |crypto_metrics| is owned by the caller, must NOT be null, and must
// exist as long as the new CryptoSession exists.
CryptoSession(metrics::CryptoMetrics* crypto_metrics);
virtual ~CryptoSession();
virtual bool GetClientToken(std::string* client_token);
@@ -206,7 +209,7 @@ class CryptoSession {
static bool initialized_;
static int session_count_;
metrics::MetricsGroup* metrics_;
metrics::CryptoMetrics* metrics_;
metrics::TimerMetric life_span_;
bool open_;

View File

@@ -9,7 +9,7 @@
#include "device_files.h"
#include "file_store.h"
#include "lock.h"
#include "metrics_group.h"
#include "metrics_collections.h"
#include "scoped_ptr.h"
#include "wv_cdm_types.h"
@@ -66,29 +66,29 @@ class UsageTableHeader {
// should not be in use by any open CryptoSession objects when calls
// to DeleteEntry and MoveEntry are made.
CdmResponseType DeleteEntry(uint32_t usage_entry_number, DeviceFiles* handle,
metrics::MetricsGroup* metrics);
metrics::CryptoMetrics* metrics);
private:
CdmResponseType MoveEntry(uint32_t from /* usage entry number */,
const CdmUsageEntry& from_usage_entry,
uint32_t to /* usage entry number */,
DeviceFiles* handle,
metrics::MetricsGroup* metrics);
metrics::CryptoMetrics* metrics);
CdmResponseType GetEntry(uint32_t usage_entry_number, DeviceFiles* handle,
CdmUsageEntry* usage_entry);
CdmResponseType StoreEntry(uint32_t usage_entry_number, DeviceFiles* handle,
const CdmUsageEntry& usage_entry);
CdmResponseType Shrink(metrics::MetricsGroup* metrics,
CdmResponseType Shrink(metrics::CryptoMetrics* metrics,
uint32_t number_of_usage_entries_to_delete);
CdmResponseType UpgradeFromUsageTable(DeviceFiles* handle,
metrics::MetricsGroup* metrics);
metrics::CryptoMetrics* metrics);
bool UpgradeLicensesFromUsageTable(DeviceFiles* handle,
metrics::MetricsGroup* metrics);
metrics::CryptoMetrics* metrics);
bool UpgradeUsageInfoFromUsageTable(DeviceFiles* handle,
metrics::MetricsGroup* metrics);
metrics::CryptoMetrics* metrics);
virtual bool is_inited() { return is_inited_; }

View File

@@ -14,7 +14,6 @@
#include "file_store.h"
#include "license_protocol.pb.h"
#include "log.h"
#include "metrics_front_end.h"
#include "properties.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
@@ -130,7 +129,8 @@ CdmResponseType CdmEngine::OpenSession(const CdmKeySystem& key_system,
CloseExpiredReleaseSessions();
scoped_ptr<CdmSession> new_session(new CdmSession(file_system_));
scoped_ptr<CdmSession> new_session(new CdmSession(file_system_,
metrics_.AddSession()));
CdmResponseType sts = new_session->Init(property_set, forced_session_id,
event_listener);
if (sts != NO_ERROR) {
@@ -498,13 +498,13 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
const std::string& query_token,
std::string* query_response) {
LOGI("CdmEngine::QueryStatus");
CryptoSession crypto_session(&metrics_);
CryptoSession crypto_session(metrics_.GetCryptoMetrics());
if (security_level == kLevel3) {
CdmResponseType status;
M_TIME(
status = crypto_session.Open(
kLevel3),
&metrics_,
metrics_.GetCryptoMetrics(),
crypto_session_open_,
status,
kLevel3);
@@ -520,7 +520,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
CdmSecurityLevel security_level;
M_TIME(
security_level = crypto_session.GetSecurityLevel(),
&metrics_,
metrics_.GetCryptoMetrics(),
crypto_session_get_security_level_,
security_level);
switch (security_level) {
@@ -548,7 +548,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
M_TIME(
got_id = crypto_session.GetExternalDeviceUniqueId(
&deviceId),
&metrics_,
metrics_.GetCryptoMetrics(),
crypto_session_get_device_unique_id_,
got_id);
if (!got_id) {
@@ -563,7 +563,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
M_TIME(
got_id = crypto_session.GetSystemId(
&system_id),
&metrics_,
metrics_.GetCryptoMetrics(),
crypto_session_get_system_id_,
got_id,
system_id);
@@ -600,7 +600,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
M_TIME(
got_info = crypto_session.UsageInformationSupport(
&supports_usage_reporting),
&metrics_,
metrics_.GetCryptoMetrics(),
crypto_session_usage_information_support_,
got_info);
if (!got_info) {
@@ -782,7 +782,8 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
DeleteAllUsageReportsUponFactoryReset();
if (NULL == cert_provisioning_.get()) {
cert_provisioning_.reset(new CertificateProvisioning(&metrics_));
cert_provisioning_.reset(
new CertificateProvisioning(metrics_.GetCryptoMetrics()));
}
CdmResponseType ret = cert_provisioning_->GetProvisioningRequest(
cert_provisioning_requested_security_level_, cert_type, cert_authority,
@@ -824,12 +825,12 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
if (NULL == cert_provisioning_.get()) {
// Certificate provisioning object has been released. Check if a concurrent
// provisioning attempt has succeeded before declaring failure.
CryptoSession crypto_session(&metrics_);
CryptoSession crypto_session(metrics_.GetCryptoMetrics());
CdmResponseType status;
M_TIME(
status = crypto_session.Open(
cert_provisioning_requested_security_level_),
&metrics_,
metrics_.GetCryptoMetrics(),
crypto_session_open_,
status,
cert_provisioning_requested_security_level_);
@@ -842,7 +843,7 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
CdmSecurityLevel security_level;
M_TIME(
security_level = crypto_session.GetSecurityLevel(),
&metrics_,
metrics_.GetCryptoMetrics(),
crypto_session_get_security_level_,
security_level);
if (!IsProvisioned(security_level)) {
@@ -892,14 +893,14 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
return UNPROVISION_ERROR_3;
}
CryptoSession crypto_session(&metrics_);
CryptoSession crypto_session(metrics_.GetCryptoMetrics());
CdmResponseType status;
M_TIME(
status = crypto_session.Open(
security_level == kSecurityLevelL3 ?
kLevel3 :
kLevelDefault),
&metrics_,
metrics_.GetCryptoMetrics(),
crypto_session_open_,
status,
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
@@ -909,7 +910,7 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
}
M_TIME(
status = crypto_session.DeleteAllUsageReports(),
&metrics_,
metrics_.GetCryptoMetrics(),
crypto_session_delete_all_usage_reports_,
status);
if (status != NO_ERROR) {
@@ -948,7 +949,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
}
usage_property_set_->set_security_level(kLevelDefault);
usage_property_set_->set_app_id(app_id);
usage_session_.reset(new CdmSession(file_system_));
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
CdmResponseType status = usage_session_->Init(usage_property_set_.get());
if (NO_ERROR != status) {
LOGE("CdmEngine::GetUsageInfo: session init error: %d", status);
@@ -968,7 +969,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
ssid, &usage_data)) {
usage_property_set_->set_security_level(kLevel3);
usage_property_set_->set_app_id(app_id);
usage_session_.reset(new CdmSession(file_system_));
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
status = usage_session_->Init(usage_property_set_.get());
if (NO_ERROR != status) {
LOGE("CdmEngine::GetUsageInfo: session init error");
@@ -1042,7 +1043,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
usage_property_set_->set_security_level(requested_security_level);
usage_property_set_->set_app_id(app_id);
usage_session_.reset(new CdmSession(file_system_));
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
CdmResponseType status = usage_session_->Init(usage_property_set_.get());
if (NO_ERROR != status) {
@@ -1120,7 +1121,8 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
? kLevel3
: kLevelDefault;
usage_property_set_->set_security_level(security_level);
usage_session_.reset(new CdmSession(file_system_));
usage_session_.reset(
new CdmSession(file_system_, metrics_.AddSession()));
usage_session_->Init(usage_property_set_.get());
if (usage_session_->get_usage_support_type() == kUsageEntrySupport) {
@@ -1544,19 +1546,20 @@ void CdmEngine::DeleteAllUsageReportsUponFactoryReset() {
if (!file_system_->Exists(device_base_path_level1) &&
!file_system_->Exists(device_base_path_level3)) {
scoped_ptr<CryptoSession> crypto_session(new CryptoSession(&metrics_));
scoped_ptr<CryptoSession> crypto_session(
new CryptoSession(metrics_.GetCryptoMetrics()));
CdmResponseType status;
M_TIME(
status = crypto_session->Open(
cert_provisioning_requested_security_level_),
&metrics_,
metrics_.GetCryptoMetrics(),
crypto_session_open_,
status,
cert_provisioning_requested_security_level_);
if (NO_ERROR == status) {
M_TIME(
status = crypto_session->DeleteAllUsageReports(),
&metrics_,
metrics_.GetCryptoMetrics(),
crypto_session_delete_all_usage_reports_,
status);
if (NO_ERROR != status) {

View File

@@ -12,7 +12,6 @@
#include "clock.h"
#include "file_store.h"
#include "log.h"
#include "metrics_front_end.h"
#include "properties.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
@@ -25,9 +24,10 @@ const size_t kKeySetIdLength = 14;
namespace wvcdm {
CdmSession::CdmSession(FileSystem* file_system) :
CdmSession::CdmSession(FileSystem* file_system,
metrics::SessionMetrics* metrics) :
metrics_(metrics),
initialized_(false),
crypto_session_(new CryptoSession(&metrics_)),
file_handle_(new DeviceFiles(file_system)),
license_received_(false),
is_offline_(false),
@@ -44,6 +44,9 @@ CdmSession::CdmSession(FileSystem* file_system) :
usage_entry_number_(0),
mock_license_parser_in_use_(false),
mock_policy_engine_in_use_(false) {
// If metrics was not provided, then use a NULL CryptoMetrics instance, too.
crypto_metrics_ = metrics_ == NULL ? NULL : metrics_->GetCryptoMetrics();
crypto_session_.reset(new CryptoSession(crypto_metrics_));
life_span_.Start();
}
@@ -54,7 +57,10 @@ CdmSession::~CdmSession() {
}
Properties::RemoveSessionPropertySet(session_id_);
M_RECORD(&metrics_, cdm_session_life_span_, life_span_.AsMs());
if (metrics_) {
M_RECORD(metrics_, cdm_session_life_span_, life_span_.AsMs());
metrics_->SetCompleted();
}
}
CdmResponseType CdmSession::Init(
@@ -78,16 +84,15 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
}
CdmResponseType sts;
M_TIME(
sts = crypto_session_->Open(
requested_security_level_),
&metrics_,
sts = crypto_session_->Open(requested_security_level_),
crypto_metrics_,
crypto_session_open_,
sts,
requested_security_level_);
if (NO_ERROR != sts) return sts;
M_TIME(
security_level_ = crypto_session_->GetSecurityLevel(),
&metrics_,
crypto_metrics_,
crypto_session_get_security_level_,
security_level_);
if (!file_handle_->Init(security_level_)) {
@@ -121,7 +126,7 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
M_TIME(
get_client_token_sts = crypto_session_->GetClientToken(
&client_token),
&metrics_,
crypto_metrics_,
crypto_session_get_token_,
get_client_token_sts);
if (!get_client_token_sts) {
@@ -138,7 +143,7 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
M_TIME(
load_cert_sts = crypto_session_->LoadCertificatePrivateKey(
wrapped_key),
&metrics_,
crypto_metrics_,
crypto_session_load_certificate_private_key_,
load_cert_sts);
if(!load_cert_sts) {
@@ -157,6 +162,7 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
session_id_ =
Properties::AlwaysUseKeySetIds() ? key_set_id_ : GenerateSessionId();
metrics_->SetSessionId(session_id_);
if (session_id_.empty()) {
LOGE("CdmSession::Init: empty session ID");
@@ -454,7 +460,8 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
if (sts != KEY_ADDED) {
CdmResponseType sts =
usage_table_header_->DeleteEntry(usage_entry_number_,
file_handle_.get(), &metrics_);
file_handle_.get(),
crypto_metrics_);
if (sts != NO_ERROR) {
LOGW("CdmSession::AddKey: Delete usage entry failed = %d", sts);
}
@@ -687,10 +694,10 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
// it, so close and reopen session.
CdmResponseType sts;
crypto_session_->Close();
crypto_session_.reset(new CryptoSession(&metrics_));
crypto_session_.reset(new CryptoSession(crypto_metrics_));
M_TIME(
sts = crypto_session_->Open(requested_security_level_),
&metrics_,
crypto_metrics_,
crypto_session_open_,
sts,
requested_security_level_);
@@ -711,7 +718,7 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
return usage_table_header_->DeleteEntry(usage_entry_number,
file_handle_.get(),
&metrics_);
crypto_metrics_);
}
bool CdmSession::IsKeyLoaded(const KeyId& key_id) {
@@ -861,7 +868,7 @@ CdmResponseType CdmSession::DeleteMultipleUsageInformation(
M_TIME(
sts = crypto_session_->DeleteMultipleUsageInformation(
provider_session_tokens),
&metrics_,
crypto_metrics_,
crypto_session_delete_multiple_usage_information_,
sts);
return sts;
@@ -871,7 +878,7 @@ CdmResponseType CdmSession::UpdateUsageTableInformation() {
CdmResponseType sts;
M_TIME(
sts = crypto_session_->UpdateUsageInformation(),
&metrics_,
crypto_metrics_,
crypto_session_update_usage_information_,
sts);
return sts;
@@ -917,7 +924,7 @@ CdmResponseType CdmSession::GenericEncrypt(const std::string& in_buffer,
iv,
algorithm,
out_buffer),
&metrics_,
crypto_metrics_,
crypto_session_generic_encrypt_,
sts,
metrics::Pow2Bucket(in_buffer.size()),
@@ -942,7 +949,7 @@ CdmResponseType CdmSession::GenericDecrypt(const std::string& in_buffer,
iv,
algorithm,
out_buffer),
&metrics_,
crypto_metrics_,
crypto_session_generic_decrypt_,
sts,
metrics::Pow2Bucket(in_buffer.size()),
@@ -965,7 +972,7 @@ CdmResponseType CdmSession::GenericSign(const std::string& message,
key_id,
algorithm,
signature),
&metrics_,
crypto_metrics_,
crypto_session_generic_sign_,
sts,
metrics::Pow2Bucket(message.size()),
@@ -984,7 +991,7 @@ CdmResponseType CdmSession::GenericVerify(const std::string& message,
key_id,
algorithm,
signature),
&metrics_,
crypto_metrics_,
crypto_session_generic_verify_,
sts,
metrics::Pow2Bucket(message.size()),

View File

@@ -12,7 +12,6 @@
#include "crypto_key.h"
#include "log.h"
#include "metrics_front_end.h"
#include "openssl/sha.h"
#include "properties.h"
#include "pst_report.h"
@@ -45,7 +44,7 @@ uint64_t CryptoSession::request_id_index_ = 0;
UsageTableHeader* CryptoSession::usage_table_header_l1_ = NULL;
UsageTableHeader* CryptoSession::usage_table_header_l3_ = NULL;
CryptoSession::CryptoSession(metrics::MetricsGroup* metrics)
CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics)
: metrics_(metrics),
open_(false),
update_usage_table_after_close_session_(false),

View File

@@ -29,8 +29,7 @@
#include "level3.h"
#include "lock.h"
#include "log.h"
#include "metrics_front_end.h"
#include "metrics_group.h"
#include "metrics_collections.h"
#include "properties.h"
#include "wv_cdm_constants.h"
@@ -425,8 +424,12 @@ class Adapter {
* To avoid changing the function signature and function contract - declare
* a one-off metrics group to collect detailed information about how
* oemcrypto was intialized.
*
* TODO(blueeyes): Refactor this to allow Initialize to provide the
* details to the caller or to use the metrics instance provided by
* the caller.
*/
wvcdm::metrics::MetricsGroup metrics;
wvcdm::metrics::CryptoMetrics metrics;
level1_ = FunctionPointers(); // start with all null pointers.
level3_ = FunctionPointers(); // start with all null pointers.
@@ -474,7 +477,7 @@ class Adapter {
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_L1_OPEN_FAILED);
return result;
}
if (LoadLevel1(metrics)) {
if (LoadLevel1(&metrics)) {
LOGD("OEMCrypto_Initialize Level 1 success. I will use level 1.");
} else {
level1_ = FunctionPointers(); // revert to all null pointers.
@@ -485,7 +488,7 @@ class Adapter {
return result;
}
bool LoadLevel1(wvcdm::metrics::MetricsGroup& metrics) {
bool LoadLevel1(wvcdm::metrics::CryptoMetrics* metrics) {
level1_valid_ = true;
const uint32_t kMinimumVersion = 8;
const uint32_t kMaximumVersion = 13;
@@ -495,7 +498,7 @@ class Adapter {
LOOKUP_ALL(8, Terminate, OEMCrypto_Terminate);
if (!level1_valid_) {
M_RECORD(
&metrics,
metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_INVALID_L1);
@@ -505,7 +508,7 @@ class Adapter {
if (st != OEMCrypto_SUCCESS) {
LOGW("Could not initialize L1. Falling Back to L3.");
M_RECORD(
&metrics,
metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INITIALIZE_L1);
@@ -513,7 +516,7 @@ class Adapter {
}
level1_.version = level1_.APIVersion();
M_RECORD(
&metrics,
metrics,
oemcrypto_l1_api_version_,
NO_TIME,
level1_.version,
@@ -522,7 +525,7 @@ class Adapter {
LOGW("liboemcrypto.so is version %d, not %d. Falling Back to L3.",
level1_.version, kMinimumVersion);
M_RECORD(
&metrics,
metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_WRONG_L1_VERSION);
@@ -600,7 +603,7 @@ class Adapter {
// If we have a valid keybox, initialization is done. We're good.
if (OEMCrypto_SUCCESS == level1_.IsKeyboxValid()) {
M_RECORD(
&metrics,
metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_KEYBOX);
@@ -612,7 +615,7 @@ class Adapter {
if (level1_.version > 11 &&
(level1_.GetProvisioningMethod() == OEMCrypto_OEMCertificate)) {
M_RECORD(
&metrics,
metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0);
@@ -632,13 +635,13 @@ class Adapter {
LOGE("OEMCrypto uses cert as identification, but cdm does not!");
LOGE("This will not work on a production device.");
M_RECORD(
&metrics,
metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_CERTIFICATE_MIX);
} else {
M_RECORD(
&metrics,
metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_CERTIFICATE);
@@ -651,7 +654,7 @@ class Adapter {
LOGW("Bad Level 1 Keybox. Falling Back to L3.");
level1_.Terminate();
M_RECORD(
&metrics,
metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_BAD_KEYBOX);
@@ -663,7 +666,7 @@ class Adapter {
LOGW("Could not open %s. Falling Back to L3.", filename.c_str());
level1_.Terminate();
M_RECORD(
&metrics,
metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX);
@@ -677,7 +680,7 @@ class Adapter {
filename.c_str());
level1_.Terminate();
M_RECORD(
&metrics,
metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INSTALL_KEYBOX);
@@ -685,7 +688,7 @@ class Adapter {
}
LOGI("Installed keybox from %s", filename.c_str());
M_RECORD(
&metrics,
metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_INSTALLED_KEYBOX);

View File

@@ -5,7 +5,6 @@
#include "crypto_session.h"
#include "license.h"
#include "log.h"
#include "metrics_group.h"
namespace {
std::string kEmptyString;
@@ -140,7 +139,7 @@ CdmResponseType UsageTableHeader::UpdateEntry(CryptoSession* crypto_session,
CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number,
DeviceFiles* handle,
metrics::MetricsGroup* metrics) {
metrics::CryptoMetrics* metrics) {
LOGV("UsageTableHeader::DeleteEntry: Lock");
AutoLock auto_lock(usage_table_header_lock_);
if (usage_entry_number >= usage_entry_info_.size())
@@ -189,14 +188,13 @@ CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number,
number_of_entries_to_be_deleted =
usage_entry_info_.size() - swap_entry_number;
}
return Shrink(metrics, number_of_entries_to_be_deleted);
}
CdmResponseType UsageTableHeader::MoveEntry(
uint32_t from_usage_entry_number, const CdmUsageEntry& from_usage_entry,
uint32_t to_usage_entry_number, DeviceFiles* handle,
metrics::MetricsGroup* metrics) {
metrics::CryptoMetrics* metrics) {
LOGV("UsageTableHeader::MoveEntry");
// crypto_session points to an object whose scope is this method or a test
@@ -373,7 +371,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
}
CdmResponseType UsageTableHeader::Shrink(
metrics::MetricsGroup* metrics,
metrics::CryptoMetrics* metrics,
uint32_t number_of_usage_entries_to_delete) {
if (usage_entry_info_.empty()) {
LOGE("UsageTableHeader::Shrink: usage entry info table unexpectedly empty");
@@ -414,14 +412,14 @@ CdmResponseType UsageTableHeader::Shrink(
}
CdmResponseType UsageTableHeader::UpgradeFromUsageTable(
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
DeviceFiles* handle, metrics::CryptoMetrics* metrics) {
UpgradeLicensesFromUsageTable(handle, metrics);
UpgradeUsageInfoFromUsageTable(handle, metrics);
return NO_ERROR;
}
bool UsageTableHeader::UpgradeLicensesFromUsageTable(
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
DeviceFiles* handle, metrics::CryptoMetrics* metrics) {
// Fetch the key set IDs for each offline license. For each license
// * retrieve the provider session token,
// * create a new usage entry
@@ -510,7 +508,7 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable(
}
bool UsageTableHeader::UpgradeUsageInfoFromUsageTable(
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
DeviceFiles* handle, metrics::CryptoMetrics* metrics) {
// Fetch all usage files. For each file retrieve all the usage info records
// within the file. For each piece of usage information
// * create a new usage entry

View File

@@ -139,7 +139,7 @@ using ::testing::StrEq;
class CdmSessionTest : public ::testing::Test {
protected:
virtual void SetUp() {
cdm_session_.reset(new CdmSession(NULL));
cdm_session_.reset(new CdmSession(NULL, &metrics_));
// Inject testing mocks.
license_parser_ = new MockCdmLicense(cdm_session_->session_id());
cdm_session_->set_license_parser(license_parser_);
@@ -151,6 +151,13 @@ class CdmSessionTest : public ::testing::Test {
cdm_session_->set_file_handle(file_handle_);
}
virtual void TearDown() {
// Force the cdm_session_ to be deleted. This enforces a requirement that
// the CDM session metrics exist at least as long as the CDM session.
cdm_session_.reset();
}
metrics::SessionMetrics metrics_;
scoped_ptr<CdmSession> cdm_session_;
MockCdmLicense* license_parser_;
MockCryptoSession* crypto_session_;

View File

@@ -395,7 +395,7 @@ TEST_F(UsageTableHeaderTest, UpdateEntry) {
TEST_F(UsageTableHeaderTest, DeleteEntry_InvalidUsageEntryNumber) {
Init(kSecurityLevelL1, kUsageTableHeader, kUsageEntryInfoVector);
uint32_t usage_entry_number = kUsageEntryInfoVector.size();
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_NE(NO_ERROR, usage_table_header_->DeleteEntry(
usage_entry_number, device_files_, &metrics));
@@ -426,7 +426,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_CryptoSessionError) {
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -462,7 +462,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastOfflineEntry) {
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -507,7 +507,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntry) {
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop2
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -558,7 +558,7 @@ TEST_F(UsageTableHeaderTest,
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
device_files_->DeleteAllLicenses();
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
@@ -608,7 +608,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntriesAreMissing) {
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -671,7 +671,7 @@ TEST_F(UsageTableHeaderTest,
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_TRUE(device_files_->StoreLicense(
usage_entry_info_vector[usage_entry_info_vector.size() - 1].key_set_id,
@@ -739,7 +739,7 @@ TEST_F(UsageTableHeaderTest,
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
uint32_t usage_entry_number_after_deleted_entry =
usage_entry_number_to_be_deleted + 1;
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -812,7 +812,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreStorageTypeUnknown) {
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -867,7 +867,7 @@ TEST_F(UsageTableHeaderTest,
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
uint32_t last_usage_entry_number =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_TRUE(device_files_->StoreLicense(
usage_entry_info_vector[last_usage_entry_number].key_set_id,
@@ -933,7 +933,7 @@ TEST_F(UsageTableHeaderTest,
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
uint32_t last_usage_entry_number =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(*crypto_session_,
@@ -1007,7 +1007,7 @@ TEST_F(UsageTableHeaderTest,
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
uint32_t last_valid_usage_entry_number =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_TRUE(device_files_->StoreLicense(
usage_entry_info_vector[last_valid_usage_entry_number].key_set_id,
@@ -1085,7 +1085,7 @@ TEST_F(UsageTableHeaderTest,
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
uint32_t last_valid_usage_entry_number =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
.Times(2)
@@ -1157,7 +1157,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsOffline) {
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
uint32_t last_usage_entry_number =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_TRUE(device_files_->StoreLicense(
usage_entry_info_vector[last_usage_entry_number].key_set_id,
@@ -1271,7 +1271,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsSecureStop) {
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
uint32_t last_usage_entry_number =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
.Times(2)
@@ -1371,7 +1371,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreOfflineAndUnknknown) {
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
uint32_t last_valid_usage_entry_number =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_TRUE(device_files_->StoreLicense(
usage_entry_info_vector[last_valid_usage_entry_number].key_set_id,
@@ -1490,7 +1490,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreSecureStopAndUnknknown) {
usage_entry_info_vector.size() - 5; // kUsageEntryInfoSecureStop1
uint32_t last_valid_usage_entry_number =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop3
metrics::MetricsGroup metrics;
metrics::CryptoMetrics metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
.Times(2)

View File

@@ -4,22 +4,19 @@
#define CDM_AMI_ADAPTER_H_
#include <stdint.h>
#include <string>
#include <media/MediaAnalyticsItem.h>
#include "report.h"
namespace wvcdm {
class AmiAdapter : public metrics::Report {
class AmiAdapter {
public:
AmiAdapter();
AmiAdapter(int64_t parent);
~AmiAdapter();
metrics::Report* NewReport() const;
void UpdateString(const std::string& metric_id, const std::string& value);
void UpdateInt32(const std::string& metric_id, int32_t value);
void UpdateInt64(const std::string& metric_id, int64_t value);

View File

@@ -11,7 +11,6 @@
#include "cdm_identifier.h"
#include "file_store.h"
#include "lock.h"
#include "metrics_front_end.h"
#include "timer.h"
#include "wv_cdm_types.h"
@@ -126,6 +125,9 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
// Validate a passed-in service certificate
virtual bool IsValidServiceCertificate(const std::string& certificate);
// Retrieve the serialized metrics from the CDM.
virtual void GetSerializedMetrics(std::string* serialized_metrics);
private:
struct CdmInfo {
CdmInfo();
@@ -160,9 +162,6 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
// This contains weak pointers to the CDM instances contained in |cdms_|.
std::map<std::string, CdmEngine*> cdm_by_session_id_;
metrics::Report* report_root_;
metrics::MetricsFrontEnd* front_end_;
CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule);
};

View File

@@ -18,7 +18,7 @@
#include "lock.h"
#include "distribution.h"
#include "metric_publisher.h"
#include "metric_serialization.h"
namespace wvcdm {
namespace metrics {
@@ -27,11 +27,11 @@ class EventMetricTest;
// This base class provides the common defintion used by all templated
// instances of EventMetric.
class BaseEventMetric : public MetricPublisher {
class BaseEventMetric : public MetricSerializable {
public:
// Publish metric values to the MetricNotification. |subscriber| must
// Send metric values to the MetricSerializer. |serializer| must
// not be null and is owned by the caller.
virtual void Publish(MetricNotification* subscriber);
virtual void Serialize(MetricSerializer* serializer);
protected:
// Instantiates a BaseEventMetric.

View File

@@ -1,46 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// This file contains the declarations for the Metric class and related
// types.
#ifndef WVCDM_METRICS_METRIC_PUBLISHER_H_
#define WVCDM_METRICS_METRIC_PUBLISHER_H_
namespace wvcdm {
namespace metrics {
// The MetricNotification is implemented by the code that instantiates
// MetricPublisher instances. The caller provides this MetricNotification
// instance to MetricPublisher::Publish. In turn, Publish will make a call to
// UpdateMetric for each value to be published. The Metric may contain zero or
// more values to be updated.
class MetricNotification {
public:
virtual ~MetricNotification() {};
// The metric_id is the metric name, plus the metric part name, and the
// metric field name/value string. E.g.
// name: "drm/cdm/decrypt/duration"
// part: "mean"
// field name/value string: "{error_code:0&buffer_size:1024}"
// becomes: "drm/cdm/decrypt/duration/mean/{error_code:0&buffer_size:1024}".
virtual void UpdateString(const std::string& metric_id,
const std::string& value) = 0;
virtual void UpdateInt32(const std::string& metric_id, int32_t value) = 0;
virtual void UpdateInt64(const std::string& metric_id, int64_t value) = 0;
virtual void UpdateDouble(const std::string& metric_id, double value) = 0;
};
// This abstract class merely provides the definition for publishing the value
// of the metric.
class MetricPublisher {
public:
virtual ~MetricPublisher() { }
// Publish metric values to the MetricNotification. |subscriber| must
// not be null and is owned by the caller.
virtual void Publish(MetricNotification* subscriber) = 0;
};
} // namespace metrics
} // namespace wvcdm
#endif // WVCDM_METRICS_METRIC_PUBLISHER_H_

View File

@@ -0,0 +1,46 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// This file contains the declarations for the Metric class and related
// types.
#ifndef WVCDM_METRICS_METRIC_SERIALIZATION_H_
#define WVCDM_METRICS_METRIC_SERIALIZATION_H_
namespace wvcdm {
namespace metrics {
// The MetricSerializer is implemented by the code that instantiates
// MetricSerializable instances. The caller provides this MetricSerializer
// instance to MetricSerializable::Serialize. In turn, Serialize will make a
// call to Set* for each value to be Serialized. The MetricSerialiable
// implementation may set zero or more values on the MetricSerializer.
class MetricSerializer {
public:
virtual ~MetricSerializer() {};
// The metric_id is the metric name, plus the metric part name, and the
// metric field name/value string. E.g.
// name: "drm/cdm/decrypt/duration"
// part: "mean"
// field name/value string: "{error_code:0&buffer_size:1024}"
// becomes: "drm/cdm/decrypt/duration/mean/{error_code:0&buffer_size:1024}".
virtual void SetString(const std::string& metric_id,
const std::string& value) = 0;
virtual void SetInt32(const std::string& metric_id, int32_t value) = 0;
virtual void SetInt64(const std::string& metric_id, int64_t value) = 0;
virtual void SetDouble(const std::string& metric_id, double value) = 0;
};
// This abstract class merely provides the definition for serializing the value
// of the metric.
class MetricSerializable {
public:
virtual ~MetricSerializable() { }
// Serialize metric values to the MetricSerializer. |serializer| must
// not be null and is owned by the caller.
virtual void Serialize(MetricSerializer* serializer) = 0;
};
} // namespace metrics
} // namespace wvcdm
#endif // WVCDM_METRICS_METRIC_SERIALIZATION_H_

View File

@@ -1,19 +1,62 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// This file contains definitions for metrics being collected throughout the
// CDM.
#ifndef WVCDM_METRICS_METRICS_GROUP_H_
#define WVCDM_METRICS_METRICS_GROUP_H_
#include <ostream>
#include <stddef.h>
#include <stdint.h>
#include "OEMCryptoCENC.h"
#include "event_metric.h"
#include "metric_publisher.h"
#include "metrics.pb.h"
#include "OEMCryptoCENC.h"
#include "wv_cdm_types.h"
// This definition indicates that a given metric does not need timing
// stats. Example:
//
// M_RECORD(my_metrics, my_metric_name, NO_TIME);
#define NO_TIME 0
// Used to record metric timing and additional information about a specific
// event. Assumes that a microsecond timing has been provided. Example:
//
// long total_time = 0;
// long error_code = TimeSomeOperation(&total_time);
// M_RECORD(my_metrics, my_metric_name, total_time, error_code);
#define M_RECORD(GROUP, METRIC, TIME, ...) \
if ( GROUP ) { \
( GROUP ) -> METRIC . Record( TIME, ##__VA_ARGS__ ); \
}
// This definition automatically times an operation and records the time and
// additional information such as error code to the provided metric.
// Example:
//
// OEMCryptoResult sts;
// M_TIME(
// sts = OEMCrypto_Initialize(),
// my_metrics_collection,
// oemcrypto_initialize_,
// sts);
#define M_TIME(CALL, GROUP, METRIC, ...) \
if ( GROUP ) { \
wvcdm::metrics::TimerMetric timer; \
timer.Start(); \
CALL; \
( GROUP ) -> METRIC . Record(timer.AsUs(), ##__VA_ARGS__ ); \
} else { \
CALL; \
}
namespace wvcdm {
namespace metrics {
// This enum defines the conditions encountered during OEMCrypto Initialization
// in oemcrypto_adapter_dynamic.
typedef enum OEMCryptoInitializationMode {
OEMCrypto_INITIALIZED_USING_IN_APP = 0,
OEMCrypto_INITIALIZED_FORCING_L3 = 1,
@@ -33,35 +76,14 @@ typedef enum OEMCryptoInitializationMode {
OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0 = 15
} OEMCryptoInitializationMode;
/*
* The metrics group is the group of all metrics that be be recorded. They
* are kept together to allow calls to be correlated to one another.
*/
class MetricsGroup {
// This class contains metrics for Crypto Session and OEM Crypto.
class CryptoMetrics {
public:
/* CDM ENGINE */
EventMetric<CdmResponseType> cdm_engine_add_key_;
EventMetric<CdmResponseType> cdm_engine_close_session_;
EventMetric<CdmResponseType> cdm_engine_decrypt_;
EventMetric<bool> cdm_engine_find_session_for_key_;
EventMetric<CdmResponseType> cdm_engine_generate_key_request_;
EventMetric<CdmResponseType> cdm_engine_get_provisioning_request_;
EventMetric<CdmResponseType> cdm_engine_get_usage_info_;
EventMetric<CdmResponseType> cdm_engine_handle_provisioning_response_;
EventMetric<> cdm_engine_life_span_;
EventMetric<CdmResponseType> cdm_engine_open_key_set_session_;
EventMetric<CdmResponseType> cdm_engine_open_session_;
EventMetric<CdmResponseType> cdm_engine_query_key_status_;
EventMetric<CdmResponseType> cdm_engine_release_all_usage_info_;
EventMetric<CdmResponseType> cdm_engine_release_usage_info_;
EventMetric<CdmResponseType> cdm_engine_remove_keys_;
EventMetric<CdmResponseType> cdm_engine_restore_key_;
EventMetric<CdmResponseType, CdmSecurityLevel> cdm_engine_unprovision_;
/* CDM SESSION */
EventMetric<> cdm_session_life_span_;
EventMetric<CdmResponseType> cdm_session_renew_key_;
EventMetric<CdmResponseType> cdm_session_restore_offline_session_;
EventMetric<CdmResponseType> cdm_session_restore_usage_session_;
CryptoMetrics();
void Serialize(drm_metrics::MetricsGroup* metrics);
/* CRYPTO SESSION */
EventMetric<CdmResponseType> crypto_session_delete_all_usage_reports_;
EventMetric<CdmResponseType> crypto_session_delete_multiple_usage_information_;
@@ -127,14 +149,111 @@ class MetricsGroup {
/* Internal OEMCrypto Metrics */
EventMetric<OEMCryptoInitializationMode> oemcrypto_initialization_mode_;
EventMetric<uint32_t, uint32_t> oemcrypto_l1_api_version_;
};
MetricsGroup();
~MetricsGroup();
// This class contains session-scoped metrics. All properties and
// statistics related to operations within a single session are
// recorded here.
class SessionMetrics {
public:
SessionMetrics();
// Sets the session id of the metrics group. This allows the session
// id to be captured and reported as part of the collection of metrics.
void SetSessionId(const CdmSessionId& session_id) {
session_id_ = session_id; }
// Returns the session id or an empty session id if it has not been set.
const CdmSessionId& GetSessionId() const { return session_id_; }
// Marks the metrics object as completed and ready for serialization.
void SetCompleted() { completed_ = true; }
// Returns true if the object is completed. This is used to determine
// when the stats are ready to be published.
bool IsCompleted() const { return completed_; }
// Returns a pointer to the crypto metrics belonging to the engine instance.
// This instance retains ownership of the object.
CryptoMetrics* GetCryptoMetrics() { return &crypto_metrics_; }
// Serialize the session metrics to the provided |metric_group|.
// |metric_group| is owned by the caller and must not be null.
void Serialize(drm_metrics::MetricsGroup* metric_group);
// Metrics collected at the session level.
EventMetric<> cdm_session_life_span_;
EventMetric<CdmResponseType> cdm_session_renew_key_;
EventMetric<CdmResponseType> cdm_session_restore_offline_session_;
EventMetric<CdmResponseType> cdm_session_restore_usage_session_;
private:
void Publish(MetricNotification* subscriber);
void SerializeSessionMetrics(drm_metrics::MetricsGroup* metric_group);
CdmSessionId session_id_;
bool completed_;
CryptoMetrics crypto_metrics_;
};
// This class contains engine-scoped metrics. All properties and
// statistics related to operations within the engine, but outside
// the scope of a session are recorded here.
class EngineMetrics {
public:
EngineMetrics();
~EngineMetrics();
// Add a new SessionMetrics instance and return a pointer to the caller.
// The new SessionMetrics instance is owned by this EngineMetrics instance
// and will exist until RemoveSession is called or this object is deleted.
SessionMetrics* AddSession();
// Removes the metrics object for the given session id. This should only
// be called when the SessionMetrics instance is no longer in use.
void RemoveSession(CdmSessionId session_id);
// Returns a pointer to the crypto metrics belonging to the engine instance.
// The CryptoMetrics instance is still owned by this object and will exist
// until this object is deleted.
CryptoMetrics* GetCryptoMetrics() { return &crypto_metrics_; }
// Serialize engine and session metrics into a serialized MetricsGroup
// instance and output that instance to the provided |metric_group|.
// |metric_group| is owned by the caller and must NOT be null.
// |completed_only| indicates that this call should only publish
// SessionMetrics instances that are marked as completed.
// |clear_sessions| indicates that this call should clear sessions metrics
// for those sessions that were serialized. This allows atomic
// serialization and closing of session-level metrics.
void Serialize(drm_metrics::MetricsGroup* metric_group, bool completed_only,
bool clear_serialized_sessions);
// Metrics recorded at the engine level.
EventMetric<CdmResponseType> cdm_engine_add_key_;
EventMetric<CdmResponseType> cdm_engine_close_session_;
EventMetric<CdmResponseType> cdm_engine_decrypt_;
EventMetric<bool> cdm_engine_find_session_for_key_;
EventMetric<CdmResponseType> cdm_engine_generate_key_request_;
EventMetric<CdmResponseType> cdm_engine_get_provisioning_request_;
EventMetric<CdmResponseType> cdm_engine_get_usage_info_;
EventMetric<CdmResponseType> cdm_engine_handle_provisioning_response_;
EventMetric<> cdm_engine_life_span_;
EventMetric<CdmResponseType> cdm_engine_open_key_set_session_;
EventMetric<CdmResponseType> cdm_engine_open_session_;
EventMetric<CdmResponseType> cdm_engine_query_key_status_;
EventMetric<CdmResponseType> cdm_engine_release_all_usage_info_;
EventMetric<CdmResponseType> cdm_engine_release_usage_info_;
EventMetric<CdmResponseType> cdm_engine_remove_keys_;
EventMetric<CdmResponseType> cdm_engine_restore_key_;
EventMetric<CdmResponseType, CdmSecurityLevel> cdm_engine_unprovision_;
private:
Lock session_metrics_lock_;
std::vector<metrics::SessionMetrics*> session_metrics_list_;
CryptoMetrics crypto_metrics_;
void SerializeEngineMetrics(drm_metrics::MetricsGroup* out);
};
} // namespace metrics
} // namespace wvcdm
#endif

View File

@@ -1,58 +0,0 @@
// Copyright 2016 Google Inc. All Rights Reserved.
#ifndef WVCDM_METRICS_METRICS_FRONT_END_H_
#define WVCDM_METRICS_METRICS_FRONT_END_H_
#include <map>
#include "report.h"
#include "timer_metric.h" /* needed for the macro */
namespace wvcdm {
namespace metrics {
class MetricsFrontEnd {
public:
MetricsFrontEnd(Report* root);
MetricNotification* CreateSubscriber();
static MetricsFrontEnd& Instance();
static void OverrideInstance(MetricsFrontEnd* instance);
private:
static MetricsFrontEnd* instance_;
Report* root_;
/* Disallow copy and assign. */
MetricsFrontEnd(const MetricsFrontEnd&);
void operator=(const MetricsFrontEnd&);
};
} // namespace metrics
} // namespace wvcdm
#define MFE wvcdm::metrics::MetricsFrontEnd::Instance()
#define NO_TIME 0
#define M_RECORD(GROUP, METRIC, TIME, ...) \
if ( GROUP ) { \
( GROUP ) -> METRIC . Record( TIME, ##__VA_ARGS__ ); \
}
#define M_TIME(CALL, GROUP, METRIC, ...) \
if ( GROUP ) { \
wvcdm::metrics::TimerMetric timer; \
timer.Start(); \
CALL; \
( GROUP ) -> METRIC . Record(timer.AsUs(), ##__VA_ARGS__ ); \
} else { \
CALL; \
}
#endif

View File

@@ -1,29 +0,0 @@
// Copyright 2016 Google Inc. All Rights Reserved.
#ifndef WVCDM_METRICS_REPORT_H_
#define WVCDM_METRICS_REPORT_H_
#include <stdint.h>
#include "event_metric.h"
namespace wvcdm {
namespace metrics {
class Report : public MetricNotification {
public:
virtual ~Report() { }
/* Create a new report of the same type. The new report is not
* a copy of this report. The pointer is to be owned by whoever
* calls this function. */
virtual Report* NewReport() const;
};
} // metrics
} //wvcdm
#endif

View File

@@ -32,28 +32,31 @@ void BaseEventMetric::Record(const std::string& field_names_values,
distribution->Record(value);
}
void BaseEventMetric::Publish(MetricNotification* notification) {
void BaseEventMetric::Serialize(MetricSerializer* serializer) {
AutoLock lock(internal_lock_);
for (std::map<std::string, Distribution*>::iterator it
= value_map_.begin(); it != value_map_.end(); it++) {
notification->UpdateInt64(
serializer->SetInt64(
metric_name_ + "/count" + it->first,
it->second->Count());
notification->UpdateDouble(
serializer->SetDouble(
metric_name_ + "/mean" + it->first,
it->second->Mean());
notification->UpdateDouble(
// Only publish additional information if there was more than one sample.
if (it->second->Count() > 1) {
serializer->SetDouble(
metric_name_ + "/variance" + it->first,
it->second->Variance());
notification->UpdateDouble(
serializer->SetDouble(
metric_name_ + "/min" + it->first,
it->second->Min());
notification->UpdateDouble(
serializer->SetDouble(
metric_name_ + "/max" + it->first,
it->second->Max());
}
}
}
} // namespace metrics
} // namespace wvcdm

View File

@@ -0,0 +1,36 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// This file contains a proto definition for serialization of metrics data.
//
syntax = "proto2";
package drm_metrics;
// need this if we are using libprotobuf-cpp-2.3.0-lite
option optimize_for = LITE_RUNTIME;
// The MetricsGroup is a collection of metric name/value pair instances
// that can be serialized and provided to a caller.
message MetricsGroup {
message Metric {
message MetricValue {
// Only one of the following values must be set. Note that the oneof
// keyword is not supported in the protobuf version checked into the CDM.
optional int64 int_value = 1;
optional double double_value = 2;
optional string string_value = 3;
}
// The name of the metric. Must be valid UTF-8. Required.
optional string name = 1;
// The value of the metric. Required.
optional MetricValue value = 2;
}
// The list of name/value pairs of metrics.
repeated Metric metric = 1;
// Allow multiple sub groups of metrics.
repeated MetricsGroup metric_sub_group = 2;
}

View File

@@ -1,75 +1,67 @@
// Copyright 2016 Google Inc. All Rights Reserved.
#include "metrics_group.h"
#include "metrics_collections.h"
#include "metrics_front_end.h"
#include <algorithm>
#include "metrics.pb.h"
using drm_metrics::MetricsGroup;
using wvcdm::metrics::MetricSerializer;
namespace {
// Helper struct for comparing session ids.
struct CompareSessionIds {
const std::string& target_;
CompareSessionIds(const wvcdm::CdmSessionId& target) : target_(target) {};
bool operator()(const wvcdm::metrics::SessionMetrics* metrics) const {
return metrics->GetSessionId() == target_;
}
};
// Local class used to serialize to the MetricsGroup proto message.
class ProtoMetricSerializer : public wvcdm::metrics::MetricSerializer {
public:
ProtoMetricSerializer(MetricsGroup* metric_group)
: metric_group_(metric_group) {}
virtual void SetString(const std::string& metric_id,
const std::string& value) {
MetricsGroup::Metric* metric = metric_group_->add_metric();
metric->set_name(metric_id);
metric->mutable_value()->set_string_value(value);
}
virtual void SetInt32(const std::string& metric_id, int32_t value) {
MetricsGroup::Metric* metric = metric_group_->add_metric();
metric->set_name(metric_id);
metric->mutable_value()->set_int_value(value);
}
virtual void SetInt64(const std::string& metric_id, int64_t value) {
MetricsGroup::Metric* metric = metric_group_->add_metric();
metric->set_name(metric_id);
metric->mutable_value()->set_int_value(value);
}
virtual void SetDouble(const std::string& metric_id, double value) {
MetricsGroup::Metric* metric = metric_group_->add_metric();
metric->set_name(metric_id);
metric->mutable_value()->set_double_value(value);
}
private:
MetricsGroup* metric_group_;
};
} // anonymous namespace
namespace wvcdm {
namespace metrics {
MetricsGroup::MetricsGroup() :
cdm_engine_add_key_(
"/drm/widevine/cdm_engine/add_key/time",
"error"),
cdm_engine_close_session_(
"/drm/widevine/cdm_engine/close_session/time",
"error"),
cdm_engine_decrypt_(
"/drm/widevine/cdm_engine/decrypt/time",
"error"),
cdm_engine_find_session_for_key_(
"/drm/widevine/cdm_engine/find_session_for_key/time",
"success"),
cdm_engine_generate_key_request_(
"/drm/widevine/cdm_engine/generate_key_request/time",
"error"),
cdm_engine_get_provisioning_request_(
"/drm/widevine/cdm_engine/get_provisioning_request/time",
"error"),
cdm_engine_get_usage_info_(
"/drm/widevine/cdm_engine/get_usage_info/time",
"error"),
cdm_engine_handle_provisioning_response_(
"/drm/widevine/cdm_engine/handle_provisioning_response/time",
"error"),
cdm_engine_life_span_(
"/drm/widevine/cdm_engine/life_span/time"),
cdm_engine_open_key_set_session_(
"/drm/widevine/cdm_engine/open_key_set_session/time",
"error"),
cdm_engine_open_session_(
"/drm/widevine/cdm_engine/open_session/time",
"error"),
cdm_engine_query_key_status_(
"/drm/widevine/cdm_engine/query_key_status/time",
"error"),
cdm_engine_release_all_usage_info_(
"/drm/widevine/cdm_engine/release_all_usage_info/time",
"error"),
cdm_engine_release_usage_info_(
"/drm/widevine/cdm_engine/release_usage_info/time",
"error"),
cdm_engine_remove_keys_(
"/drm/widevine/cdm_engine/remove_keys/time",
"error"),
cdm_engine_restore_key_(
"/drm/widevine/cdm_engine/restore_key/time",
"error"),
cdm_engine_unprovision_(
"/drm/widevine/cdm_engine/unprovision/time",
"error",
"security_level"),
cdm_session_life_span_(
"/drm/widevine/cdm_session/life_span/time"),
cdm_session_renew_key_(
"/drm/widevine/cdm_session/renew_key/time",
"error"),
cdm_session_restore_offline_session_(
"/drm/widevine/cdm_session/restore_offline_session/time",
"error"),
cdm_session_restore_usage_session_(
"/drm/widevine/cdm_session/restore_usage_session/time",
"error"),
CryptoMetrics::CryptoMetrics() :
crypto_session_delete_all_usage_reports_(
"/drm/widevine/crypto_session/delete_all_usage_reports/time",
"error"),
@@ -289,97 +281,232 @@ MetricsGroup::MetricsGroup() :
"version",
"min_version") {}
MetricsGroup::~MetricsGroup() {
#if 0 // Disable metrics for now to work around P0:b/35093325
MetricNotification* subscriber = MFE.CreateSubscriber();
if (subscriber) {
Publish(subscriber);
}
delete subscriber;
#endif
void CryptoMetrics::Serialize(MetricsGroup* metrics) {
ProtoMetricSerializer serializer(metrics);
/* CRYPTO SESSION */
crypto_session_delete_all_usage_reports_.Serialize(&serializer);
crypto_session_delete_multiple_usage_information_.Serialize(&serializer);
crypto_session_generic_decrypt_.Serialize(&serializer);
crypto_session_generic_encrypt_.Serialize(&serializer);
crypto_session_generic_sign_.Serialize(&serializer);
crypto_session_generic_verify_.Serialize(&serializer);
crypto_session_get_device_unique_id_.Serialize(&serializer);
crypto_session_get_security_level_.Serialize(&serializer);
crypto_session_get_system_id_.Serialize(&serializer);
crypto_session_get_token_.Serialize(&serializer);
crypto_session_life_span_.Serialize(&serializer);
crypto_session_load_certificate_private_key_.Serialize(&serializer);
crypto_session_open_.Serialize(&serializer);
crypto_session_update_usage_information_.Serialize(&serializer);
crypto_session_usage_information_support_.Serialize(&serializer);
/* OEMCRYPTO */
oemcrypto_api_version_.Serialize(&serializer);
oemcrypto_close_session_.Serialize(&serializer);
oemcrypto_copy_buffer_.Serialize(&serializer);
oemcrypto_deactivate_usage_entry_.Serialize(&serializer);
oemcrypto_decrypt_cenc_.Serialize(&serializer);
oemcrypto_delete_usage_entry_.Serialize(&serializer);
oemcrypto_delete_usage_table_.Serialize(&serializer);
oemcrypto_derive_keys_from_session_key_.Serialize(&serializer);
oemcrypto_force_delete_usage_entry_.Serialize(&serializer);
oemcrypto_generate_derived_keys_.Serialize(&serializer);
oemcrypto_generate_nonce_.Serialize(&serializer);
oemcrypto_generate_rsa_signature_.Serialize(&serializer);
oemcrypto_generate_signature_.Serialize(&serializer);
oemcrypto_generic_decrypt_.Serialize(&serializer);
oemcrypto_generic_encrypt_.Serialize(&serializer);
oemcrypto_generic_sign_.Serialize(&serializer);
oemcrypto_generic_verify_.Serialize(&serializer);
oemcrypto_get_device_id_.Serialize(&serializer);
oemcrypto_get_hdcp_capability_.Serialize(&serializer);
oemcrypto_get_key_data_.Serialize(&serializer);
oemcrypto_get_max_number_of_sessions_.Serialize(&serializer);
oemcrypto_get_number_of_open_sessions_.Serialize(&serializer);
oemcrypto_get_oem_public_certificate_.Serialize(&serializer);
oemcrypto_get_provisioning_method_.Serialize(&serializer);
oemcrypto_get_random_.Serialize(&serializer);
oemcrypto_initialize_.Serialize(&serializer);
oemcrypto_install_keybox_.Serialize(&serializer);
oemcrypto_is_anti_rollback_hw_present_.Serialize(&serializer);
oemcrypto_is_keybox_valid_.Serialize(&serializer);
oemcrypto_load_device_rsa_key_.Serialize(&serializer);
oemcrypto_load_keys_.Serialize(&serializer);
oemcrypto_load_test_keybox_.Serialize(&serializer);
oemcrypto_load_test_rsa_key_.Serialize(&serializer);
oemcrypto_open_session_.Serialize(&serializer);
oemcrypto_refresh_keys_.Serialize(&serializer);
oemcrypto_report_usage_.Serialize(&serializer);
oemcrypto_rewrap_device_rsa_key_.Serialize(&serializer);
oemcrypto_rewrap_device_rsa_key_30_.Serialize(&serializer);
oemcrypto_security_level_.Serialize(&serializer);
oemcrypto_security_patch_level_.Serialize(&serializer);
oemcrypto_select_key_.Serialize(&serializer);
oemcrypto_supports_usage_table_.Serialize(&serializer);
oemcrypto_update_usage_table_.Serialize(&serializer);
oemcrypto_wrap_keybox_.Serialize(&serializer);
/* Internal OEMCrypto Metrics */
oemcrypto_initialization_mode_.Serialize(&serializer);
oemcrypto_l1_api_version_.Serialize(&serializer);
}
void MetricsGroup::Publish(MetricNotification* subscriber) {
cdm_engine_add_key_.Publish(subscriber);
cdm_engine_close_session_.Publish(subscriber);
cdm_engine_decrypt_.Publish(subscriber);
cdm_engine_find_session_for_key_.Publish(subscriber);
cdm_engine_generate_key_request_.Publish(subscriber);
cdm_engine_get_provisioning_request_.Publish(subscriber);
cdm_engine_get_usage_info_.Publish(subscriber);
cdm_engine_handle_provisioning_response_.Publish(subscriber);
cdm_engine_life_span_.Publish(subscriber);
cdm_engine_open_key_set_session_.Publish(subscriber);
cdm_engine_open_session_.Publish(subscriber);
cdm_engine_query_key_status_.Publish(subscriber);
cdm_engine_release_all_usage_info_.Publish(subscriber);
cdm_engine_release_usage_info_.Publish(subscriber);
cdm_engine_remove_keys_.Publish(subscriber);
cdm_engine_restore_key_.Publish(subscriber);
cdm_engine_unprovision_.Publish(subscriber);
cdm_session_life_span_.Publish(subscriber);
cdm_session_renew_key_.Publish(subscriber);
cdm_session_restore_offline_session_.Publish(subscriber);
cdm_session_restore_usage_session_.Publish(subscriber);
crypto_session_delete_all_usage_reports_.Publish(subscriber);
crypto_session_delete_multiple_usage_information_.Publish(subscriber);
crypto_session_generic_decrypt_.Publish(subscriber);
crypto_session_generic_sign_.Publish(subscriber);
crypto_session_generic_verify_.Publish(subscriber);
crypto_session_get_device_unique_id_.Publish(subscriber);
crypto_session_get_security_level_.Publish(subscriber);
crypto_session_get_system_id_.Publish(subscriber);
crypto_session_get_token_.Publish(subscriber);
crypto_session_life_span_.Publish(subscriber);
crypto_session_load_certificate_private_key_.Publish(subscriber);
crypto_session_open_.Publish(subscriber);
crypto_session_update_usage_information_.Publish(subscriber);
crypto_session_usage_information_support_.Publish(subscriber);
oemcrypto_api_version_.Publish(subscriber);
oemcrypto_close_session_.Publish(subscriber);
oemcrypto_copy_buffer_.Publish(subscriber);
oemcrypto_deactivate_usage_entry_.Publish(subscriber);
oemcrypto_decrypt_cenc_.Publish(subscriber);
oemcrypto_delete_usage_entry_.Publish(subscriber);
oemcrypto_delete_usage_table_.Publish(subscriber);
oemcrypto_derive_keys_from_session_key_.Publish(subscriber);
oemcrypto_force_delete_usage_entry_.Publish(subscriber);
oemcrypto_generate_derived_keys_.Publish(subscriber);
oemcrypto_generate_nonce_.Publish(subscriber);
oemcrypto_generate_rsa_signature_.Publish(subscriber);
oemcrypto_generate_signature_.Publish(subscriber);
oemcrypto_generic_decrypt_.Publish(subscriber);
oemcrypto_generic_encrypt_.Publish(subscriber);
oemcrypto_generic_sign_.Publish(subscriber);
oemcrypto_generic_verify_.Publish(subscriber);
oemcrypto_get_device_id_.Publish(subscriber);
oemcrypto_get_hdcp_capability_.Publish(subscriber);
oemcrypto_get_key_data_.Publish(subscriber);
oemcrypto_get_max_number_of_sessions_.Publish(subscriber);
oemcrypto_get_number_of_open_sessions_.Publish(subscriber);
oemcrypto_get_oem_public_certificate_.Publish(subscriber);
oemcrypto_get_provisioning_method_.Publish(subscriber);
oemcrypto_get_random_.Publish(subscriber);
oemcrypto_install_keybox_.Publish(subscriber);
oemcrypto_is_anti_rollback_hw_present_.Publish(subscriber);
oemcrypto_is_keybox_valid_.Publish(subscriber);
oemcrypto_load_device_rsa_key_.Publish(subscriber);
oemcrypto_load_keys_.Publish(subscriber);
oemcrypto_load_test_keybox_.Publish(subscriber);
oemcrypto_load_test_rsa_key_.Publish(subscriber);
oemcrypto_open_session_.Publish(subscriber);
oemcrypto_refresh_keys_.Publish(subscriber);
oemcrypto_report_usage_.Publish(subscriber);
oemcrypto_rewrap_device_rsa_key_.Publish(subscriber);
oemcrypto_rewrap_device_rsa_key_30_.Publish(subscriber);
oemcrypto_security_level_.Publish(subscriber);
oemcrypto_security_patch_level_.Publish(subscriber);
oemcrypto_select_key_.Publish(subscriber);
oemcrypto_supports_usage_table_.Publish(subscriber);
oemcrypto_update_usage_table_.Publish(subscriber);
oemcrypto_wrap_keybox_.Publish(subscriber);
oemcrypto_initialization_mode_.Publish(subscriber);
oemcrypto_l1_api_version_.Publish(subscriber);
SessionMetrics::SessionMetrics() :
cdm_session_life_span_(
"/drm/widevine/cdm_session/life_span/time"),
cdm_session_renew_key_(
"/drm/widevine/cdm_session/renew_key/time",
"error"),
cdm_session_restore_offline_session_(
"/drm/widevine/cdm_session/restore_offline_session/time",
"error"),
cdm_session_restore_usage_session_(
"/drm/widevine/cdm_session/restore_usage_session/time",
"error"),
completed_(false) {
}
void SessionMetrics::Serialize(MetricsGroup* metric_group) {
SerializeSessionMetrics(metric_group);
crypto_metrics_.Serialize(metric_group);
}
void SessionMetrics::SerializeSessionMetrics(MetricsGroup* metric_group) {
ProtoMetricSerializer serializer(metric_group);
// Add the session id as a single-valued metric.
serializer.SetString("/drm/widevine/cdm_session/session_id", session_id_);
cdm_session_life_span_.Serialize(&serializer);
cdm_session_renew_key_.Serialize(&serializer);
cdm_session_restore_offline_session_.Serialize(&serializer);
cdm_session_restore_usage_session_.Serialize(&serializer);
}
EngineMetrics::EngineMetrics() :
cdm_engine_add_key_(
"/drm/widevine/cdm_engine/add_key/time",
"error"),
cdm_engine_close_session_(
"/drm/widevine/cdm_engine/close_session/time",
"error"),
cdm_engine_decrypt_(
"/drm/widevine/cdm_engine/decrypt/time",
"error"),
cdm_engine_find_session_for_key_(
"/drm/widevine/cdm_engine/find_session_for_key/time",
"success"),
cdm_engine_generate_key_request_(
"/drm/widevine/cdm_engine/generate_key_request/time",
"error"),
cdm_engine_get_provisioning_request_(
"/drm/widevine/cdm_engine/get_provisioning_request/time",
"error"),
cdm_engine_get_usage_info_(
"/drm/widevine/cdm_engine/get_usage_info/time",
"error"),
cdm_engine_handle_provisioning_response_(
"/drm/widevine/cdm_engine/handle_provisioning_response/time",
"error"),
cdm_engine_life_span_(
"/drm/widevine/cdm_engine/life_span/time"),
cdm_engine_open_key_set_session_(
"/drm/widevine/cdm_engine/open_key_set_session/time",
"error"),
cdm_engine_open_session_(
"/drm/widevine/cdm_engine/open_session/time",
"error"),
cdm_engine_query_key_status_(
"/drm/widevine/cdm_engine/query_key_status/time",
"error"),
cdm_engine_release_all_usage_info_(
"/drm/widevine/cdm_engine/release_all_usage_info/time",
"error"),
cdm_engine_release_usage_info_(
"/drm/widevine/cdm_engine/release_usage_info/time",
"error"),
cdm_engine_remove_keys_(
"/drm/widevine/cdm_engine/remove_keys/time",
"error"),
cdm_engine_restore_key_(
"/drm/widevine/cdm_engine/restore_key/time",
"error"),
cdm_engine_unprovision_(
"/drm/widevine/cdm_engine/unprovision/time",
"error",
"security_level") {
}
EngineMetrics::~EngineMetrics() {
AutoLock kock(session_metrics_lock_);
std::vector<SessionMetrics*>::iterator i;
for (i = session_metrics_list_.begin(); i != session_metrics_list_.end();
i++) {
delete *i;
}
session_metrics_list_.clear();
}
SessionMetrics* EngineMetrics::AddSession() {
AutoLock lock(session_metrics_lock_);
SessionMetrics* metrics = new SessionMetrics();
session_metrics_list_.push_back(metrics);
return metrics;
}
void EngineMetrics::RemoveSession(wvcdm::CdmSessionId session_id) {
AutoLock lock(session_metrics_lock_);
session_metrics_list_.erase(
std::remove_if(session_metrics_list_.begin(),
session_metrics_list_.end(),
CompareSessionIds(session_id)),
session_metrics_list_.end());
}
void EngineMetrics::Serialize(drm_metrics::MetricsGroup* metric_group,
bool completed_only,
bool clear_serialized_sessions) {
AutoLock lock(session_metrics_lock_);
SerializeEngineMetrics(metric_group);
std::vector<SessionMetrics*>::iterator i;
for (i = session_metrics_list_.begin(); i != session_metrics_list_.end();
/* no increment */) {
bool serialized = false;
if (!completed_only || (*i)->IsCompleted()) {
(*i)->Serialize(metric_group->add_metric_sub_group());
serialized = true;
}
// Clear the serialized session metrics if requested.
if (serialized && clear_serialized_sessions) {
session_metrics_list_.erase(i);
} else {
i++;
}
}
}
void EngineMetrics::SerializeEngineMetrics(MetricsGroup* metric_group) {
ProtoMetricSerializer serializer(metric_group);
cdm_engine_add_key_.Serialize(&serializer);
cdm_engine_close_session_.Serialize(&serializer);
cdm_engine_decrypt_.Serialize(&serializer);
cdm_engine_find_session_for_key_.Serialize(&serializer);
cdm_engine_generate_key_request_.Serialize(&serializer);
cdm_engine_get_provisioning_request_.Serialize(&serializer);
cdm_engine_get_usage_info_.Serialize(&serializer);
cdm_engine_handle_provisioning_response_.Serialize(&serializer);
cdm_engine_life_span_.Serialize(&serializer);
cdm_engine_open_key_set_session_.Serialize(&serializer);
cdm_engine_open_session_.Serialize(&serializer);
cdm_engine_query_key_status_.Serialize(&serializer);
cdm_engine_release_all_usage_info_.Serialize(&serializer);
cdm_engine_release_usage_info_.Serialize(&serializer);
cdm_engine_remove_keys_.Serialize(&serializer);
cdm_engine_restore_key_.Serialize(&serializer);
cdm_engine_unprovision_.Serialize(&serializer);
crypto_metrics_.Serialize(metric_group);
}
} // metrics
} // wvcdm

View File

@@ -1,31 +0,0 @@
// Copyright 2016 Google Inc. All Rights Reserved
#include "metrics_front_end.h"
#include <stddef.h>
#include <log.h>
namespace wvcdm {
namespace metrics {
MetricsFrontEnd* MetricsFrontEnd::instance_ = NULL;
MetricsFrontEnd::MetricsFrontEnd(Report* root) :
root_(root) { }
MetricNotification* MetricsFrontEnd::CreateSubscriber() {
return root_ == NULL ? NULL : root_->NewReport();
}
MetricsFrontEnd& MetricsFrontEnd::Instance() {
static MetricsFrontEnd kDummy(NULL);
return instance_ == NULL ? kDummy : *instance_;
}
void MetricsFrontEnd::OverrideInstance(MetricsFrontEnd* instance) {
instance_ = instance;
}
} // namespace metrics
} // namespace wvcdm

View File

@@ -3,7 +3,7 @@
// Unit tests for EventMetric
#include "event_metric.h"
#include "metric_publisher.h"
#include "metric_serialization.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -15,22 +15,22 @@ using testing::NotNull;
namespace wvcdm {
namespace metrics {
class MockEventMetricNotification : public MetricNotification {
class MockEventMetricSerializer : public MetricSerializer {
public:
MOCK_METHOD2(UpdateString, void(const std::string& metric_id,
MOCK_METHOD2(SetString, void(const std::string& metric_id,
const std::string& value));
MOCK_METHOD2(UpdateInt32, void(const std::string& metric_id,
MOCK_METHOD2(SetInt32, void(const std::string& metric_id,
int32_t value));
MOCK_METHOD2(UpdateInt64, void(const std::string& metric_id,
MOCK_METHOD2(SetInt64, void(const std::string& metric_id,
int64_t value));
MOCK_METHOD2(UpdateDouble, void(const std::string& metric_id,
MOCK_METHOD2(SetDouble, void(const std::string& metric_id,
double value));
};
class EventMetricTest : public ::testing::Test {
public:
void SetUp() {
mock_notification_.reset(new MockEventMetricNotification());
mock_serializer_.reset(new MockEventMetricSerializer());
}
protected:
template<typename F1,
@@ -44,7 +44,7 @@ class EventMetricTest : public ::testing::Test {
return metric.value_map_;
}
scoped_ptr<MockEventMetricNotification> mock_notification_;
scoped_ptr<MockEventMetricSerializer> mock_serializer_;
};
TEST_F(EventMetricTest, NoFieldsSuccessNullCallback) {
@@ -60,19 +60,36 @@ TEST_F(EventMetricTest, NoFieldsSuccessNullCallback) {
TEST_F(EventMetricTest, NoFieldsSuccessWithCallback) {
wvcdm::metrics::EventMetric<> metric("no/fields/metric");
EXPECT_CALL(*mock_notification_,
UpdateInt64("no/fields/metric/count", 1.0));
EXPECT_CALL(*mock_notification_,
UpdateDouble("no/fields/metric/mean", 10.0));
EXPECT_CALL(*mock_notification_,
UpdateDouble("no/fields/metric/variance", 0.0));
EXPECT_CALL(*mock_notification_,
UpdateDouble("no/fields/metric/min", 10.0));
EXPECT_CALL(*mock_notification_,
UpdateDouble("no/fields/metric/max", 10.0));
EXPECT_CALL(*mock_serializer_,
SetInt64("no/fields/metric/count", 2));
EXPECT_CALL(*mock_serializer_,
SetDouble("no/fields/metric/mean", 10.0));
EXPECT_CALL(*mock_serializer_,
SetDouble("no/fields/metric/variance", 0.0));
EXPECT_CALL(*mock_serializer_,
SetDouble("no/fields/metric/min", 10.0));
EXPECT_CALL(*mock_serializer_,
SetDouble("no/fields/metric/max", 10.0));
metric.Record(10);
metric.Publish(mock_notification_.get());
metric.Record(10);
metric.Serialize(mock_serializer_.get());
std::map<std::string, Distribution*> value_map = GetValueMap(metric);
ASSERT_EQ(1u, GetValueMap(metric).size());
EXPECT_EQ(2, value_map.begin()->second->Count());
EXPECT_EQ("", value_map.begin()->first);
}
TEST_F(EventMetricTest, NoFieldsSuccessSingleRecordWithCallback) {
wvcdm::metrics::EventMetric<> metric("no/fields/metric");
EXPECT_CALL(*mock_serializer_,
SetInt64("no/fields/metric/count", 1.0));
EXPECT_CALL(*mock_serializer_,
SetDouble("no/fields/metric/mean", 10.0));
metric.Record(10);
metric.Serialize(mock_serializer_.get());
std::map<std::string, Distribution*> value_map = GetValueMap(metric);
ASSERT_EQ(1u, GetValueMap(metric).size());
@@ -142,24 +159,24 @@ TEST_F(EventMetricTest, TwoFieldsSuccessWithCallback) {
// Callbacks from second record operation.
EXPECT_CALL(
*mock_notification_,
UpdateInt64("two/fields/metric/count{error_code:11&pow2_size:16}", 2.0));
*mock_serializer_,
SetInt64("two/fields/metric/count{error_code:11&pow2_size:16}", 2.0));
EXPECT_CALL(
*mock_notification_,
UpdateDouble("two/fields/metric/mean{error_code:11&pow2_size:16}", 3.5));
*mock_serializer_,
SetDouble("two/fields/metric/mean{error_code:11&pow2_size:16}", 3.5));
EXPECT_CALL(
*mock_notification_,
UpdateDouble("two/fields/metric/variance{error_code:11&pow2_size:16}",
*mock_serializer_,
SetDouble("two/fields/metric/variance{error_code:11&pow2_size:16}",
0.25));
EXPECT_CALL(
*mock_notification_,
UpdateDouble("two/fields/metric/min{error_code:11&pow2_size:16}", 3.0));
*mock_serializer_,
SetDouble("two/fields/metric/min{error_code:11&pow2_size:16}", 3.0));
EXPECT_CALL(
*mock_notification_,
UpdateDouble("two/fields/metric/max{error_code:11&pow2_size:16}", 4.0));
*mock_serializer_,
SetDouble("two/fields/metric/max{error_code:11&pow2_size:16}", 4.0));
metric.Record(3, 11, Pow2Bucket(29));
metric.Record(4, 11, Pow2Bucket(29));
metric.Publish(mock_notification_.get());
metric.Serialize(mock_serializer_.get());
}
TEST_F(EventMetricTest, ThreeFieldsSuccess) {

View File

@@ -0,0 +1,444 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Unit tests for the metrics collections,
// EngineMetrics, SessionMetrics and CrytpoMetrics.
#include "metrics_collections.h"
#include <sstream>
#include "gmock/gmock.h"
#include "google/protobuf/text_format.h"
#include "gtest/gtest.h"
#include "log.h"
#include "metrics.pb.h"
#include "wv_cdm_types.h"
using drm_metrics::MetricsGroup;
using google::protobuf::TextFormat;
namespace wvcdm {
namespace metrics {
// TODO(blueeyes): Improve this implementation by supporting full message
// API In CDM. That allows us to use MessageDifferencer.
class EngineMetricsTest : public ::testing::Test {
};
TEST_F(EngineMetricsTest, AllEngineMetrics) {
EngineMetrics engine_metrics;
// Set some values in all of the engine metrics.
engine_metrics.cdm_engine_add_key_.Record(1.0, KEY_ADDED);
engine_metrics.cdm_engine_close_session_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_decrypt_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_find_session_for_key_.Record(1.0, false);
engine_metrics.cdm_engine_generate_key_request_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_get_provisioning_request_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_get_usage_info_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_handle_provisioning_response_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_life_span_.Record(1.0);
engine_metrics.cdm_engine_open_key_set_session_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_open_session_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_query_key_status_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_release_all_usage_info_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_release_usage_info_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_remove_keys_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_restore_key_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_unprovision_.Record(1.0, NO_ERROR, kSecurityLevelL1);
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, true, false);
// For each EventMetric, 2 metrics get serialized since only one sample was
// taken. So, the total number of serialized metrics are 2*17.
ASSERT_EQ(2 * 17, actual_metrics.metric_size());
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
// Spot check some metrics.
EXPECT_EQ("/drm/widevine/cdm_engine/add_key/time/count{error:2}",
actual_metrics.metric(0).name());
EXPECT_EQ("/drm/widevine/cdm_engine/close_session/time/mean{error:0}",
actual_metrics.metric(3).name());
EXPECT_EQ("/drm/widevine/cdm_engine/decrypt/time/mean{error:0}",
actual_metrics.metric(5).name());
EXPECT_EQ(1.0, actual_metrics.metric(5).value().double_value());
}
TEST_F(EngineMetricsTest, EngineAndCryptoMetrics) {
EngineMetrics engine_metrics;
// Set some values in some of the engine metrics and some crypto metrics.
engine_metrics.cdm_engine_add_key_.Record(1.0, KEY_ADDED);
engine_metrics.cdm_engine_close_session_.Record(1.0, NO_ERROR);
CryptoMetrics* crypto_metrics = engine_metrics.GetCryptoMetrics();
crypto_metrics->crypto_session_generic_decrypt_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128);
crypto_metrics->crypto_session_get_device_unique_id_
.Record(4.0, false);
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, true, false);
// For each EventMetric, 2 metrics get serialized since only one sample was
// taken. So, the total number of serialized metrics are 2*4 since we
// touched 4 metrics.
ASSERT_EQ(2 * 4, actual_metrics.metric_size());
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
// Spot check some metrics.
EXPECT_EQ("/drm/widevine/cdm_engine/add_key/time/count{error:2}",
actual_metrics.metric(0).name());
EXPECT_EQ(
"/drm/widevine/crypto_session/generic_decrypt/time/count"
"{error:0&length:1024&algorithm:1}",
actual_metrics.metric(4).name());
EXPECT_EQ(
"/drm/widevine/crypto_session/get_device_unique_id/time/mean{success:0}",
actual_metrics.metric(7).name());
EXPECT_EQ(4.0, actual_metrics.metric(7).value().double_value());
}
TEST_F(EngineMetricsTest, EmptyEngineMetrics) {
EngineMetrics engine_metrics;
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, true, false);
EXPECT_EQ(0, actual_metrics.metric_size());
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
}
TEST_F(EngineMetricsTest, EngineMetricsWithCompletedSessions) {
EngineMetrics engine_metrics;
// Set a values in an engine metric and in a crypto metric.
engine_metrics.cdm_engine_add_key_.Record(1.0, KEY_ADDED);
engine_metrics.GetCryptoMetrics()
->crypto_session_load_certificate_private_key_.Record(2.0, true);
// Create two sessions and record some metrics.
SessionMetrics* session_metrics_1 = engine_metrics.AddSession();
session_metrics_1->SetSessionId("session_id_1");
SessionMetrics* session_metrics_2 = engine_metrics.AddSession();
session_metrics_2->SetSessionId("session_id_2");
// Record a CryptoMetrics metric in the session.
session_metrics_2->GetCryptoMetrics()->crypto_session_generic_decrypt_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128);
session_metrics_2->SetSessionId("session_id_2");
// Mark only session 2 as completed.
session_metrics_2->SetCompleted();
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, true, false);
// Validate metric counts.
// For each EventMetric, 2 metrics get serialized since only one sample was
// taken. So, the total number of serialized metrics are 2*2 since we
// touched 2 metrics.
ASSERT_EQ(2 * 2, actual_metrics.metric_size());
ASSERT_EQ(1, actual_metrics.metric_sub_group_size());
ASSERT_EQ(3, actual_metrics.metric_sub_group(0).metric_size());
// Spot check some metrics.
EXPECT_EQ("/drm/widevine/cdm_engine/add_key/time/count{error:2}",
actual_metrics.metric(0).name());
EXPECT_EQ("/drm/widevine/crypto_session/load_certificate_private_key"
"/time/count{success:1}",
actual_metrics.metric(2).name());
EXPECT_EQ("/drm/widevine/cdm_session/session_id",
actual_metrics.metric_sub_group(0).metric(0).name());
EXPECT_EQ(
"session_id_2",
actual_metrics.metric_sub_group(0).metric(0).value().string_value());
EXPECT_EQ(
"/drm/widevine/crypto_session/generic_decrypt/time/count"
"{error:0&length:1024&algorithm:1}",
actual_metrics.metric_sub_group(0).metric(1).name());
}
TEST_F(EngineMetricsTest, EngineMetricsSerializeAllSessions) {
EngineMetrics engine_metrics;
// Create two sessions and record some metrics.
SessionMetrics* session_metrics_1 = engine_metrics.AddSession();
session_metrics_1->SetSessionId("session_id_1");
SessionMetrics* session_metrics_2 = engine_metrics.AddSession();
session_metrics_2->SetSessionId("session_id_2");
// Mark only session 2 as completed.
session_metrics_2->SetCompleted();
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, false, false);
// Validate metric counts.
// No Engine-level metrics were recorded.
ASSERT_EQ(0, actual_metrics.metric_size());
// Two sub groups, 1 per session.
ASSERT_EQ(2, actual_metrics.metric_sub_group_size());
ASSERT_EQ(1, actual_metrics.metric_sub_group(0).metric_size());
// Spot check some metrics.
EXPECT_EQ("/drm/widevine/cdm_session/session_id",
actual_metrics.metric_sub_group(0).metric(0).name());
EXPECT_EQ(
"session_id_1",
actual_metrics.metric_sub_group(0).metric(0).value().string_value());
EXPECT_EQ("/drm/widevine/cdm_session/session_id",
actual_metrics.metric_sub_group(1).metric(0).name());
EXPECT_EQ(
"session_id_2",
actual_metrics.metric_sub_group(1).metric(0).value().string_value());
}
TEST_F(EngineMetricsTest, EngineMetricsRemoveSessions) {
EngineMetrics engine_metrics;
// Create two sessions and record some metrics.
SessionMetrics* session_metrics_1 = engine_metrics.AddSession();
session_metrics_1->SetSessionId("session_id_1");
SessionMetrics* session_metrics_2 = engine_metrics.AddSession();
session_metrics_2->SetSessionId("session_id_2");
// Mark only session 2 as completed.
session_metrics_2->SetCompleted();
// Serialize all metrics, don't remove any.
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, false, false);
// Validate metric counts.
// Two sub groups, 1 per session.
ASSERT_EQ(2, actual_metrics.metric_sub_group_size());
// Serialize completed metrics, remove them.
actual_metrics.Clear();
engine_metrics.Serialize(&actual_metrics, true, true);
// Validate metric counts.
// Only one, completed session should exist.
ASSERT_EQ(1, actual_metrics.metric_sub_group_size());
ASSERT_EQ(1, actual_metrics.metric_sub_group(0).metric_size());
EXPECT_EQ(
"session_id_2",
actual_metrics.metric_sub_group(0).metric(0).value().string_value());
// Serialize all metrics, remove them.
actual_metrics.Clear();
engine_metrics.Serialize(&actual_metrics, false, true);
// Validate metric counts.
// Only one, non-complete session should exist.
ASSERT_EQ(1, actual_metrics.metric_sub_group_size());
ASSERT_EQ(1, actual_metrics.metric_sub_group(0).metric_size());
EXPECT_EQ(
"session_id_1",
actual_metrics.metric_sub_group(0).metric(0).value().string_value());
// Serialize all metrics, don't remove any.
actual_metrics.Clear();
engine_metrics.Serialize(&actual_metrics, false, false);
// Validate metric counts.
// There should be no more metric subgroups left.
ASSERT_EQ(0, actual_metrics.metric_sub_group_size());
}
class SessionMetricsTest : public ::testing::Test {
};
TEST_F(SessionMetricsTest, AllSessionMetrics) {
SessionMetrics session_metrics;
session_metrics.SetSessionId("session_id 1");
session_metrics.cdm_session_life_span_.Record(1.0);
session_metrics.cdm_session_renew_key_.Record(1.0, NO_ERROR);
session_metrics.cdm_session_restore_offline_session_.Record(1.0, NO_ERROR);
session_metrics.cdm_session_restore_usage_session_.Record(1.0, NO_ERROR);
// Record a CryptoMetrics metric in the session.
session_metrics.GetCryptoMetrics()->crypto_session_generic_decrypt_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128);
MetricsGroup actual_metrics;
session_metrics.Serialize(&actual_metrics);
ASSERT_EQ(11, actual_metrics.metric_size());
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
// Spot check some metrics.
EXPECT_EQ("/drm/widevine/cdm_session/session_id",
actual_metrics.metric(0).name());
EXPECT_EQ("/drm/widevine/cdm_session/life_span/time/count",
actual_metrics.metric(1).name());
EXPECT_EQ("/drm/widevine/cdm_session/renew_key/time/mean{error:0}",
actual_metrics.metric(4).name());
EXPECT_EQ(1.0, actual_metrics.metric(4).value().double_value());
EXPECT_EQ("/drm/widevine/crypto_session/generic_decrypt/time/count"
"{error:0&length:1024&algorithm:1}",
actual_metrics.metric(9).name());
}
TEST_F(SessionMetricsTest, EmptySessionMetrics) {
SessionMetrics session_metrics;
MetricsGroup actual_metrics;
session_metrics.Serialize(&actual_metrics);
// Session metric always has a session id.
ASSERT_EQ(1, actual_metrics.metric_size());
EXPECT_EQ("/drm/widevine/cdm_session/session_id",
actual_metrics.metric(0).name());
EXPECT_EQ("", actual_metrics.metric(0).value().string_value());
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
}
class CryptoMetricsTest : public ::testing::Test {
};
TEST_F(CryptoMetricsTest, AllCryptoMetrics) {
CryptoMetrics crypto_metrics;
// Crypto session metrics.
crypto_metrics.crypto_session_delete_all_usage_reports_
.Record(1.0, NO_ERROR);
crypto_metrics.crypto_session_delete_multiple_usage_information_
.Record(1.0, NO_ERROR);
crypto_metrics.crypto_session_generic_decrypt_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128);
crypto_metrics.crypto_session_generic_encrypt_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128);
crypto_metrics.crypto_session_generic_sign_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kSigningAlgorithmHmacSha256);
crypto_metrics.crypto_session_generic_verify_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kSigningAlgorithmHmacSha256);
crypto_metrics.crypto_session_get_device_unique_id_.Record(1.0, true);
crypto_metrics.crypto_session_get_security_level_
.Record(1.0, kSecurityLevelL1);
crypto_metrics.crypto_session_get_system_id_.Record(1.0, true, 1234);
crypto_metrics.crypto_session_get_token_.Record(1.0, true);
crypto_metrics.crypto_session_life_span_.Record(1.0);
crypto_metrics.crypto_session_load_certificate_private_key_
.Record(1.0, true);
crypto_metrics.crypto_session_open_.Record(1.0, NO_ERROR, kLevelDefault);
crypto_metrics.crypto_session_update_usage_information_
.Record(1.0, NO_ERROR);
crypto_metrics.crypto_session_usage_information_support_.Record(1.0, true);
// Oem crypto metrics.
crypto_metrics.oemcrypto_api_version_.Record(1.0, 123, kLevelDefault);
crypto_metrics.oemcrypto_close_session_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_copy_buffer_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED,
kLevelDefault, Pow2Bucket(1025));
crypto_metrics.oemcrypto_deactivate_usage_entry_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_decrypt_cenc_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_delete_usage_entry_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_delete_usage_table_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_derive_keys_from_session_key_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_force_delete_usage_entry_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_generate_derived_keys_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_generate_nonce_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_generate_rsa_signature_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_generate_signature_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_generic_decrypt_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_generic_encrypt_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_generic_sign_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_generic_verify_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_get_device_id_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_get_hdcp_capability_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_get_key_data_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED,
Pow2Bucket(1025), kLevelDefault);
crypto_metrics.oemcrypto_get_max_number_of_sessions_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_get_number_of_open_sessions_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_get_oem_public_certificate_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_get_provisioning_method_
.Record(1.0, OEMCrypto_Keybox, kLevelDefault);
crypto_metrics.oemcrypto_get_random_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_initialize_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_install_keybox_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_is_anti_rollback_hw_present_
.Record(1.0, true, kLevelDefault);
crypto_metrics.oemcrypto_is_keybox_valid_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_load_device_rsa_key_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_load_keys_.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_load_test_keybox_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_load_test_rsa_key_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_open_session_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_refresh_keys_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_report_usage_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_rewrap_device_rsa_key_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_rewrap_device_rsa_key_30_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_security_level_.Record(1.0, "test", kLevelDefault);
crypto_metrics.oemcrypto_security_patch_level_
.Record(1.0, 123, kLevelDefault);
crypto_metrics.oemcrypto_select_key_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_supports_usage_table_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_update_usage_table_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_wrap_keybox_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
// Internal OEMCrypto Metrics
crypto_metrics.oemcrypto_initialization_mode_
.Record(1.0, OEMCrypto_INITIALIZED_FORCING_L3);
crypto_metrics.oemcrypto_l1_api_version_.Record(1.0, 12, 123);
MetricsGroup actual_metrics;
crypto_metrics.Serialize(&actual_metrics);
// 61 EventMetric instances, 2 values each.
ASSERT_EQ(122, actual_metrics.metric_size());
// Spot check some metrics.
EXPECT_EQ(
"/drm/widevine/crypto_session/delete_all_usage_reports/time/count"
"{error:0}",
actual_metrics.metric(0).name());
EXPECT_EQ(1, actual_metrics.metric(0).value().int_value());
EXPECT_EQ(
"/drm/widevine/oemcrypto/l1_api_version/mean{version:12&min_version:123}",
actual_metrics.metric(121).name());
EXPECT_EQ(1.0, actual_metrics.metric(121).value().double_value());
// No subgroups should exist.
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
}
} // namespace metrics
} // namespace wvcdm

View File

@@ -22,10 +22,6 @@ AmiAdapter::~AmiAdapter() {
analytics_item_.selfrecord();
}
metrics::Report* AmiAdapter::NewReport() const {
return new AmiAdapter(analytics_item_.getSessionID());
}
void AmiAdapter::UpdateString(const std::string& metric_id,
const std::string& value) {
analytics_item_.setCString(metric_id.c_str(), value.c_str());

View File

@@ -7,7 +7,7 @@
#include "initialization_data.h"
#include "license.h"
#include "log.h"
#include "metrics_front_end.h"
#include "metrics.pb.h"
#include "properties.h"
#include "service_certificate.h"
#include "wv_cdm_constants.h"
@@ -21,22 +21,10 @@ namespace wvcdm {
Lock WvContentDecryptionModule::session_sharing_id_generation_lock_;
WvContentDecryptionModule::WvContentDecryptionModule() {
// TODO (b/36497276)
// replace call to new AmiAdapter() and remove ami_apdater.*
report_root_ = NULL; // new AmiAdapter();
front_end_ = new metrics::MetricsFrontEnd(report_root_);
metrics::MetricsFrontEnd::OverrideInstance(front_end_);
}
WvContentDecryptionModule::WvContentDecryptionModule() {}
WvContentDecryptionModule::~WvContentDecryptionModule() {
DisablePolicyTimer(true);
metrics::MetricsFrontEnd::OverrideInstance(NULL);
delete front_end_;
delete report_root_;
front_end_ = NULL;
report_root_ = NULL;
}
bool WvContentDecryptionModule::IsSupported(const std::string& init_data_type) {
@@ -409,6 +397,25 @@ bool WvContentDecryptionModule::IsValidServiceCertificate(
NO_ERROR;
}
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);
}
WvContentDecryptionModule::CdmInfo::CdmInfo()
: cdm_engine(new CdmEngine(&file_system)) {}

View File

@@ -529,13 +529,16 @@ status_t WVDrmPlugin::getPropertyString(const String8& name,
status_t WVDrmPlugin::getPropertyByteArray(const String8& name,
Vector<uint8_t>& value) const {
if (name == "deviceUniqueId") {
return queryProperty(QUERY_KEY_DEVICE_ID, value);
} else if (name == "provisioningUniqueId") {
return queryProperty(QUERY_KEY_PROVISIONING_ID, value);
} else if (name == "serviceCertificate") {
value = ToVector(mPropertySet.service_certificate());
} else if (name == "metrics") {
std::string metrics_value;
mCDM->GetSerializedMetrics(&metrics_value);
value = ToVector(metrics_value);
} else {
ALOGE("App requested unknown byte array property %s", name.string());
return android::ERROR_DRM_CANNOT_HANDLE;

View File

@@ -714,6 +714,10 @@ Return<void> WVDrmPlugin::getPropertyByteArray(
}
} else if (name == "serviceCertificate") {
value = StrToVector(mPropertySet.service_certificate());
} else if (name == "metrics") {
std::string metrics_value;
mCDM->GetSerializedMetrics(&metrics_value);
value = StrToVector(metrics_value);
} else {
ALOGE("App requested unknown byte array property %s", name.c_str());
status = android::ERROR_DRM_CANNOT_HANDLE;

View File

@@ -114,7 +114,17 @@ const std::string kAppId("com.unittest.mock.app.id");
const uint8_t* const kUnprovisionResponse =
reinterpret_cast<const uint8_t*>("unprovision");
const size_t kUnprovisionResponseSize = 11;
}
const std::string kDeviceId = "0123456789ABCDEF";
// This is a serialized MetricsGroup message containing a small amount of
// sample data. This ensures we're able to extract it via a property.
const char kSerializedMetrics[] = {
0x0a, 0x0a, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x02, 0x08, 0x00,
0x0a, 0x12, 0x0a, 0x05, 0x74, 0x65, 0x73, 0x74, 0x32, 0x12, 0x09, 0x11,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x15, 0x0a, 0x05,
0x74, 0x65, 0x73, 0x74, 0x33, 0x12, 0x0c, 0x1a, 0x0a, 0x74, 0x65, 0x73,
0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65};
} // anonymous namespace
class MockCDM : public WvContentDecryptionModule {
public:
@@ -180,6 +190,8 @@ class MockCDM : public WvContentDecryptionModule {
CdmResponseType(const CdmUsageInfoReleaseMessage&, const CdmIdentifier&));
MOCK_METHOD1(IsValidServiceCertificate, bool(const std::string&));
MOCK_METHOD1(GetSerializedMetrics, void(std::string*));
};
class MockCrypto : public WVGenericCryptoInterface {
@@ -1044,6 +1056,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
static const std::string openSessions = "42";
static const std::string maxSessions = "54";
static const std::string oemCryptoApiVersion = "13";
std::string serializedMetrics(
kSerializedMetrics, kSerializedMetrics + sizeof(kSerializedMetrics));
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _))
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1),
@@ -1075,6 +1089,9 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
.WillOnce(DoAll(SetArgPointee<2>(oemCryptoApiVersion),
testing::Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm, GetSerializedMetrics(_))
.WillOnce(SetArgPointee<0>(serializedMetrics));
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto, false);
std::string stringResult;
std::vector<uint8_t> vectorResult;
@@ -1161,6 +1178,15 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
ASSERT_EQ(Status::OK, status);
EXPECT_EQ(oemCryptoApiVersion, stringResult.c_str());
});
plugin.getPropertyByteArray(
hidl_string("metrics"),
[&](Status status, hidl_vec<uint8_t> vectorResult) {
ASSERT_EQ(Status::OK, status);
std::vector<uint8_t> id(vectorResult);
EXPECT_THAT(id, ElementsAreArray(serializedMetrics.data(),
serializedMetrics.size()));
});
}
TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) {

View File

@@ -32,7 +32,16 @@ const String8 kAppId("com.unittest.mock.app.id");
const uint8_t* const kUnprovisionResponse =
reinterpret_cast<const uint8_t*>("unprovision");
const size_t kUnprovisionResponseSize = 11;
}
// This is a serialized MetricsGroup message containing a small amount of
// sample data. This ensures we're able to extract it via a property.
const char kSerializedMetrics[] = {
0x0a, 0x0a, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x02, 0x08, 0x00,
0x0a, 0x12, 0x0a, 0x05, 0x74, 0x65, 0x73, 0x74, 0x32, 0x12, 0x09, 0x11,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x15, 0x0a, 0x05,
0x74, 0x65, 0x73, 0x74, 0x33, 0x12, 0x0c, 0x1a, 0x0a, 0x74, 0x65, 0x73,
0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65};
} // anonymous namespace
class MockCDM : public WvContentDecryptionModule {
public:
@@ -98,6 +107,8 @@ class MockCDM : public WvContentDecryptionModule {
CdmResponseType(const CdmUsageInfoReleaseMessage&, const CdmIdentifier&));
MOCK_METHOD1(IsValidServiceCertificate, bool(const std::string&));
MOCK_METHOD1(GetSerializedMetrics, void(std::string*));
};
class MockCrypto : public WVGenericCryptoInterface {
@@ -837,6 +848,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
static const string openSessions = "15";
static const string maxSessions = "18";
static const string oemCryptoApiVersion = "10";
string serializedMetrics(kSerializedMetrics,
kSerializedMetrics + sizeof(kSerializedMetrics));
EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _))
.WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1),
@@ -868,6 +881,9 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
.WillOnce(DoAll(SetArgPointee<2>(oemCryptoApiVersion),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(*cdm, GetSerializedMetrics(_))
.WillOnce(SetArgPointee<0>(serializedMetrics));
String8 stringResult;
Vector<uint8_t> vectorResult;
@@ -919,6 +935,12 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
res = plugin.getPropertyString(String8("oemCryptoApiVersion"), stringResult);
ASSERT_EQ(OK, res);
EXPECT_EQ(oemCryptoApiVersion, stringResult.string());
vectorResult.clear();
res = plugin.getPropertyByteArray(String8("metrics"), vectorResult);
ASSERT_EQ(OK, res);
EXPECT_THAT(vectorResult, ElementsAreArray(serializedMetrics.data(),
serializedMetrics.size()));
}
TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) {