Files
android/libwvdrmengine/tools/metrics_dump/src/metrics_dump.cpp
Edwin Wong 0ac0ee50eb Display menu if no argument is given.
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
2021-02-22 23:04:59 -08:00

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;
}