Add a metric decorator around cdm engine

[ Merge from http://go/wvgerrit/69105 ]

This adds a metric collecting decorator class around cdm engine. This
implementation uses a templated decorator. The decorator enables:

1) Wrapping the CDM Engine methods to capture timing and error
information.
2) Allows use of a mock CDM Engine for testing.

Test: Unit tests. GPlay manual testing and GTS tests.
BUG: http://b/64724336
Change-Id: I5e4a0f552974fab1939bc7ab02719a1f5849cf3f
This commit is contained in:
Adam Stone
2019-01-15 17:25:43 -08:00
parent 1cc4f71975
commit 46eecb6b80
14 changed files with 954 additions and 110 deletions

View File

@@ -83,6 +83,7 @@ try_adb_push() {
try_adb_push base64_test
try_adb_push buffer_reader_test
try_adb_push cdm_engine_test
try_adb_push cdm_engine_metrics_decorator_unittest
try_adb_push cdm_feature_test
try_adb_push cdm_extended_duration_test
try_adb_push cdm_session_unittest

View File

@@ -29,6 +29,7 @@ METRICS_SRC_DIR := metrics/src
LOCAL_SRC_FILES := \
$(CORE_SRC_DIR)/buffer_reader.cpp \
$(CORE_SRC_DIR)/cdm_engine.cpp \
$(CORE_SRC_DIR)/cdm_engine_factory.cpp \
$(CORE_SRC_DIR)/cdm_session.cpp \
$(CORE_SRC_DIR)/cdm_session_map.cpp \
$(CORE_SRC_DIR)/certificate_provisioning.cpp \

View File

@@ -26,6 +26,7 @@
namespace wvcdm {
class CdmClientPropertySet;
class CdmEngineFactory;
class CdmSession;
class CryptoEngine;
class UsagePropertySet;
@@ -37,7 +38,6 @@ typedef std::map<CdmKeySetId,
class CdmEngine {
public:
CdmEngine(FileSystem* file_system, const std::string& spoid = EMPTY_SPOID);
virtual ~CdmEngine();
// Session related methods
@@ -316,10 +316,37 @@ class CdmEngine {
// dead lock.
virtual void OnTimerEvent();
virtual metrics::EngineMetrics* GetMetrics() { return &metrics_; }
// Fills the |engine_metrics| parameter with the current snapshot of metrics
// data. Returns true if the metrics data is populated, false otherwise.
// |engine_metrics| is owned by the caller and must not be null.
// The CdmEngine implementation is a placeholder. Just return false.
virtual bool GetMetricsSnapshot(
__attribute__((unused)) drm_metrics::WvCdmMetrics *metrics) {
return false;
}
virtual CdmResponseType ValidateServiceCertificate(const std::string& cert);
// Setter and getter for the |app_package_name| identifier for this instance
// of the CdmEngine. This is used to identify the package name.
virtual void SetAppPackageName(const std::string& app_package_name) {
app_package_name_ = app_package_name;
}
virtual const std::string& GetAppPackageName() {
return app_package_name_;
}
protected:
friend class CdmEngineFactory;
friend class WvCdmEnginePreProvTest;
friend class WvCdmTestBase;
friend class WvGenericOperationsTest;
friend class TestLicenseHolder;
CdmEngine(FileSystem* file_system,
std::shared_ptr<metrics::EngineMetrics> metrics,
const std::string& spoid = EMPTY_SPOID);
private:
// private methods
CdmResponseType OpenSession(
@@ -348,7 +375,8 @@ class CdmEngine {
* ensure that all data has been properly recorded in the group before
* it is published.
*/
metrics::EngineMetrics metrics_;
std::shared_ptr<metrics::EngineMetrics> metrics_;
std::string app_package_name_;
CdmSessionMap session_map_;
CdmReleaseKeySetMap release_key_sets_;

View File

@@ -0,0 +1,28 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#ifndef WVCDM_CORE_CDM_ENGINE_FACTORY_H_
#define WVCDM_CORE_CDM_ENGINE_FACTORY_H_
#include <string>
#include "cdm_engine.h"
#include "file_store.h"
namespace wvcdm {
// This factory is used to create an instance of the CdmEngine.
class CdmEngineFactory {
public:
// Creates a new instance of a CdmEngine. Caller retains ownership of the
// |files_system| which cannot be null.
static CdmEngine* CreateCdmEngine(FileSystem* file_system);
private:
CORE_DISALLOW_COPY_AND_ASSIGN(CdmEngineFactory);
};
} // namespace wvcdm
#endif // WVCDM_CORE_CDM_ENGINE_FACTORY_H_

View File

@@ -0,0 +1,263 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#ifndef WVCDM_CORE_CDM_ENGINE_METRICS_DECORATOR_H_
#define WVCDM_CORE_CDM_ENGINE_METRICS_DECORATOR_H_
#include <memory>
#include <string>
#include <vector>
#include "cdm_engine.h"
#include "cdm_session_map.h"
#include "certificate_provisioning.h"
#include "clock.h"
#include "crypto_session.h"
#include "disallow_copy_and_assign.h"
#include "file_store.h"
#include "initialization_data.h"
#include "metrics_collections.h"
#include "oemcrypto_adapter.h"
#include "properties.h"
#include "service_certificate.h"
#include "wv_cdm_constants.h"
#include "wv_cdm_types.h"
namespace wvcdm {
class CdmClientPropertySet;
class CdmEngineFactory;
class CdmSession;
class CryptoEngine;
class UsagePropertySet;
class WvCdmEventListener;
// This is a templated decorator class implementation of the CdmEngine.
// It captures metric information related to the inner CdmEngine class.
// Usage:
// FileSystem* file_system; // Construction of FileSystem object not shown.
// std::shared_ptr<metrics::EngineMetrics> metrics(new EngineMetrics);
// CdmEngine* e = new CdmEngineMetricsImpl<CdmEngine>(file_system, metrics);
template<class T>
class CdmEngineMetricsImpl : public T {
public:
// This constructor initializes the instance and takes ownership of |metrics|.
// |file_system| and |metrics| must not be null.
// |metrics| is used within the base class constructor. So, it must be
// passed in as a dependency and provided to the base constructor.
CdmEngineMetricsImpl(FileSystem* file_system,
std::shared_ptr<metrics::EngineMetrics> metrics,
const std::string& spoid = EMPTY_SPOID)
: T(file_system, metrics, spoid), metrics_(metrics) {
metrics_->cdm_engine_creation_time_millis_.Record(clock_.GetCurrentTime());
std::string cdm_version;
if(Properties::GetWVCdmVersion(&cdm_version)) {
metrics_->cdm_engine_cdm_version_.Record(cdm_version);
} else {
metrics_->cdm_engine_cdm_version_.SetError(false);
}
}
~CdmEngineMetricsImpl() override {};
bool GetMetricsSnapshot(drm_metrics::WvCdmMetrics *metrics) override {
if (metrics == nullptr) return false;
metrics_->Serialize(metrics);
return true;
}
CdmResponseType OpenSession(
const CdmKeySystem& key_system, CdmClientPropertySet* property_set,
const CdmSessionId& forced_session_id, WvCdmEventListener* event_listener)
override {
CdmResponseType sts = T::OpenSession(
key_system, property_set, forced_session_id, event_listener);
metrics_->cdm_engine_open_session_.Increment(sts);
return sts;
}
CdmResponseType OpenSession(
const CdmKeySystem& key_system, CdmClientPropertySet* property_set,
WvCdmEventListener* event_listener, CdmSessionId* session_id)
override {
CdmResponseType sts = T::OpenSession(
key_system, property_set, event_listener, session_id);
metrics_->cdm_engine_open_session_.Increment(sts);
return sts;
}
CdmResponseType CloseSession(const CdmSessionId& session_id) override {
CdmResponseType sts = T::CloseSession(session_id);
metrics_->cdm_engine_close_session_.Increment(sts);
return sts;
}
CdmResponseType OpenKeySetSession(
const CdmKeySetId& key_set_id, CdmClientPropertySet* property_set,
WvCdmEventListener* event_listener) override {
CdmResponseType sts = T::OpenKeySetSession(key_set_id, property_set,
event_listener);
metrics_->cdm_engine_open_key_set_session_.Increment(sts);
return sts;
}
CdmResponseType GenerateKeyRequest(
const CdmSessionId& session_id, const CdmKeySetId& key_set_id,
const InitializationData& init_data, const CdmLicenseType license_type,
CdmAppParameterMap& app_parameters, CdmKeyRequest* key_request) override {
CdmResponseType sts;
M_TIME(sts = T::GenerateKeyRequest(session_id, key_set_id, init_data,
license_type, app_parameters,
key_request),
metrics_, cdm_engine_generate_key_request_, sts, license_type);
return sts;
}
CdmResponseType AddKey(
const CdmSessionId& session_id, const CdmKeyResponse& key_data,
CdmLicenseType* license_type, CdmKeySetId* key_set_id) override {
if (license_type == nullptr) {
LOGE("CdmEngine::AddKey: license_type cannot be null.");
return PARAMETER_NULL;
}
CdmResponseType sts;
M_TIME(sts = T::AddKey(session_id, key_data, license_type, key_set_id),
metrics_, cdm_engine_add_key_, sts, *license_type);
return sts;
}
CdmResponseType RestoreKey(const CdmSessionId& session_id,
const CdmKeySetId& key_set_id) override {
CdmResponseType sts;
M_TIME(sts = T::RestoreKey(session_id, key_set_id),
metrics_, cdm_engine_restore_key_, sts);
return sts;
}
CdmResponseType RemoveKeys(const CdmSessionId& session_id) override {
CdmResponseType sts = T::RemoveKeys(session_id);
metrics_->cdm_engine_remove_keys_.Increment(sts);
return sts;
}
CdmResponseType QueryKeyStatus(const CdmSessionId& session_id,
CdmQueryMap* query_response) override {
CdmResponseType sts;
M_TIME(sts = T::QueryKeyStatus(session_id, query_response),
metrics_, cdm_engine_query_key_status_, sts);
return sts;
}
CdmResponseType GetProvisioningRequest(
CdmCertificateType cert_type, const std::string& cert_authority,
const std::string& service_certificate,
CdmProvisioningRequest* request, std::string* default_url) override {
CdmResponseType sts;
M_TIME(sts = T::GetProvisioningRequest(cert_type, cert_authority,
service_certificate,
request, default_url),
metrics_, cdm_engine_get_provisioning_request_, sts);
return sts;
}
CdmResponseType HandleProvisioningResponse(
const CdmProvisioningResponse& response, std::string* cert,
std::string* wrapped_key) override {
CdmResponseType sts;
M_TIME(
sts = T::HandleProvisioningResponse(response, cert, wrapped_key),
metrics_, cdm_engine_handle_provisioning_response_, sts);
return sts;
}
CdmResponseType Unprovision(CdmSecurityLevel security_level) override {
CdmResponseType sts = T::Unprovision(security_level);
metrics_->cdm_engine_unprovision_.Increment(sts, security_level);
return sts;
}
CdmResponseType GetUsageInfo(const std::string& app_id,
CdmUsageInfo* usage_info) override {
CdmResponseType sts;
M_TIME(sts = T::GetUsageInfo(app_id, usage_info),
metrics_, cdm_engine_get_usage_info_, sts);
return sts;
}
CdmResponseType GetUsageInfo(const std::string& app_id,
const CdmSecureStopId& ssid,
CdmUsageInfo* usage_info) override {
CdmResponseType sts;
M_TIME(sts = T::GetUsageInfo(app_id, ssid, usage_info),
metrics_, cdm_engine_get_usage_info_, sts);
return sts;
}
CdmResponseType RemoveAllUsageInfo(const std::string& app_id) override {
CdmResponseType sts = T::RemoveAllUsageInfo(app_id);
metrics_->cdm_engine_remove_all_usage_info_.Increment(sts);
return sts;
}
CdmResponseType RemoveAllUsageInfo(const std::string& app_id,
CdmSecurityLevel security_level) override {
CdmResponseType sts = T::RemoveAllUsageInfo(app_id, security_level);
metrics_->cdm_engine_remove_all_usage_info_.Increment(sts);
return sts;
}
CdmResponseType RemoveUsageInfo(
const std::string& app_id, const CdmSecureStopId& secure_stop_id)
override {
CdmResponseType sts = T::RemoveUsageInfo(app_id, secure_stop_id);
metrics_->cdm_engine_remove_usage_info_.Increment(sts);
return sts;
}
CdmResponseType ReleaseUsageInfo(const CdmUsageInfoReleaseMessage& message)
override {
CdmResponseType sts = T::ReleaseUsageInfo(message);
metrics_->cdm_engine_release_usage_info_.Increment(sts);
return sts;
}
CdmResponseType ListUsageIds(
const std::string& app_id, CdmSecurityLevel security_level,
std::vector<std::string>* ksids,
std::vector<std::string>* provider_session_tokens) override {
CdmResponseType sts = T::ListUsageIds(app_id, security_level,
ksids, provider_session_tokens);
metrics_->cdm_engine_get_secure_stop_ids_.Increment(sts);
return sts;
}
bool FindSessionForKey(const KeyId& key_id, CdmSessionId* session_id)
override {
bool status =
T::FindSessionForKey(key_id, session_id);
metrics_->cdm_engine_find_session_for_key_.Increment(status);
return status;
}
CdmResponseType Decrypt(const CdmSessionId& session_id,
const CdmDecryptionParameters& parameters) override {
CdmResponseType sts;
M_TIME(sts = T::Decrypt(session_id, parameters),
metrics_, cdm_engine_decrypt_, sts,
metrics::Pow2Bucket(parameters.encrypt_length));
return sts;
}
private:
std::shared_ptr<metrics::EngineMetrics> metrics_;
Clock clock_;
};
} // wvcdm namespace
#endif // WVCDM_CORE_CDM_ENGINE_METRICS_DECORATOR_H_

View File

@@ -71,8 +71,11 @@ class UsagePropertySet : public CdmClientPropertySet {
bool CdmEngine::seeded_ = false;
CdmEngine::CdmEngine(FileSystem* file_system, const std::string& spoid)
: cert_provisioning_(),
CdmEngine::CdmEngine(FileSystem* file_system,
std::shared_ptr<metrics::EngineMetrics> metrics,
const std::string& spoid)
: metrics_(metrics),
cert_provisioning_(),
cert_provisioning_requested_security_level_(kLevelDefault),
file_system_(file_system),
spoid_(spoid),
@@ -85,16 +88,6 @@ CdmEngine::CdmEngine(FileSystem* file_system, const std::string& spoid)
srand(clock_.GetCurrentTime());
seeded_ = true;
}
metrics_.cdm_engine_creation_time_millis_.Record(clock_.GetCurrentTime());
std::string cdm_version;
if(Properties::GetWVCdmVersion(&cdm_version)) {
metrics_.cdm_engine_cdm_version_.Record(cdm_version);
} else {
// Set error "false", the return value of GetWVCdmVersion.
metrics_.cdm_engine_cdm_version_.SetError(false);
}
}
CdmEngine::~CdmEngine() {
@@ -141,7 +134,7 @@ CdmResponseType CdmEngine::OpenSession(
CloseExpiredReleaseSessions();
std::unique_ptr<CdmSession> new_session(new CdmSession(file_system_,
metrics_.AddSession()));
metrics_->AddSession()));
CdmResponseType sts = new_session->Init(property_set, forced_session_id,
event_listener);
if (sts != NO_ERROR) {
@@ -206,7 +199,7 @@ CdmResponseType CdmEngine::CloseSession(const CdmSessionId& session_id) {
LOGE("CdmEngine::CloseSession: session not found = %s", session_id.c_str());
return SESSION_NOT_FOUND_1;
}
metrics_.ConsolidateSessions();
metrics_->ConsolidateSessions();
return NO_ERROR;
}
@@ -529,7 +522,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
std::string* query_response) {
LOGI("CdmEngine::QueryStatus");
std::unique_ptr<CryptoSession> crypto_session(
CryptoSession::MakeCryptoSession(metrics_.GetCryptoMetrics()));
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
CdmResponseType status;
if (!query_response) {
@@ -584,11 +577,11 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
if (!got_info) {
LOGW("CdmEngine::QueryStatus: UsageInformationSupport failed");
metrics_.GetCryptoMetrics()->crypto_session_usage_information_support_
metrics_->GetCryptoMetrics()->crypto_session_usage_information_support_
.SetError(got_info);
return UNKNOWN_ERROR;
}
metrics_.GetCryptoMetrics()->crypto_session_usage_information_support_
metrics_->GetCryptoMetrics()->crypto_session_usage_information_support_
.Record(supports_usage_reporting);
*query_response =
@@ -677,7 +670,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
M_TIME(
status = crypto_session->Open(
security_level),
metrics_.GetCryptoMetrics(),
metrics_->GetCryptoMetrics(),
crypto_session_open_,
status,
security_level);
@@ -688,7 +681,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
if (query_token == QUERY_KEY_DEVICE_ID) {
std::string deviceId;
status = crypto_session->GetExternalDeviceUniqueId(&deviceId);
metrics_.GetCryptoMetrics()->crypto_session_get_device_unique_id_
metrics_->GetCryptoMetrics()->crypto_session_get_device_unique_id_
.Increment(status);
if (status != NO_ERROR) return status;
@@ -878,7 +871,7 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
if (NULL == cert_provisioning_.get()) {
cert_provisioning_.reset(
new CertificateProvisioning(metrics_.GetCryptoMetrics()));
new CertificateProvisioning(metrics_->GetCryptoMetrics()));
CdmResponseType status = cert_provisioning_->Init(service_certificate);
if (status != NO_ERROR) return status;
}
@@ -924,12 +917,12 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
// Certificate provisioning object has been released. Check if a concurrent
// provisioning attempt has succeeded before declaring failure.
std::unique_ptr<CryptoSession> crypto_session(
CryptoSession::MakeCryptoSession(metrics_.GetCryptoMetrics()));
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
CdmResponseType status;
M_TIME(
status = crypto_session->Open(
cert_provisioning_requested_security_level_),
metrics_.GetCryptoMetrics(),
metrics_->GetCryptoMetrics(),
crypto_session_open_,
status,
cert_provisioning_requested_security_level_);
@@ -967,7 +960,7 @@ bool CdmEngine::IsProvisioned(CdmSecurityLevel security_level) {
property_set.set_security_level(
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
CdmSession session(file_system_, metrics_.AddSession());
CdmSession session(file_system_, metrics_->AddSession());
CdmResponseType status = session.Init(&property_set);
if (NO_ERROR != status) {
@@ -981,7 +974,7 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
// Devices with baked-in DRM certs cannot be reprovisioned and therefore must
// not be unprovisioned.
std::unique_ptr<CryptoSession> crypto_session(
CryptoSession::MakeCryptoSession(metrics_.GetCryptoMetrics()));
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
CdmClientTokenType token_type = kClientTokenUninitialized;
CdmResponseType res = crypto_session->GetProvisioningMethod(
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault,
@@ -1016,14 +1009,14 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
CdmResponseType CdmEngine::DeleteUsageTable(CdmSecurityLevel security_level) {
LOGI("CdmEngine::DeleteUsageTable: security level: %d", security_level);
std::unique_ptr<CryptoSession> crypto_session(
CryptoSession::MakeCryptoSession(metrics_.GetCryptoMetrics()));
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
CdmResponseType status;
M_TIME(
status = crypto_session->Open(
security_level == kSecurityLevelL3 ?
kLevel3 :
kLevelDefault),
metrics_.GetCryptoMetrics(),
metrics_->GetCryptoMetrics(),
crypto_session_open_,
status,
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
@@ -1033,7 +1026,7 @@ CdmResponseType CdmEngine::DeleteUsageTable(CdmSecurityLevel security_level) {
return UNPROVISION_ERROR_4;
}
status = crypto_session->DeleteAllUsageReports();
metrics_.GetCryptoMetrics()->crypto_session_delete_all_usage_reports_
metrics_->GetCryptoMetrics()->crypto_session_delete_all_usage_reports_
.Increment(status);
if (status != NO_ERROR) {
LOGE("CdmEngine::DeleteUsageTable: error deleteing usage reports: %d",
@@ -1101,7 +1094,7 @@ CdmResponseType CdmEngine::DeleteUsageRecord(const std::string& app_id,
// Got provider token. Remove from OEMCrypto.
std::unique_ptr<CryptoSession> crypto_session(
CryptoSession::MakeCryptoSession(metrics_.GetCryptoMetrics()));
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
CdmResponseType status = crypto_session->Open(
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
if (status == NO_ERROR) {
@@ -1224,7 +1217,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_, metrics_.AddSession()));
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);
@@ -1244,7 +1237,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_, metrics_.AddSession()));
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");
@@ -1324,7 +1317,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_, metrics_.AddSession()));
usage_session_.reset(new CdmSession(file_system_, metrics_->AddSession()));
CdmResponseType status = usage_session_->Init(usage_property_set_.get());
if (NO_ERROR != status) {
@@ -1408,7 +1401,7 @@ CdmResponseType CdmEngine::RemoveAllUsageInfo(
// Got at least one provider token. Remove from OEMCrypto.
std::unique_ptr<CryptoSession> crypto_session(
CryptoSession::MakeCryptoSession(metrics_.GetCryptoMetrics()));
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
CdmResponseType status = crypto_session->Open(
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
if (status == NO_ERROR) {
@@ -1437,7 +1430,7 @@ CdmResponseType CdmEngine::RemoveAllUsageInfo(const std::string& app_id) {
? kLevel3
: kLevelDefault;
usage_property_set_->set_security_level(security_level);
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
usage_session_.reset(new CdmSession(file_system_, metrics_->AddSession()));
usage_session_->Init(usage_property_set_.get());
switch (usage_session_->get_usage_support_type()) {
@@ -1530,7 +1523,7 @@ CdmResponseType CdmEngine::RemoveUsageInfo(
? kLevel3
: kLevelDefault;
usage_property_set_->set_security_level(security_level);
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
usage_session_.reset(new CdmSession(file_system_, metrics_->AddSession()));
usage_session_->Init(usage_property_set_.get());
std::vector<DeviceFiles::CdmUsageData> usage_data;
@@ -1565,7 +1558,7 @@ CdmResponseType CdmEngine::RemoveUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id),
provider_session_token);
std::unique_ptr<CryptoSession> crypto_session(
CryptoSession::MakeCryptoSession(metrics_.GetCryptoMetrics()));
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
status = crypto_session->Open(
static_cast<CdmSecurityLevel>(j) == kSecurityLevelL3
? kLevel3 : kLevelDefault);
@@ -2086,18 +2079,18 @@ void CdmEngine::DeleteAllUsageReportsUponFactoryReset() {
if (!file_system_->Exists(device_base_path_level1) &&
!file_system_->Exists(device_base_path_level3)) {
std::unique_ptr<CryptoSession> crypto_session(
CryptoSession::MakeCryptoSession(metrics_.GetCryptoMetrics()));
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
CdmResponseType status;
M_TIME(
status = crypto_session->Open(
cert_provisioning_requested_security_level_),
metrics_.GetCryptoMetrics(),
metrics_->GetCryptoMetrics(),
crypto_session_open_,
status,
cert_provisioning_requested_security_level_);
if (NO_ERROR == status) {
status = crypto_session->DeleteAllUsageReports();
metrics_.GetCryptoMetrics()->crypto_session_delete_all_usage_reports_
metrics_->GetCryptoMetrics()->crypto_session_delete_all_usage_reports_
.Increment(status);
if (NO_ERROR != status) {
LOGW(

View File

@@ -0,0 +1,24 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#include "cdm_engine_factory.h"
#include <memory>
#include <string>
#include "cdm_engine.h"
#include "cdm_engine_metrics_decorator.h"
#include "clock.h"
#include "file_store.h"
namespace wvcdm {
CdmEngine* CdmEngineFactory::CreateCdmEngine(FileSystem* file_system) {
std::unique_ptr<metrics::EngineMetrics> engine_metrics(
new metrics::EngineMetrics());
return new CdmEngineMetricsImpl<CdmEngine>(file_system,
std::move(engine_metrics));
}
} // namespace wvcdm

View File

@@ -0,0 +1,529 @@
// Copyright 2018 Google LLC. All Rights Reserved. This fil and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
// These tests are for the cdm engine metrics implementation. They ensure that
// The cdm engine metrics impl is correctly forwarding calls to the internal
// implementation and capturing metrics as appropriate.
#include "cdm_engine_metrics_decorator.h"
#include <memory>
#include <string>
#include "cdm_client_property_set.h"
#include "cdm_engine.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "metrics.pb.h"
#include "wv_cdm_event_listener.h"
using ::testing::_;
using ::testing::ByRef;
using ::testing::Eq;
using ::testing::Matcher;
using ::testing::Return;
using ::testing::StrEq;
using ::testing::StrictMock;
using ::wvcdm::metrics::EngineMetrics;
namespace wvcdm {
class MockCdmClientPropertySet : public CdmClientPropertySet {
public:
MOCK_CONST_METHOD0(security_level, const std::string&());
MOCK_CONST_METHOD0(use_privacy_mode, bool());
MOCK_CONST_METHOD0(service_certificate, const std::string&());
MOCK_METHOD1(set_service_certificate, void(const std::string&));
MOCK_CONST_METHOD0(is_session_sharing_enabled, bool());
MOCK_CONST_METHOD0(session_sharing_id, uint32_t());
MOCK_METHOD1(set_session_sharing_id, void(uint32_t));
MOCK_CONST_METHOD0(app_id, const std::string&());
};
class MockWvCdmEventListener : public WvCdmEventListener {
MOCK_METHOD1(OnSessionRenewalNeeded, void(const CdmSessionId&));
MOCK_METHOD3(OnSessionKeysChange,
void(const CdmSessionId&, const CdmKeyStatusMap&,
bool has_new_usable_key));
MOCK_METHOD2(OnExpirationUpdate, void(const CdmSessionId&, int64_t));
};
class MockCdmEngineImpl : public CdmEngine {
public:
MockCdmEngineImpl(FileSystem* file_system,
std::shared_ptr<EngineMetrics> metrics,
const std::string& spoid)
: CdmEngine(file_system, metrics, spoid) {}
MOCK_METHOD4(OpenSession, CdmResponseType(
const CdmKeySystem&, CdmClientPropertySet*,
const CdmSessionId&, WvCdmEventListener*));
MOCK_METHOD4(OpenSession, CdmResponseType(
const CdmKeySystem&, CdmClientPropertySet*,
WvCdmEventListener*, CdmSessionId*));
MOCK_METHOD1(CloseSession, CdmResponseType(const CdmSessionId&));
MOCK_METHOD3(OpenKeySetSession,
CdmResponseType(const CdmKeySetId&, CdmClientPropertySet*,
WvCdmEventListener*));
MOCK_METHOD6(GenerateKeyRequest,
CdmResponseType(const CdmSessionId&, const CdmKeySetId&,
const InitializationData&, const CdmLicenseType,
CdmAppParameterMap&, CdmKeyRequest*));
MOCK_METHOD4(AddKey, CdmResponseType(
const CdmSessionId&, const CdmKeyResponse&,
CdmLicenseType*, CdmKeySetId*));
MOCK_METHOD2(RestoreKey, CdmResponseType(const CdmSessionId&,
const CdmKeySetId&));
MOCK_METHOD1(RemoveKeys, CdmResponseType(const CdmSessionId&));
MOCK_METHOD2(QueryKeyStatus, CdmResponseType(const CdmSessionId&,
CdmQueryMap*));
MOCK_METHOD5(GetProvisioningRequest, CdmResponseType(
CdmCertificateType, const std::string&, const std::string&,
CdmProvisioningRequest*, std::string*));
MOCK_METHOD3(HandleProvisioningResponse, CdmResponseType(
const CdmProvisioningResponse&, std::string*, std::string*));
MOCK_METHOD1(Unprovision, CdmResponseType(CdmSecurityLevel));
MOCK_METHOD4(ListUsageIds, CdmResponseType(
const std::string&, CdmSecurityLevel,
std::vector<std::string>*, std::vector<std::string>*));
MOCK_METHOD1(RemoveAllUsageInfo, CdmResponseType(const std::string&));
MOCK_METHOD2(RemoveAllUsageInfo, CdmResponseType(const std::string&,
CdmSecurityLevel));
MOCK_METHOD2(RemoveUsageInfo, CdmResponseType(const std::string&,
const CdmSecureStopId&));
MOCK_METHOD1(ReleaseUsageInfo,
CdmResponseType(const CdmUsageInfoReleaseMessage&));
MOCK_METHOD2(Decrypt, CdmResponseType(const CdmSessionId&,
const CdmDecryptionParameters&));
MOCK_METHOD2(FindSessionForKey, bool(const KeyId&, CdmSessionId*));
};
class WvCdmEngineMetricsImplTest : public ::testing::Test {
public:
void SetUp() override {
file_system_.reset(new FileSystem);
std::shared_ptr<EngineMetrics> engine_metrics(new EngineMetrics);
test_cdm_metrics_engine_.reset(
new CdmEngineMetricsImpl<StrictMock<MockCdmEngineImpl>>(
file_system_.get(), engine_metrics));
}
protected:
std::unique_ptr<FileSystem> file_system_;
std::unique_ptr<CdmEngineMetricsImpl<StrictMock<MockCdmEngineImpl>>>
test_cdm_metrics_engine_;
};
TEST_F(WvCdmEngineMetricsImplTest, OpenSession_Overload1) {
MockCdmClientPropertySet property_set;
MockWvCdmEventListener event_listener;
EXPECT_CALL(*test_cdm_metrics_engine_,
OpenSession(
StrEq("foo"), Eq(&property_set),
Matcher<const CdmSessionId&>(Eq("bar")), Eq(&event_listener)))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->OpenSession("foo", &property_set, "bar",
&event_listener));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(1, metrics_proto.engine_metrics().cdm_engine_open_session_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_open_session(0).attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, OpenSession_Overload2) {
MockCdmClientPropertySet property_set;
MockWvCdmEventListener event_listener;
CdmSessionId session_id;
EXPECT_CALL(*test_cdm_metrics_engine_,
OpenSession(
StrEq("foo"), Eq(&property_set),
Eq(&event_listener), Matcher<CdmSessionId*>(Eq(&session_id))))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->OpenSession(
"foo", &property_set, &event_listener, &session_id));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(1, metrics_proto.engine_metrics().cdm_engine_open_session_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_open_session(0).attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, CloseSession) {
MockCdmClientPropertySet property_set;
MockWvCdmEventListener event_listener;
EXPECT_CALL(*test_cdm_metrics_engine_, CloseSession(Eq("bar")))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->CloseSession("bar"));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(1, metrics_proto.engine_metrics().cdm_engine_close_session_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_close_session(0).attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, OpenKeySetSession) {
MockCdmClientPropertySet property_set;
MockWvCdmEventListener event_listener;
EXPECT_CALL(*test_cdm_metrics_engine_,
OpenKeySetSession(Eq("bar"), Eq(&property_set), Eq(&event_listener)))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->OpenKeySetSession("bar", &property_set,
&event_listener));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics().cdm_engine_open_key_set_session_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_open_key_set_session(0).attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, GenerateKeyRequest) {
InitializationData initialization_data;
CdmAppParameterMap app_parameters;
CdmKeyRequest key_request;
EXPECT_CALL(*test_cdm_metrics_engine_,
GenerateKeyRequest(Eq("foo"), Eq("bar"), _, Eq(kLicenseTypeStreaming),
Eq(app_parameters), Eq(&key_request)))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->GenerateKeyRequest(
"foo", "bar", initialization_data,
kLicenseTypeStreaming, app_parameters, &key_request));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_generate_key_request_time_us_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_generate_key_request_time_us(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, AddKey) {
CdmLicenseType license_type;
CdmKeySetId key_set_id;
EXPECT_CALL(*test_cdm_metrics_engine_,
AddKey(Eq("fake session id"), Eq("fake response"), Eq(&license_type),
Eq(&key_set_id)))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->AddKey(
"fake session id", "fake response",
&license_type, &key_set_id));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_add_key_time_us_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_add_key_time_us(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, RestoreKey) {
EXPECT_CALL(*test_cdm_metrics_engine_,
RestoreKey(Eq("fake session id"), Eq("fake key set id")))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->RestoreKey(
"fake session id", "fake key set id"));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_restore_key_time_us_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_restore_key_time_us(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, RemoveKeys) {
EXPECT_CALL(*test_cdm_metrics_engine_,
RemoveKeys(Eq("fake session id")))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->RemoveKeys("fake session id"));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_remove_keys_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_remove_keys(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, QueryKeyStatus) {
CdmQueryMap query_response;
EXPECT_CALL(*test_cdm_metrics_engine_,
QueryKeyStatus(Eq("fake session id"), Eq(&query_response)))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->QueryKeyStatus("fake session id",
&query_response));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_query_key_status_time_us_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_query_key_status_time_us(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, GetProvisioningRequest) {
CdmProvisioningRequest request;
std::string default_url;
EXPECT_CALL(*test_cdm_metrics_engine_,
GetProvisioningRequest(Eq(kCertificateX509),
Eq("fake certificate authority"),
Eq("fake service certificate"),
Eq(&request), Eq(&default_url)))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->GetProvisioningRequest(
kCertificateX509, "fake certificate authority",
"fake service certificate", &request, &default_url));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_get_provisioning_request_time_us_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_get_provisioning_request_time_us(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, HandleProvisioningResponse) {
CdmProvisioningResponse response;
std::string cert;
std::string wrapped_key;
EXPECT_CALL(*test_cdm_metrics_engine_,
HandleProvisioningResponse(Eq("fake provisioning response"),
Eq(&cert), Eq(&wrapped_key)))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->HandleProvisioningResponse(
"fake provisioning response", &cert, &wrapped_key));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_handle_provisioning_response_time_us_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_handle_provisioning_response_time_us(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, Unprovision) {
EXPECT_CALL(*test_cdm_metrics_engine_,
Unprovision(Eq(kSecurityLevelL2)))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->Unprovision(kSecurityLevelL2));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_unprovision_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_unprovision(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, RemoveAllUsageInfo_Overload1) {
EXPECT_CALL(*test_cdm_metrics_engine_,
RemoveAllUsageInfo(Eq("fake app id")))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->RemoveAllUsageInfo("fake app id"));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_remove_all_usage_info_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_remove_all_usage_info(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, RemoveAllUsageInfo_Overload2) {
EXPECT_CALL(*test_cdm_metrics_engine_,
RemoveAllUsageInfo(Eq("fake app id"), Eq(kSecurityLevelL2)))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->RemoveAllUsageInfo("fake app id",
kSecurityLevelL2));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_remove_all_usage_info_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_remove_all_usage_info(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, RemoveUsageInfo) {
EXPECT_CALL(*test_cdm_metrics_engine_,
RemoveUsageInfo(Eq("fake app id"), Eq("fake secure stop id")))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->RemoveUsageInfo("fake app id",
"fake secure stop id"));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_remove_usage_info_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_remove_usage_info(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, ReleaseUsageInfo) {
EXPECT_CALL(*test_cdm_metrics_engine_,
ReleaseUsageInfo(Eq("fake release message")))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->ReleaseUsageInfo("fake release message"));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_release_usage_info_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_release_usage_info(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, ListUsageIds) {
std::vector<std::string> ksids;
std::vector<std::string> provider_session_tokens;
EXPECT_CALL(*test_cdm_metrics_engine_,
ListUsageIds(Eq("fake app id"), Eq(kSecurityLevelL2),
Eq(&ksids), Eq(&provider_session_tokens)))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->ListUsageIds(
"fake app id", kSecurityLevelL2, &ksids,
&provider_session_tokens));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_get_secure_stop_ids_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_get_secure_stop_ids(0)
.attributes().error_code());
}
TEST_F(WvCdmEngineMetricsImplTest, FindSessionForKey) {
CdmSessionId session_id;
EXPECT_CALL(*test_cdm_metrics_engine_,
FindSessionForKey(Eq("fake key id"), Eq(&session_id)))
.WillOnce(Return(true));
ASSERT_TRUE(test_cdm_metrics_engine_->FindSessionForKey("fake key id",
&session_id));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_find_session_for_key_size());
EXPECT_TRUE(metrics_proto.engine_metrics()
.cdm_engine_find_session_for_key(0)
.attributes().error_code_bool());
}
TEST_F(WvCdmEngineMetricsImplTest, Decrypt) {
CdmDecryptionParameters parameters;
EXPECT_CALL(*test_cdm_metrics_engine_, Decrypt(Eq("fake session id"), _))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
test_cdm_metrics_engine_->Decrypt("fake session id", parameters));
drm_metrics::WvCdmMetrics metrics_proto;
test_cdm_metrics_engine_->GetMetricsSnapshot(&metrics_proto);
ASSERT_EQ(
1, metrics_proto.engine_metrics()
.cdm_engine_decrypt_time_us_size());
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
metrics_proto.engine_metrics()
.cdm_engine_decrypt_time_us(0)
.attributes().error_code());
}
} // namespace wvcdm

View File

@@ -32,6 +32,7 @@ namespace wvcdm {
using drm_metrics::DistributionMetric;
using drm_metrics::WvCdmMetrics;
using metrics::EngineMetrics;
namespace {
@@ -48,7 +49,9 @@ const std::string kComma = ",";
class WvCdmEnginePreProvTest : public WvCdmTestBase {
public:
WvCdmEnginePreProvTest()
: cdm_engine_(&file_system_), session_opened_(false) {}
: dummy_engine_metrics_(new EngineMetrics),
cdm_engine_(&file_system_, dummy_engine_metrics_),
session_opened_(false) {}
~WvCdmEnginePreProvTest() override {}
@@ -112,6 +115,7 @@ class WvCdmEnginePreProvTest : public WvCdmTestBase {
}
FileSystem file_system_;
shared_ptr<metrics::EngineMetrics> dummy_engine_metrics_;
CdmEngine cdm_engine_;
bool session_opened_;
std::string key_msg_;
@@ -256,7 +260,7 @@ class WvCdmEngineTest : public WvCdmEnginePreProvTest {
EXPECT_EQ(KEY_ADDED, status);
EXPECT_EQ(expected_license_type, license_type);
VerifyLicenseRequestLatency(kKeyRequestTypeInitial,
*cdm_engine_.GetMetrics());
*dummy_engine_metrics_);
}
void VerifyRenewalKeyResponse(const std::string& server_url,
@@ -264,7 +268,7 @@ class WvCdmEngineTest : public WvCdmEnginePreProvTest {
std::string resp = GetKeyRequestResponse(server_url, client_auth);
EXPECT_EQ(KEY_ADDED, cdm_engine_.RenewKey(session_id_, resp));
VerifyLicenseRequestLatency(kKeyRequestTypeRenewal,
*cdm_engine_.GetMetrics());
*dummy_engine_metrics_);
}
void VerifyLicenseRequestLatency(

View File

@@ -32,7 +32,9 @@ namespace wvcdm {
class WvGenericOperationsTest : public WvCdmTestBase {
public:
WvGenericOperationsTest()
: cdm_engine_(&file_system_), holder_(&cdm_engine_) {}
: dummy_engine_metrics_(new metrics::EngineMetrics),
cdm_engine_(&file_system_, dummy_engine_metrics_),
holder_(&cdm_engine_) {}
void SetUp() override {
WvCdmTestBase::SetUp();
@@ -73,6 +75,7 @@ class WvGenericOperationsTest : public WvCdmTestBase {
protected:
FileSystem file_system_;
std::shared_ptr<metrics::EngineMetrics> dummy_engine_metrics_;
CdmEngine cdm_engine_;
TestLicenseHolder holder_;

View File

@@ -27,6 +27,8 @@
#include "test_printers.h"
#include "url_request.h"
using wvcdm::metrics::EngineMetrics;
namespace wvcdm {
namespace {
void show_menu(char* prog_name) {
@@ -262,8 +264,10 @@ void WvCdmTestBase::Provision() {
CdmSessionId session_id;
FileSystem file_system;
// TODO(fredgc): provision for different SPOIDs.
CdmEngine cdm_engine(&file_system);
CdmEngine cdm_engine(&file_system,
std::shared_ptr<EngineMetrics>(new EngineMetrics));
CdmResponseType result = cdm_engine.GetProvisioningRequest(
cert_type, cert_authority, config_.provisioning_service_certificate(),
@@ -325,7 +329,8 @@ void WvCdmTestBase::Provision() {
void WvCdmTestBase::EnsureProvisioned() {
CdmSessionId session_id;
FileSystem file_system;
CdmEngine cdm_engine(&file_system);
CdmEngine cdm_engine(&file_system,
std::shared_ptr<EngineMetrics>(new EngineMetrics));
CdmResponseType status =
cdm_engine.OpenSession(config_.key_system(), NULL, NULL, &session_id);
if (status == NEED_PROVISIONING) {

View File

@@ -6,6 +6,7 @@
#include "cdm_client_property_set.h"
#include "cdm_engine.h"
#include "cdm_engine_factory.h"
#include "initialization_data.h"
#include "license.h"
#include "log.h"
@@ -64,7 +65,6 @@ CdmResponseType WvContentDecryptionModule::OpenSession(
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
CdmResponseType sts = cdm_engine->OpenSession(key_system, property_set,
event_listener, session_id);
cdm_engine->GetMetrics()->cdm_engine_open_session_.Increment(sts);
if (sts == NO_ERROR) {
cdm_by_session_id_[*session_id] = cdm_engine;
}
@@ -79,7 +79,6 @@ CdmResponseType WvContentDecryptionModule::CloseSession(
if (!cdm_engine) return SESSION_NOT_FOUND_1;
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
CdmResponseType sts = cdm_engine->CloseSession(session_id);
cdm_engine->GetMetrics()->cdm_engine_close_session_.Increment(sts);
if (sts == NO_ERROR) {
cdm_by_session_id_.erase(session_id);
}
@@ -102,7 +101,6 @@ CdmResponseType WvContentDecryptionModule::GenerateKeyRequest(
CdmResponseType sts;
if (license_type == kLicenseTypeRelease) {
sts = cdm_engine->OpenKeySetSession(key_set_id, property_set, NULL);
cdm_engine->GetMetrics()->cdm_engine_open_key_set_session_.Increment(sts);
if (sts != NO_ERROR) return sts;
cdm_by_session_id_[key_set_id] = cdm_engine;
}
@@ -124,11 +122,9 @@ CdmResponseType WvContentDecryptionModule::GenerateKeyRequest(
InitializationData initialization_data(init_data_type, init_data,
oec_version);
M_TIME(sts = cdm_engine->GenerateKeyRequest(session_id, key_set_id,
initialization_data, license_type,
app_parameters, key_request),
cdm_engine->GetMetrics(), cdm_engine_generate_key_request_,
sts, license_type);
sts = cdm_engine->GenerateKeyRequest(session_id, key_set_id,
initialization_data, license_type,
app_parameters, key_request);
switch (license_type) {
case kLicenseTypeRelease:
if (sts != KEY_MESSAGE) {
@@ -156,9 +152,7 @@ CdmResponseType WvContentDecryptionModule::AddKey(
}
CdmResponseType sts;
CdmLicenseType license_type;
M_TIME(sts = cdm_engine->AddKey(session_id, key_data,
&license_type, key_set_id),
cdm_engine->GetMetrics(), cdm_engine_add_key_, sts, license_type);
sts = cdm_engine->AddKey(session_id, key_data, &license_type, key_set_id);
// Empty session id indicates license type release.
if (sts == KEY_ADDED && session_id.empty()) {
cdm_engine->CloseKeySetSession(release_key_set_id);
@@ -172,8 +166,7 @@ CdmResponseType WvContentDecryptionModule::RestoreKey(
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
if (!cdm_engine) return SESSION_NOT_FOUND_4;
CdmResponseType sts;
M_TIME(sts = cdm_engine->RestoreKey(session_id, key_set_id),
cdm_engine->GetMetrics(), cdm_engine_restore_key_, sts);
sts = cdm_engine->RestoreKey(session_id, key_set_id);
if (sts == KEY_ADDED) EnablePolicyTimer();
return sts;
}
@@ -183,7 +176,6 @@ CdmResponseType WvContentDecryptionModule::RemoveKeys(
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
if (!cdm_engine) return SESSION_NOT_FOUND_5;
CdmResponseType sts = cdm_engine->RemoveKeys(session_id);
cdm_engine->GetMetrics()->cdm_engine_remove_keys_.Increment(sts);
return sts;
}
@@ -205,8 +197,7 @@ CdmResponseType WvContentDecryptionModule::QueryKeyStatus(
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
if (!cdm_engine) return SESSION_NOT_FOUND_9;
CdmResponseType sts;
M_TIME(sts = cdm_engine->QueryKeyStatus(session_id, key_info),
cdm_engine->GetMetrics(), cdm_engine_query_key_status_, sts);
sts = cdm_engine->QueryKeyStatus(session_id, key_info);
return sts;
}
@@ -227,59 +218,41 @@ CdmResponseType WvContentDecryptionModule::GetProvisioningRequest(
const CdmIdentifier& identifier, const std::string& service_certificate,
CdmProvisioningRequest* request, std::string* default_url) {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
CdmResponseType sts;
M_TIME(sts = cdm_engine->GetProvisioningRequest(cert_type, cert_authority,
service_certificate,
request, default_url),
cdm_engine->GetMetrics(), cdm_engine_get_provisioning_request_, sts);
return sts;
return cdm_engine->GetProvisioningRequest(
cert_type, cert_authority, service_certificate, request, default_url);
}
CdmResponseType WvContentDecryptionModule::HandleProvisioningResponse(
const CdmIdentifier& identifier, CdmProvisioningResponse& response,
std::string* cert, std::string* wrapped_key) {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
CdmResponseType sts;
M_TIME(
sts = cdm_engine->HandleProvisioningResponse(response, cert, wrapped_key),
cdm_engine->GetMetrics(), cdm_engine_handle_provisioning_response_, sts);
return sts;
return cdm_engine->HandleProvisioningResponse(response, cert, wrapped_key);
}
CdmResponseType WvContentDecryptionModule::Unprovision(
CdmSecurityLevel level, const CdmIdentifier& identifier) {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
CdmResponseType sts = cdm_engine->Unprovision(level);
cdm_engine->GetMetrics()->cdm_engine_unprovision_.Increment(sts, level);
return sts;
return cdm_engine->Unprovision(level);
}
CdmResponseType WvContentDecryptionModule::GetUsageInfo(
const std::string& app_id, const CdmIdentifier& identifier,
CdmUsageInfo* usage_info) {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
CdmResponseType sts;
M_TIME(sts = cdm_engine->GetUsageInfo(app_id, usage_info),
cdm_engine->GetMetrics(), cdm_engine_get_usage_info_, sts);
return sts;
return cdm_engine->GetUsageInfo(app_id, usage_info);
}
CdmResponseType WvContentDecryptionModule::GetUsageInfo(
const std::string& app_id, const CdmSecureStopId& ssid,
const CdmIdentifier& identifier, CdmUsageInfo* usage_info) {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
CdmResponseType sts;
M_TIME(sts = cdm_engine->GetUsageInfo(app_id, ssid, usage_info),
cdm_engine->GetMetrics(), cdm_engine_get_usage_info_, sts);
return sts;
return cdm_engine->GetUsageInfo(app_id, ssid, usage_info);
}
CdmResponseType WvContentDecryptionModule::RemoveAllUsageInfo(
const std::string& app_id, const CdmIdentifier& identifier) {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
CdmResponseType sts = cdm_engine->RemoveAllUsageInfo(app_id);
cdm_engine->GetMetrics()->cdm_engine_remove_all_usage_info_.Increment(sts);
return sts;
return cdm_engine->RemoveAllUsageInfo(app_id);
}
CdmResponseType WvContentDecryptionModule::RemoveUsageInfo(
@@ -287,18 +260,14 @@ CdmResponseType WvContentDecryptionModule::RemoveUsageInfo(
const CdmIdentifier& identifier,
const CdmSecureStopId& secure_stop_id) {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
CdmResponseType sts = cdm_engine->RemoveUsageInfo(app_id, secure_stop_id);
cdm_engine->GetMetrics()->cdm_engine_remove_usage_info_.Increment(sts);
return sts;
return cdm_engine->RemoveUsageInfo(app_id, secure_stop_id);
}
CdmResponseType WvContentDecryptionModule::ReleaseUsageInfo(
const CdmUsageInfoReleaseMessage& message,
const CdmIdentifier& identifier) {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
CdmResponseType sts = cdm_engine->ReleaseUsageInfo(message);
cdm_engine->GetMetrics()->cdm_engine_release_usage_info_.Increment(sts);
return sts;
return cdm_engine->ReleaseUsageInfo(message);
}
CdmResponseType WvContentDecryptionModule::GetSecureStopIds(
@@ -318,9 +287,7 @@ CdmResponseType WvContentDecryptionModule::GetSecureStopIds(
CdmResponseType sts_l3 = cdm_engine->ListUsageIds(app_id, kSecurityLevelL3,
NULL, &secure_stop_ids);
ssids->insert(ssids->end(), secure_stop_ids.begin(), secure_stop_ids.end());
if (sts_l3 != NO_ERROR) sts = sts_l3;
cdm_engine->GetMetrics()->cdm_engine_get_secure_stop_ids_.Increment(sts);
return sts;
return sts_l3 != NO_ERROR ? sts_l3 : sts;
}
CdmResponseType WvContentDecryptionModule::Decrypt(
@@ -339,8 +306,6 @@ CdmResponseType WvContentDecryptionModule::Decrypt(
if (validate_key_id && Properties::GetSessionSharingId(session_id) != 0) {
bool status =
cdm_engine->FindSessionForKey(*parameters.key_id, &local_session_id);
cdm_engine->GetMetrics()->cdm_engine_find_session_for_key_.Increment(
status);
if (!status) {
// key does not need to be loaded if clear lead/frame has a
// single subsample. It does in all other cases.
@@ -351,11 +316,7 @@ CdmResponseType WvContentDecryptionModule::Decrypt(
}
}
}
CdmResponseType sts;
M_TIME(sts = cdm_engine->Decrypt(local_session_id, parameters),
cdm_engine->GetMetrics(), cdm_engine_decrypt_, sts,
metrics::Pow2Bucket(parameters.encrypt_length));
return sts;
return cdm_engine->Decrypt(local_session_id, parameters);
}
void WvContentDecryptionModule::NotifyResolution(const CdmSessionId& session_id,
@@ -387,12 +348,12 @@ CdmResponseType WvContentDecryptionModule::GetMetrics(
// TODO(blueeyes): Add a better error.
return UNKNOWN_ERROR;
}
it->second.cdm_engine->GetMetrics()->Serialize(metrics);
return NO_ERROR;
return it->second.cdm_engine->GetMetricsSnapshot(metrics) ?
NO_ERROR : UNKNOWN_ERROR;
}
WvContentDecryptionModule::CdmInfo::CdmInfo()
: cdm_engine(new CdmEngine(&file_system)) {}
: cdm_engine(CdmEngineFactory::CreateCdmEngine(&file_system)) {}
CdmEngine* WvContentDecryptionModule::EnsureCdmForIdentifier(
const CdmIdentifier& identifier) {
@@ -406,9 +367,7 @@ CdmEngine* WvContentDecryptionModule::EnsureCdmForIdentifier(
cdms_[identifier].file_system.set_origin(identifier.origin);
cdms_[identifier].file_system.set_identifier(identifier.spoid +
identifier.origin);
// Set the app package name for use by metrics.
cdms_[identifier].cdm_engine->GetMetrics()->SetAppPackageName(
cdms_[identifier].cdm_engine->SetAppPackageName(
identifier.app_package_name);
}
CdmEngine* cdm_engine = cdms_[identifier].cdm_engine.get();

View File

@@ -21,6 +21,11 @@ test_src_dir := ../core/test
test_main := ../core/test/test_main.cpp
include $(LOCAL_PATH)/integration-test.mk
test_name := cdm_engine_metrics_decorator_unittest
test_src_dir := ../core/test
test_main := ../core/test/test_main.cpp
include $(LOCAL_PATH)/integration-test.mk
test_name := cdm_extended_duration_test
test_src_dir := .
test_main := ../core/test/test_main.cpp

View File

@@ -93,6 +93,7 @@ adb_shell_run request_license_test
adb_shell_run base64_test
adb_shell_run buffer_reader_test
adb_shell_run cdm_engine_test
adb_shell_run cdm_engine_metrics_decorator_unittest
adb_shell_run cdm_session_unittest
adb_shell_run counter_metric_unittest
adb_shell_run crypto_session_unittest