[ Merge of http://go/wvgerrit/59022 ] Android metrics are output by the adb shell command |dumpsys media.metrics|. They appear in bugreports and can also be requested interactively. Both the widevine and framework mediadrm metrics are base64 encoded protobufs detailing each of the metrics items. This tool prints them in a readable format. Test: wv android unit/integration tests Change-Id: Id1bc05b34693a3ca44dd3872a28a2337b3ce4d79
174 lines
5.8 KiB
C++
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 Master
|
|
// License Agreement.
|
|
//
|
|
// Format mediadrm framework protobuf metrics
|
|
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
#include "mediadrm_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
|