Files
android/libwvdrmengine/tools/metrics_dump/src/mediadrm_metrics.cpp
Edwin Wong d5d0652d4f Build metrics_dump tool in Android.
Replace Makefile with Android.bp.
Remove duplication of protos in proto directory.

Since we are now building the metrics_dump tool
under Android, use frameworks metrics.proto
directly. Also, reference cdm's wv_metrics.proto
from the cdm directory instead of creating a
subset in proto directory.

bug: 161783052
bug: 170607430

Test: build
  m -j128 metrics_dump
Test: metrics_dump [bugreport from adt-3-r.zip]
Test: metrics_dump [bugreport from sabrina-q.gz]
Test: metrics_dump --widevine [adb shell dumpsys media.metrics output]
Change-Id: I82c7e723453ac2a6335cb2bb732a376d535b9ea3
2020-11-03 10:19:32 -08:00

174 lines
5.8 KiB
C++

// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
//
// Format mediadrm framework protobuf metrics
#include <fstream>
#include <iomanip>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include "metrics.pb.h"
namespace mediadrm_metrics {
using namespace android::drm_metrics;
using std::string;
using std::to_string;
const string kIndentPerLine = " ";
string FormatAttributes(const DrmFrameworkMetrics::Attributes& attributes) {
string result;
if (attributes.has_error_code()) {
result.append("error_code:");
result.append(to_string(attributes.error_code()));
}
if (attributes.has_key_status_type()) {
if (result.size()) result.append(",");
result.append("key_status_type:");
result.append(to_string(attributes.key_status_type()));
}
if (attributes.has_event_type()) {
if (result.size()) result.append(",");
result.append("event_type:");
result.append(to_string(attributes.event_type()));
}
if (result.size()) {
return string(" {") + result + "}";
} else {
return "";
}
}
string FormatCounter(const DrmFrameworkMetrics::Counter& cm) {
string result;
if (cm.has_count()) {
result = string("count=") + to_string(cm.count());
if (cm.has_attributes()) {
result.append(FormatAttributes(cm.attributes()));
}
}
return result;
}
string FormatDistributionMetric(
const DrmFrameworkMetrics::DistributionMetric& dm) {
string result;
if (dm.has_operation_count()) {
if (dm.operation_count() == 1) {
if (dm.has_mean()) {
std::ostringstream buffer;
buffer << dm.mean();
result += string("mean=") + buffer.str();
}
} else {
if (dm.has_min()) {
std::ostringstream buffer;
buffer << dm.min();
result = string("min=") + buffer.str();
}
if (dm.has_max()) {
std::ostringstream buffer;
buffer << dm.max();
if (result.size()) result.append(" ");
result += string("max=") + buffer.str();
}
if (dm.has_mean()) {
std::ostringstream buffer;
buffer << dm.mean();
if (result.size()) result.append(" ");
result += string("mean=") + buffer.str();
}
if (dm.has_variance()) {
std::ostringstream buffer;
buffer << dm.variance();
if (result.size()) result.append(" ");
result += string("variance=") + buffer.str();
}
if (dm.has_operation_count()) {
if (result.size()) result.append(" ");
result += string("count=") + to_string(dm.operation_count());
}
}
if (dm.has_attributes()) {
result.append(FormatAttributes(dm.attributes()));
}
}
return result;
}
#define FORMAT_REPEATED_DISTRIBUTION(NAME, INDENT) \
if (metrics.NAME##_size() == 1) { \
result.append(INDENT + #NAME + ": "); \
result.append(FormatDistributionMetric(metrics.NAME(0)) + "\n"); \
} else { \
for (int i = 0; i < metrics.NAME##_size(); i++) { \
result.append(INDENT + #NAME "[" + to_string(i) + "]: "); \
result.append(FormatDistributionMetric(metrics.NAME(i)) + "\n"); \
} \
}
#define FORMAT_REPEATED_COUNTER(NAME, INDENT) \
if (metrics.NAME##_size() == 1) { \
result.append(INDENT + #NAME ": "); \
result.append(FormatCounter(metrics.NAME(0)) + "\n"); \
} else { \
for (int i = 0; i < metrics.NAME##_size(); i++) { \
result.append(INDENT + #NAME "[" + to_string(i) + "]: "); \
result.append(FormatCounter(metrics.NAME(i)) + "\n"); \
} \
}
uint8_t hex2bin(char c) { return isdigit(c) ? c - '0' : tolower(c) - 'a' + 10; }
string hexdecode(string encoded) {
string result;
for (size_t i = 0; i < encoded.size(); i += 2) {
char c = hex2bin(encoded[i]) << 4 | hex2bin(encoded[i + 1]);
result += c;
}
return result;
}
string ms_to_seconds(uint64_t time_ms) {
uint64_t time_s = time_ms / 1000;
uint64_t ms = time_ms - time_s * 1000;
return to_string(time_s) + "." + to_string(ms);
}
void FormatDrmFrameworkMetrics(const DrmFrameworkMetrics& metrics,
string& result) {
string indent = kIndentPerLine;
result.append("mediadrm_metrics\n");
FORMAT_REPEATED_COUNTER(open_session_counter, indent);
FORMAT_REPEATED_COUNTER(close_session_counter, indent);
FORMAT_REPEATED_DISTRIBUTION(get_key_request_time_us, indent);
FORMAT_REPEATED_DISTRIBUTION(provide_key_response_time_us, indent);
FORMAT_REPEATED_COUNTER(get_provisioning_request_counter, indent);
FORMAT_REPEATED_COUNTER(provide_provisioning_response_counter, indent);
FORMAT_REPEATED_COUNTER(key_status_change_counter, indent);
FORMAT_REPEATED_COUNTER(event_callback_counter, indent);
FORMAT_REPEATED_COUNTER(get_device_unique_id_counter, indent);
size_t i = 0;
for (auto const& entry : metrics.session_lifetimes()) {
DrmFrameworkMetrics_SessionLifetime lifetime = entry.second;
if (lifetime.has_start_time_ms() && lifetime.has_end_time_ms()) {
result += indent + "session[" + to_string(++i) + "]: \"" +
hexdecode(entry.first) + "\"";
result +=
string(" start: ") + ms_to_seconds(lifetime.start_time_ms()) + " sec";
result += string(" duration: ") +
to_string(lifetime.end_time_ms() - lifetime.start_time_ms()) +
" ms\n";
}
}
}
}; // namespace mediadrm_metrics