If not argument is given, the app just sits and wait for stdin input, this can be confusing for the user. Add logic to display menu if no argument is given. Test: metrics_dump display menu Test: metrics_dump [bugreport from sabrina-q.gz] display mediadrm and widevine metrics Test: metrics_dump --mediadrm [adb shell dumpsys media.metrics output] display mediadrm metrics Test: metrics_dump --widevine [adb shell dumpsys media.metrics output] display widevine metrics Test: metrics_dump [bugreport from sabrina-q.gz] --widevine display menu because the order is app_name, options, input file Bug: 180983850 Change-Id: I9b35f782d8f59663661148d3950f89e4724b6bce Merged-In: I9b35f782d8f59663661148d3950f89e4724b6bce
198 lines
6.1 KiB
C++
198 lines
6.1 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 metric output from |adb shell dumpsys media.metrics|
|
|
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
#include "base64decode.h"
|
|
#include "mediadrm_metrics.h"
|
|
#include "parse_metrics.h"
|
|
#include "wv_metrics.h"
|
|
|
|
namespace metrics_dump {
|
|
|
|
using namespace base64;
|
|
using namespace wv_metrics;
|
|
using std::cerr;
|
|
using std::cout;
|
|
using std::endl;
|
|
using std::string;
|
|
using std::vector;
|
|
|
|
string selected_one;
|
|
std::vector<string> excluded_ones;
|
|
|
|
// Look for metrics pattern
|
|
// q-metrics:
|
|
// [:item:item:]
|
|
// r-metrics:
|
|
// {item, (item), (item)}
|
|
//
|
|
// @return true if metrics is formatted prior to R release
|
|
bool is_q_metrics(const string &line) {
|
|
int left_brackets = std::count(line.begin(), line.end(), '[');
|
|
int right_brackets = std::count(line.begin(), line.end(), ']');
|
|
return (left_brackets == 1 && right_brackets == 1 &&
|
|
line.find('(') == string::npos && line.find(')') == string::npos);
|
|
}
|
|
|
|
// Process one line of metrics
|
|
void process_one_metric(const string &line) {
|
|
std::istringstream fields(line);
|
|
|
|
MediaMetrics metrics;
|
|
parse_metrics(line, &metrics);
|
|
|
|
// handle specific package and component selection
|
|
if (selected_one.size() && metrics.package != selected_one &&
|
|
metrics.component != selected_one) {
|
|
return;
|
|
}
|
|
if (std::find(excluded_ones.begin(), excluded_ones.end(), metrics.package) !=
|
|
excluded_ones.end()) {
|
|
return;
|
|
}
|
|
if (std::find(excluded_ones.begin(), excluded_ones.end(),
|
|
metrics.component) != excluded_ones.end()) {
|
|
return;
|
|
}
|
|
|
|
cout << "===================================================================="
|
|
"============="
|
|
<< endl;
|
|
if (is_q_metrics(line)) {
|
|
char timebuf[128];
|
|
time_t time_s = stoll(metrics.timestamp) / 1000000000LL;
|
|
strftime(timebuf, sizeof(timebuf), "%a %b %e %H:%M:%S", localtime(&time_s));
|
|
cout << timebuf << " timestamp: " << time_s << endl << endl;
|
|
} else {
|
|
cout << metrics.timestamp << endl << endl;
|
|
}
|
|
cout << " "
|
|
<< "APK PACKAGE -> METRICS COMPONENT" << endl;
|
|
cout << " " << metrics.package << " -> " << metrics.component << endl;
|
|
cout << "\tuid:" << metrics.uid << " pid:" << metrics.pid << endl;
|
|
|
|
for (auto property : metrics.properties) {
|
|
string key = property.first;
|
|
string value = property.second;
|
|
if (key == "serialized_metrics") {
|
|
string decoded = Base64::Decode(value);
|
|
if (metrics.component == "drm.vendor.google.widevinecdm") {
|
|
drm_metrics::WvCdmMetrics wv_metrics;
|
|
if (!wv_metrics.ParseFromString(decoded)) {
|
|
cerr << "failed to parse proto string" << endl;
|
|
} else {
|
|
string result;
|
|
FormatWvCdmMetrics(wv_metrics, result);
|
|
cout << endl << result << endl;
|
|
}
|
|
} else {
|
|
android::drm_metrics::DrmFrameworkMetrics fw_metrics;
|
|
if (!fw_metrics.ParseFromString(decoded)) {
|
|
cerr << "failed to parse proto string" << endl;
|
|
} else {
|
|
string result;
|
|
mediadrm_metrics::FormatDrmFrameworkMetrics(fw_metrics, result);
|
|
cout << endl << result << endl;
|
|
}
|
|
}
|
|
} else {
|
|
cout << " " << key << ": " << value << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
void process_metrics(std::istream &instream) {
|
|
string line;
|
|
while (std::getline(instream, line)) {
|
|
if (line.find("serialized_metrics") != string::npos) {
|
|
process_one_metric(line);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace metrics_dump
|
|
|
|
using std::cerr;
|
|
using std::endl;
|
|
using std::string;
|
|
|
|
void exit_with_menu() {
|
|
cerr << "usage: metrics_dump [options] [<bugreport>]" << endl;
|
|
cerr << endl;
|
|
cerr << "Displays the drm metrics that are generated by" << endl;
|
|
cerr << "adb shell dumpsys media.metrics. Input may be from a file" << endl;
|
|
cerr << "such as a bugreport, or from stdin." << endl;
|
|
cerr << endl;
|
|
cerr << "options:" << endl;
|
|
cerr << " --no-gms" << endl;
|
|
cerr << " ignore metrics from package com.google.android.gms" << endl;
|
|
cerr << " which are generated frequently by droidguard" << endl;
|
|
cerr << " --widevine" << endl;
|
|
cerr << " show only widevine metrics, "
|
|
"component=drm.vendor.Google.WidevineCDM"
|
|
<< endl;
|
|
cerr << " --mediadrm" << endl;
|
|
cerr << " show only framework drm metrics, component=mediadrm" << endl;
|
|
cerr << " --exclude <package>|<component>" << endl;
|
|
cerr << " ignore metrics from the specified package or component"
|
|
<< endl;
|
|
cerr << " --select <package>|<component>" << endl;
|
|
cerr << " only show metrics from the specified package or component"
|
|
<< endl;
|
|
exit(0);
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
// Verify that the version of the library that we linked against is
|
|
// compatible with the version of the headers we compiled against.
|
|
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
|
|
|
int i = 1;
|
|
if (argc == 1) exit_with_menu();
|
|
while (i < argc) {
|
|
string arg = argv[i];
|
|
if (arg == "--help") {
|
|
exit_with_menu();
|
|
} else if (arg == "--no-gms") {
|
|
metrics_dump::excluded_ones.push_back("com.google.android.gms");
|
|
} else if (arg == "--widevine") {
|
|
metrics_dump::selected_one = "drm.vendor.google.widevinecdm";
|
|
} else if (arg == "--mediadrm") {
|
|
metrics_dump::selected_one = "mediadrm";
|
|
} else if (i == argc - 1) {
|
|
std::ifstream bugfile(argv[i]);
|
|
if (bugfile.is_open()) {
|
|
metrics_dump::process_metrics(bugfile);
|
|
bugfile.close();
|
|
} else {
|
|
cerr << "unable to open input file " << argv[i] << endl;
|
|
}
|
|
break;
|
|
} else {
|
|
// args with a parameter
|
|
if (arg == "--exclude") {
|
|
string lowercase_argv = argv[++i];
|
|
metrics_dump::to_lower(lowercase_argv);
|
|
metrics_dump::excluded_ones.push_back(lowercase_argv);
|
|
} else if (arg == "--select") {
|
|
metrics_dump::selected_one = argv[++i];
|
|
metrics_dump::to_lower(metrics_dump::selected_one);
|
|
} else {
|
|
exit_with_menu();
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
if (i == argc) {
|
|
metrics_dump::process_metrics(std::cin);
|
|
}
|
|
return 0;
|
|
}
|