Merge "Added metrics history for WV CDM for Android." into udc-dev am: b5a7412675 am: 600c37d848
Original change: https://googleplex-android-review.googlesource.com/c/platform/vendor/widevine/+/22794476 Change-Id: I218eb3950be0fc7686ccc34bb64f7244310c9be1 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -5,12 +5,14 @@
|
||||
#ifndef CDM_BASE_WV_CONTENT_DECRYPTION_MODULE_H_
|
||||
#define CDM_BASE_WV_CONTENT_DECRYPTION_MODULE_H_
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
#include "cdm_identifier.h"
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "file_store.h"
|
||||
@@ -24,6 +26,32 @@ class CdmClientPropertySet;
|
||||
class CdmEngine;
|
||||
class WvCdmEventListener;
|
||||
|
||||
class WvMetricsSnapshot {
|
||||
public:
|
||||
WvMetricsSnapshot(const CdmIdentifier& identifier,
|
||||
drm_metrics::WvCdmMetrics&& metrics, ::time_t ts);
|
||||
|
||||
// Acts as a constructor, but uses the current time.
|
||||
static WvMetricsSnapshot MakeSnapshot(const CdmIdentifier& identifier,
|
||||
drm_metrics::WvCdmMetrics&& metrics);
|
||||
|
||||
WvMetricsSnapshot() = default;
|
||||
WvMetricsSnapshot(const WvMetricsSnapshot&) = default;
|
||||
WvMetricsSnapshot(WvMetricsSnapshot&&) = default;
|
||||
WvMetricsSnapshot& operator=(const WvMetricsSnapshot&) = default;
|
||||
WvMetricsSnapshot& operator=(WvMetricsSnapshot&&) = default;
|
||||
|
||||
const CdmIdentifier& cdm_id() const { return cdm_id_; }
|
||||
const drm_metrics::WvCdmMetrics& metrics() const { return metrics_; }
|
||||
::time_t timestamp() const { return timestamp_; }
|
||||
std::string GetFormattedTimestamp() const;
|
||||
|
||||
private:
|
||||
CdmIdentifier cdm_id_;
|
||||
drm_metrics::WvCdmMetrics metrics_;
|
||||
::time_t timestamp_ = 0;
|
||||
};
|
||||
|
||||
class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
||||
public:
|
||||
WvContentDecryptionModule();
|
||||
@@ -142,18 +170,30 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
||||
// Validate a passed-in service certificate
|
||||
virtual bool IsValidServiceCertificate(const std::string& certificate);
|
||||
|
||||
// Fill the metrics parameter with the metrics data for the CdmEngine
|
||||
// associated with the given CdmIdentifier. If the CdmEngine instance does
|
||||
// not exist, this will return an error.
|
||||
virtual CdmResponseType GetMetrics(const CdmIdentifier& identifier,
|
||||
drm_metrics::WvCdmMetrics* metrics);
|
||||
// Fill the |metrics| parameter with the engine metrics data for the
|
||||
// CdmEngine associated with the given CdmIdentifier.
|
||||
// If the CdmEngine instance does not exist, this will return an error.
|
||||
virtual CdmResponseType GetCurrentMetrics(const CdmIdentifier& identifier,
|
||||
drm_metrics::WvCdmMetrics* metrics);
|
||||
|
||||
// Fill the metrics parameter with the metrics data for all the CdmEngine
|
||||
// associated with the given CdmIdentifiers. If there are no CdmEngine
|
||||
// instances, this will return an error.
|
||||
virtual CdmResponseType GetMetrics(
|
||||
std::vector<drm_metrics::WvCdmMetrics>* metrics,
|
||||
bool* full_list_returned);
|
||||
// Fill the |snapshots| parameter wrapped engine metrics for all CdmEngine
|
||||
// instances that currently enabled (actively decrypting or performing
|
||||
// other engine-level operations).
|
||||
// Current metrics snapshots contain the engine identifier, metrics data
|
||||
// and time (roughly current time).
|
||||
// |full_list_returned| will indicate whether all existing enginers were
|
||||
// able to report their metrics successfully.
|
||||
virtual CdmResponseType GetAllCurrentMetricsSnapshots(
|
||||
std::vector<WvMetricsSnapshot>* snapshots, bool* full_list_returned);
|
||||
|
||||
// Fill the |snapshots| parameter wrapped engine metrics for several of
|
||||
// the most recently closed CdmEngine instances.
|
||||
// Saved metrics snapshots contain the engine identifier, metrics data
|
||||
// and time of closing.
|
||||
// The same engine identifier may appear multiple times in the list (
|
||||
// depending on how the app utilizes the MediaDrm plugin).
|
||||
virtual CdmResponseType GetAllSavedMetricsSnapshots(
|
||||
std::vector<WvMetricsSnapshot>* snapshots);
|
||||
|
||||
// Closes the CdmEngine and sessions associated with the given CdmIdentifier.
|
||||
virtual CdmResponseType CloseCdm(const CdmIdentifier& identifier);
|
||||
@@ -234,8 +274,10 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
||||
// not exist, this will return an error.
|
||||
// This methods assumes that |metrics| is not null and that the |cdms_lock_|
|
||||
// has already been acquired.
|
||||
CdmResponseType GetMetricsInternal(const CdmIdentifier& identifier,
|
||||
drm_metrics::WvCdmMetrics* metrics);
|
||||
CdmResponseType GetCurrentMetricsInternal(const CdmIdentifier& identifier,
|
||||
drm_metrics::WvCdmMetrics* metrics);
|
||||
void SaveMetrics(const CdmIdentifier& identifier,
|
||||
drm_metrics::WvCdmMetrics&& metrics);
|
||||
|
||||
static std::mutex session_sharing_id_generation_lock_;
|
||||
std::mutex timer_lock_;
|
||||
@@ -264,6 +306,10 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
||||
// - Hold lock when erasing, release once erased.
|
||||
std::mutex cdms_lock_;
|
||||
|
||||
// Contains a finite list of histories of different CDM engine instances.
|
||||
// When a CDM engine is closed, its metrics will be saved.
|
||||
std::deque<WvMetricsSnapshot> saved_metrics_snapshots_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule);
|
||||
};
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -20,14 +20,71 @@
|
||||
#include "wv_cdm_event_listener.h"
|
||||
#include "wv_metrics.pb.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
using wvutil::FileSystem;
|
||||
using wvutil::LoggingUidSetter;
|
||||
|
||||
namespace {
|
||||
const int kCdmTimerDurationSeconds = 1;
|
||||
|
||||
// In the interest of limiting memory usage, only a limited number of
|
||||
// the most recent metrics snapshots whould be stored.
|
||||
constexpr size_t kMaxSavedMetricsSnapshotCount = 50;
|
||||
|
||||
// Value returned by time() if the operation fails.
|
||||
constexpr time_t kTimeError = static_cast<time_t>(-1);
|
||||
|
||||
// Removes certain field from the provided CdmIdentifier as to make
|
||||
// it better usable for tracking the same engine across different
|
||||
// calls into the DRM plugin service.
|
||||
CdmIdentifier ScrubIdentifierForMetrics(const CdmIdentifier& identifier) {
|
||||
return CdmIdentifier{identifier.spoid, identifier.origin,
|
||||
identifier.app_package_name, identifier.unique_id,
|
||||
/* user_id */ wvutil::UNKNOWN_UID};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace wvcdm {
|
||||
WvMetricsSnapshot::WvMetricsSnapshot(const CdmIdentifier& identifier,
|
||||
drm_metrics::WvCdmMetrics&& metrics,
|
||||
time_t ts)
|
||||
: cdm_id_(ScrubIdentifierForMetrics(identifier)),
|
||||
metrics_(std::move(metrics)),
|
||||
timestamp_(ts) {}
|
||||
|
||||
WvMetricsSnapshot WvMetricsSnapshot::MakeSnapshot(
|
||||
const CdmIdentifier& identifier, drm_metrics::WvCdmMetrics&& metrics) {
|
||||
const time_t now = time(nullptr);
|
||||
if (now == kTimeError) {
|
||||
LOGW("Failed to get current time");
|
||||
return WvMetricsSnapshot(identifier, std::move(metrics), 0);
|
||||
}
|
||||
return WvMetricsSnapshot(identifier, std::move(metrics), now);
|
||||
}
|
||||
|
||||
std::string WvMetricsSnapshot::GetFormattedTimestamp() const {
|
||||
if (timestamp_ == 0) return "<unset>";
|
||||
struct tm time_info = {};
|
||||
if (localtime_r(×tamp_, &time_info) == nullptr) {
|
||||
LOGE("Failed to convert to local time");
|
||||
return "<conversion error(" + std::to_string(timestamp_) + ")>";
|
||||
}
|
||||
char timestamp_buffer[64]; // asctime_r() requires at least 29 bytes.
|
||||
memset(timestamp_buffer, 0, sizeof(timestamp_buffer));
|
||||
if (asctime_r(&time_info, timestamp_buffer) == nullptr) {
|
||||
LOGE("Failed to format localtime to ASC time");
|
||||
return "<format error(" + std::to_string(timestamp_) + ")>";
|
||||
}
|
||||
std::string result(timestamp_buffer);
|
||||
// The Linux manual illustrates asctime_r() as returning a value
|
||||
// with a new line character at the end. However, it does not
|
||||
// specify this in the description. This is to account for different
|
||||
// behavior on different systems.
|
||||
if (!result.empty() && result.back() == '\n') {
|
||||
result.pop_back();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::mutex WvContentDecryptionModule::session_sharing_id_generation_lock_;
|
||||
|
||||
@@ -394,45 +451,61 @@ bool WvContentDecryptionModule::IsValidServiceCertificate(
|
||||
return cert.has_certificate();
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetMetrics(
|
||||
std::vector<drm_metrics::WvCdmMetrics>* metrics, bool* full_list_returned) {
|
||||
if (!metrics || !full_list_returned) {
|
||||
return CdmResponseType(PARAMETER_NULL);
|
||||
}
|
||||
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||
for (auto& key_value_pair : cdms_) {
|
||||
const CdmIdentifier& identifier = key_value_pair.first;
|
||||
drm_metrics::WvCdmMetrics metric;
|
||||
const CdmResponseType status = GetMetricsInternal(identifier, &metric);
|
||||
if (status == NO_ERROR) {
|
||||
metrics->push_back(metric);
|
||||
} else {
|
||||
LOGD("GetMetrics call failed: cdm identifier=%u, error=%d",
|
||||
identifier.unique_id, status.ToInt());
|
||||
}
|
||||
}
|
||||
// With no streaming activities, |cdms_| size would be zero,
|
||||
// treat it as a non full list in that case.
|
||||
*full_list_returned = !cdms_.empty() && metrics->size() == cdms_.size();
|
||||
|
||||
// We only return error if no metrics is returned when cdms_ is not empty.
|
||||
// - metrics && cdms_ sizes can both be zero, returns NO_ERROR
|
||||
// - metrics size <= cdms_, returns NO_ERROR
|
||||
// - metrics is empty, but cdms_ is not, returns UNKNOWN_ERROR
|
||||
return (metrics->empty() && !cdms_.empty()) ? CdmResponseType(UNKNOWN_ERROR)
|
||||
: CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetMetrics(
|
||||
CdmResponseType WvContentDecryptionModule::GetCurrentMetrics(
|
||||
const CdmIdentifier& identifier, drm_metrics::WvCdmMetrics* metrics) {
|
||||
if (!metrics) {
|
||||
return CdmResponseType(PARAMETER_NULL);
|
||||
}
|
||||
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||
return GetMetricsInternal(identifier, metrics);
|
||||
return GetCurrentMetricsInternal(identifier, metrics);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetMetricsInternal(
|
||||
CdmResponseType WvContentDecryptionModule::GetAllCurrentMetricsSnapshots(
|
||||
std::vector<WvMetricsSnapshot>* snapshots, bool* full_list_returned) {
|
||||
if (!snapshots || !full_list_returned) {
|
||||
return CdmResponseType(PARAMETER_NULL);
|
||||
}
|
||||
snapshots->clear();
|
||||
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||
for (const auto& cdm_info : cdms_) {
|
||||
const CdmIdentifier& identifier = cdm_info.first;
|
||||
drm_metrics::WvCdmMetrics metric;
|
||||
const CdmResponseType status =
|
||||
GetCurrentMetricsInternal(identifier, &metric);
|
||||
if (status == NO_ERROR) {
|
||||
snapshots->push_back(
|
||||
WvMetricsSnapshot::MakeSnapshot(identifier, std::move(metric)));
|
||||
} else {
|
||||
LOGD("Failed to get metrics: cdm_identifier = %u, error = %s",
|
||||
identifier.unique_id, status.ToString().c_str());
|
||||
}
|
||||
}
|
||||
// With no streaming activities, |cdms_| size would be zero,
|
||||
// treat it as a non full list in that case.
|
||||
*full_list_returned = !cdms_.empty() && snapshots->size() == cdms_.size();
|
||||
|
||||
// We only return error if no metrics is returned when cdms_ is not empty.
|
||||
// - metrics && cdms_ sizes can both be zero, returns NO_ERROR
|
||||
// - metrics size <= cdms_, returns NO_ERROR
|
||||
// - metrics is empty, but cdms_ is not, returns UNKNOWN_ERROR
|
||||
return (snapshots->empty() && !cdms_.empty()) ? CdmResponseType(UNKNOWN_ERROR)
|
||||
: CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetAllSavedMetricsSnapshots(
|
||||
std::vector<WvMetricsSnapshot>* snapshots) {
|
||||
if (snapshots == nullptr) {
|
||||
return CdmResponseType(PARAMETER_NULL);
|
||||
}
|
||||
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||
// This has the potential to be an expensive operation. However,
|
||||
// this function is only used during debug reporting.
|
||||
snapshots->assign(saved_metrics_snapshots_.cbegin(),
|
||||
saved_metrics_snapshots_.cend());
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetCurrentMetricsInternal(
|
||||
const CdmIdentifier& identifier, drm_metrics::WvCdmMetrics* metrics) {
|
||||
// Note: Caller should lock before calling.
|
||||
auto it = cdms_.find(identifier);
|
||||
@@ -446,6 +519,16 @@ CdmResponseType WvContentDecryptionModule::GetMetricsInternal(
|
||||
: CdmResponseType(UNKNOWN_ERROR);
|
||||
}
|
||||
|
||||
void WvContentDecryptionModule::SaveMetrics(
|
||||
const CdmIdentifier& identifier, drm_metrics::WvCdmMetrics&& metrics) {
|
||||
// Caller should have acquired |cdms_lock_|.
|
||||
saved_metrics_snapshots_.push_front(
|
||||
WvMetricsSnapshot::MakeSnapshot(identifier, std::move(metrics)));
|
||||
if (saved_metrics_snapshots_.size() > kMaxSavedMetricsSnapshotCount) {
|
||||
saved_metrics_snapshots_.resize(kMaxSavedMetricsSnapshotCount);
|
||||
}
|
||||
}
|
||||
|
||||
WvContentDecryptionModule::CdmInfo::CdmInfo()
|
||||
: cdm_engine(CdmEngineFactory::CreateCdmEngine(&file_system)) {}
|
||||
|
||||
@@ -489,6 +572,17 @@ CdmEngine* WvContentDecryptionModule::GetCdmForSessionId(
|
||||
|
||||
void WvContentDecryptionModule::CloseAllCdms() {
|
||||
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||
for (const auto& cdm_info : cdms_) {
|
||||
const CdmIdentifier& identifier = cdm_info.first;
|
||||
drm_metrics::WvCdmMetrics metrics;
|
||||
const CdmResponseType status =
|
||||
GetCurrentMetricsInternal(identifier, &metrics);
|
||||
if (status == NO_ERROR) {
|
||||
SaveMetrics(identifier, std::move(metrics));
|
||||
} else {
|
||||
LOGD("CloseAllCdms failed to save metrics");
|
||||
}
|
||||
}
|
||||
cdm_by_session_id_.clear();
|
||||
cdms_.clear();
|
||||
}
|
||||
@@ -496,22 +590,32 @@ void WvContentDecryptionModule::CloseAllCdms() {
|
||||
CdmResponseType WvContentDecryptionModule::CloseCdm(
|
||||
const CdmIdentifier& cdm_identifier) {
|
||||
std::unique_lock<std::mutex> auto_lock(cdms_lock_);
|
||||
auto it = cdms_.find(cdm_identifier);
|
||||
if (it == cdms_.end()) {
|
||||
auto cdm_it = cdms_.find(cdm_identifier);
|
||||
if (cdm_it == cdms_.end()) {
|
||||
LOGE("Cdm Identifier not found");
|
||||
// TODO(blueeyes): Create a better error.
|
||||
return CdmResponseType(UNKNOWN_ERROR);
|
||||
}
|
||||
CdmEngine* cdm_engine = cdm_it->second.cdm_engine.get();
|
||||
// Save metrics snapshot.
|
||||
drm_metrics::WvCdmMetrics metrics;
|
||||
const bool success = cdm_engine->GetMetricsSnapshot(&metrics);
|
||||
if (success) {
|
||||
SaveMetrics(cdm_identifier, std::move(metrics));
|
||||
} else {
|
||||
LOGW("Failed to get metrics snapshot: unique_id = %" PRIu32,
|
||||
cdm_identifier.unique_id);
|
||||
}
|
||||
// Remove any sessions that point to this engine.
|
||||
for (auto session_it = cdm_by_session_id_.begin();
|
||||
session_it != cdm_by_session_id_.end();) {
|
||||
if (session_it->second == it->second.cdm_engine.get()) {
|
||||
if (session_it->second == cdm_engine) {
|
||||
session_it = cdm_by_session_id_.erase(session_it);
|
||||
} else {
|
||||
++session_it;
|
||||
}
|
||||
}
|
||||
cdms_.erase(it);
|
||||
cdms_.erase(cdm_it);
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
|
||||
@@ -1545,7 +1545,8 @@ TEST_P(WvCdmStreamingUsageReportTest, DISABLED_UsageTest) {
|
||||
|
||||
// Validate that update usage table entry is exercised.
|
||||
drm_metrics::WvCdmMetrics metrics;
|
||||
ASSERT_EQ(NO_ERROR, decryptor_->GetMetrics(kDefaultCdmIdentifier, &metrics));
|
||||
ASSERT_EQ(NO_ERROR, decryptor_->GetCurrentMetrics(
|
||||
kDefaultCdmIdentifier, &metrics));
|
||||
ValidateHasUpdateUsageEntry(metrics);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ class WvContentDecryptionModuleMetricsTest : public WvCdmTestBase {
|
||||
TEST_F(WvContentDecryptionModuleMetricsTest, IdentifierNotFound) {
|
||||
drm_metrics::WvCdmMetrics metrics;
|
||||
ASSERT_EQ(wvcdm::UNKNOWN_ERROR,
|
||||
decryptor_.GetMetrics(kDefaultCdmIdentifier, &metrics));
|
||||
decryptor_.GetCurrentMetrics(kDefaultCdmIdentifier, &metrics));
|
||||
}
|
||||
|
||||
TEST_F(WvContentDecryptionModuleMetricsTest, EngineOnlyMetrics) {
|
||||
@@ -62,7 +62,7 @@ TEST_F(WvContentDecryptionModuleMetricsTest, EngineOnlyMetrics) {
|
||||
|
||||
drm_metrics::WvCdmMetrics metrics;
|
||||
ASSERT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.GetMetrics(kDefaultCdmIdentifier, &metrics));
|
||||
decryptor_.GetCurrentMetrics(kDefaultCdmIdentifier, &metrics));
|
||||
|
||||
// 100 is an arbitrary high value that shouldn't ever occur.
|
||||
EXPECT_THAT(metrics.engine_metrics()
|
||||
@@ -110,7 +110,7 @@ TEST_F(WvContentDecryptionModuleMetricsTest, EngineAndSessionMetrics) {
|
||||
|
||||
drm_metrics::WvCdmMetrics metrics;
|
||||
ASSERT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.GetMetrics(kDefaultCdmIdentifier, &metrics));
|
||||
decryptor_.GetCurrentMetrics(kDefaultCdmIdentifier, &metrics));
|
||||
std::string serialized_metrics;
|
||||
ASSERT_TRUE(metrics.SerializeToString(&serialized_metrics));
|
||||
|
||||
@@ -162,7 +162,8 @@ TEST_F(WvContentDecryptionModuleMetricsTest,
|
||||
for (int i = 0; i < cdm_engine_count; i++) {
|
||||
drm_metrics::WvCdmMetrics metrics;
|
||||
metrics.Clear();
|
||||
ASSERT_EQ(wvcdm::NO_ERROR, decryptor_.GetMetrics(identifiers[i], &metrics));
|
||||
ASSERT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.GetCurrentMetrics(identifiers[i], &metrics));
|
||||
std::string serialized_metrics;
|
||||
ASSERT_TRUE(metrics.SerializeToString(&serialized_metrics));
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "Utils.h"
|
||||
#include "android-base/macros.h"
|
||||
@@ -754,24 +755,23 @@ Status WVDrmPlugin::unprovisionDevice() {
|
||||
|
||||
::ndk::ScopedAStatus WVDrmPlugin::getMetrics(
|
||||
vector<::aidl::android::hardware::drm::DrmMetricGroup>* _aidl_return) {
|
||||
_aidl_return->clear();
|
||||
CdmIdentifier identifier;
|
||||
auto status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
|
||||
if (status != Status::OK) {
|
||||
*_aidl_return = vector<DrmMetricGroup>();
|
||||
return toNdkScopedAStatus(status);
|
||||
}
|
||||
|
||||
drm_metrics::WvCdmMetrics proto_metrics;
|
||||
CdmResponseType result = mCDM->GetMetrics(identifier, &proto_metrics);
|
||||
const CdmResponseType result = mCDM->GetCurrentMetrics(identifier, &proto_metrics);
|
||||
if (result != wvcdm::NO_ERROR) {
|
||||
*_aidl_return = vector<DrmMetricGroup>();
|
||||
return toNdkScopedAStatus(mapCdmResponseType(result));
|
||||
}
|
||||
|
||||
vector<DrmMetricGroup> wvMetrics;
|
||||
::wvcdm::WvMetricsAdapter adapter;
|
||||
::wvcdm::WvMetricsAdapter::ToWvMetrics(proto_metrics, &wvMetrics);
|
||||
*_aidl_return = wvMetrics;
|
||||
*_aidl_return = std::move(wvMetrics);
|
||||
return toNdkScopedAStatus(Status::OK);
|
||||
}
|
||||
|
||||
@@ -1196,7 +1196,8 @@ Status WVDrmPlugin::unprovisionDevice() {
|
||||
if (status != Status::OK) {
|
||||
ALOGE("Unexpected error retrieving cdm identifier: %d", status.get());
|
||||
} else {
|
||||
status = mapCdmResponseType(mCDM->GetMetrics(identifier, &metrics));
|
||||
status =
|
||||
mapCdmResponseType(mCDM->GetCurrentMetrics(identifier, &metrics));
|
||||
}
|
||||
}
|
||||
if (status == Status::OK) {
|
||||
|
||||
@@ -241,7 +241,7 @@ class MockCDM : public WvContentDecryptionModule {
|
||||
MOCK_METHOD(bool, IsValidServiceCertificate, (const std::string &),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(CdmResponseType, GetMetrics,
|
||||
MOCK_METHOD(CdmResponseType, GetCurrentMetrics,
|
||||
(const CdmIdentifier &, drm_metrics::WvCdmMetrics *), (override));
|
||||
|
||||
MOCK_METHOD(CdmResponseType, GetDecryptHashError,
|
||||
@@ -1175,7 +1175,7 @@ TEST_F(WVDrmPluginHalTest, ReturnsExpectedPropertyValues) {
|
||||
.WillOnce(DoAll(SetArgPointee<2>(wvcdm::QUERY_VALUE_NOT_SUPPORTED),
|
||||
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
|
||||
|
||||
EXPECT_CALL(*mCdm, GetMetrics(_, _))
|
||||
EXPECT_CALL(*mCdm, GetCurrentMetrics(_, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(expected_metrics),
|
||||
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
|
||||
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
|
||||
#include "WVDrmFactory.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
|
||||
#include <android/binder_ibinder_platform.h>
|
||||
#include <binder/IPCThreadState.h>
|
||||
@@ -23,6 +25,7 @@
|
||||
#include "WVUUID.h"
|
||||
#include "android-base/properties.h"
|
||||
#include "cutils/properties.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_content_decryption_module.h"
|
||||
#include "wv_metrics.h"
|
||||
@@ -59,21 +62,44 @@ void FormatIndent(int fd, size_t indent) {
|
||||
if (real_indent < indent) FormatIndent(fd, indent - real_indent);
|
||||
}
|
||||
|
||||
void FormatWvCdmIdentifier(int fd, size_t parent_indent,
|
||||
const wvcdm::CdmIdentifier& identifier) {
|
||||
const size_t indent = parent_indent + 2;
|
||||
// Spoid.
|
||||
FormatIndent(fd, indent);
|
||||
dprintf(fd, "spoid: \"%s\"\n", wvutil::b2a_hex(identifier.spoid).c_str());
|
||||
// Origin.
|
||||
FormatIndent(fd, indent);
|
||||
dprintf(fd, "origin: \"%s\"\n", wvutil::b2a_hex(identifier.origin).c_str());
|
||||
// App package name.
|
||||
FormatIndent(fd, indent);
|
||||
dprintf(fd, "app_package_name: \"%s\"\n",
|
||||
identifier.app_package_name.c_str());
|
||||
// Unique ID.
|
||||
FormatIndent(fd, indent);
|
||||
dprintf(fd, "unique_id: %" PRIu32 "\n", identifier.unique_id);
|
||||
}
|
||||
|
||||
void FormatWvMetricsSnapshotItem(int fd, size_t parent_indent,
|
||||
drm_metrics::WvCdmMetrics& metrics,
|
||||
const wvcdm::WvMetricsSnapshot& snapshot,
|
||||
size_t item_index) {
|
||||
const size_t indent = parent_indent + 2;
|
||||
// TODO(b/239462891): Provide identifier and timestamp for metrics.
|
||||
|
||||
// Serialized proto size.
|
||||
// CDM identifier.
|
||||
FormatIndent(fd, parent_indent); // First parameter uses indent + list tick.
|
||||
dprintf(fd, "- serialized_proto_bytes: %zu # [%zu]\n",
|
||||
metrics.ByteSizeLong(), item_index);
|
||||
|
||||
dprintf(fd, "- identifier: # [%zu]\n", item_index);
|
||||
FormatWvCdmIdentifier(fd, indent, snapshot.cdm_id());
|
||||
// Timestamp.
|
||||
FormatIndent(fd, indent);
|
||||
dprintf(fd, "timestamp: \"%s\"\n", snapshot.GetFormattedTimestamp().c_str());
|
||||
// Serialized proto size.
|
||||
FormatIndent(fd, indent);
|
||||
dprintf(fd, "serialized_proto_bytes: %zu\n",
|
||||
snapshot.metrics().ByteSizeLong());
|
||||
// Engine metrics.
|
||||
FormatIndent(fd, indent);
|
||||
dprintf(fd, "cdm_metrics:\n");
|
||||
std::stringstream ss;
|
||||
wv_metrics::FormatWvCdmMetrics(metrics, indent, ss);
|
||||
wv_metrics::FormatWvCdmMetrics(snapshot.metrics(), indent, ss);
|
||||
PrintStream(fd, ss);
|
||||
}
|
||||
} // namespace
|
||||
@@ -213,15 +239,15 @@ void WVDrmFactory::printCdmMetrics(int fd) {
|
||||
|
||||
android::sp<wvcdm::WvContentDecryptionModule> cdm(getCDM());
|
||||
|
||||
vector<drm_metrics::WvCdmMetrics> metrics;
|
||||
bool full_list_returned = true;
|
||||
std::vector<wvcdm::WvMetricsSnapshot> snapshots;
|
||||
bool full_list_returned = false;
|
||||
wvcdm::CdmResponseType result =
|
||||
cdm->GetMetrics(&metrics, &full_list_returned);
|
||||
cdm->GetAllCurrentMetricsSnapshots(&snapshots, &full_list_returned);
|
||||
if (result != wvcdm::NO_ERROR) {
|
||||
dprintf(fd, " live_metrics:\n");
|
||||
dprintf(fd, " error_message: \"%s\"\n", result.ToString().c_str());
|
||||
dprintf(fd, " error_code: %d\n", static_cast<int>(result.code()));
|
||||
} else if (metrics.empty()) {
|
||||
} else if (snapshots.empty()) {
|
||||
// YAML does not support empty property values.
|
||||
const char kNoMetricsMessage[] =
|
||||
"Metrics not available, please retry while streaming a video.";
|
||||
@@ -229,15 +255,15 @@ void WVDrmFactory::printCdmMetrics(int fd) {
|
||||
} else {
|
||||
dprintf(fd, " live_metrics: ");
|
||||
if (full_list_returned) {
|
||||
dprintf(fd, "# count = %zu\n", metrics.size());
|
||||
dprintf(fd, "# count = %zu\n", snapshots.size());
|
||||
} else {
|
||||
const char kPartialListMessage[] =
|
||||
"Some metrics are missing due to an internal error, "
|
||||
"check logs for details.";
|
||||
dprintf(fd, "# count = %zu, %s\n", metrics.size(), kPartialListMessage);
|
||||
dprintf(fd, "# count = %zu, %s\n", snapshots.size(), kPartialListMessage);
|
||||
}
|
||||
for (size_t i = 0; i < metrics.size(); i++) {
|
||||
FormatWvMetricsSnapshotItem(fd, 2, metrics[i], i);
|
||||
for (size_t i = 0; i < snapshots.size(); i++) {
|
||||
FormatWvMetricsSnapshotItem(fd, 2, snapshots[i], i);
|
||||
}
|
||||
}
|
||||
// TODO(b/270166158): Print metrics history.
|
||||
|
||||
Reference in New Issue
Block a user