MediaMetrics: Update dumpsys parameters
Make --prefix and --since work for analytics.
Test: adb shell dumpsys media.metrics --all
Test: adb shell dumpsys media.metrics --clear
Test: adb shell dumpsys media.metrics --heap
Test: adb shell dumpsys media.metrics --help
Test: adb shell dumpsys media.metrics --prefix c
Test: adb shell dumpsys media.metrics --prefix audio.volume
Test: adb shell dumpsys media.metrics --since -100
Test: adb shell dumpsys media.metrics --unreachable
Bug: 149850236
Change-Id: Id3e0cb6fe789027b5d5c86cce93ce07f636736bf
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index d76bc2c..b9703ba 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -207,69 +207,66 @@
return NO_ERROR;
}
+ static const String16 allOption("--all");
+ static const String16 clearOption("--clear");
static const String16 heapOption("--heap");
+ static const String16 helpOption("--help");
+ static const String16 prefixOption("--prefix");
+ static const String16 sinceOption("--since");
static const String16 unreachableOption("--unreachable");
+
+ bool all = false;
+ bool clear = false;
bool heap = false;
bool unreachable = false;
+ int64_t sinceNs = 0;
+ std::string prefix;
- const String16 protoOption("--proto");
- const String16 clearOption("--clear");
- bool clear = false;
- const String16 sinceOption("--since");
- nsecs_t ts_since = 0;
- const String16 helpOption("--help");
- const String16 onlyOption("--only");
- std::string only;
- const int n = args.size();
- for (int i = 0; i < n; i++) {
- if (args[i] == clearOption) {
+ const size_t n = args.size();
+ for (size_t i = 0; i < n; i++) {
+ if (args[i] == allOption) {
+ all = true;
+ } else if (args[i] == clearOption) {
clear = true;
} else if (args[i] == heapOption) {
heap = true;
- } else if (args[i] == protoOption) {
- i++;
- if (i < n) {
- // ignore
- } else {
- result.append("missing value for -proto\n\n");
- }
- } else if (args[i] == sinceOption) {
- i++;
- if (i < n) {
- String8 value(args[i]);
- char *endp;
- const char *p = value.string();
- ts_since = strtoll(p, &endp, 10);
- if (endp == p || *endp != '\0') {
- ts_since = 0;
- }
- } else {
- ts_since = 0;
- }
- // command line is milliseconds; internal units are nano-seconds
- ts_since *= NANOS_PER_MILLISECOND;
- } else if (args[i] == onlyOption) {
- i++;
- if (i < n) {
- String8 value(args[i]);
- only = value.string();
- }
} else if (args[i] == helpOption) {
// TODO: consider function area dumping.
// dumpsys media.metrics audiotrack,codec
// or dumpsys media.metrics audiotrack codec
result.append("Recognized parameters:\n");
- result.append("--heap heap usage (top 100)\n");
- result.append("--help this help message\n");
- result.append("--proto # dump using protocol #");
- result.append("--clear clears out saved records\n");
- result.append("--only X process records for component X\n");
- result.append("--since X include records since X\n");
- result.append(" (X is milliseconds since the UNIX epoch)\n");
- result.append("--unreachable unreachable memory (leaks)\n");
+ result.append("--all show all records\n");
+ result.append("--clear clear out saved records\n");
+ result.append("--heap show heap usage (top 100)\n");
+ result.append("--help display help\n");
+ result.append("--prefix X process records for component X\n");
+ result.append("--since X X < 0: records from -X seconds in the past\n");
+ result.append(" X = 0: ignore\n");
+ result.append(" X > 0: records from X seconds since Unix epoch\n");
+ result.append("--unreachable show unreachable memory (leaks)\n");
write(fd, result.string(), result.size());
return NO_ERROR;
+ } else if (args[i] == prefixOption) {
+ ++i;
+ if (i < n) {
+ prefix = String8(args[i]).string();
+ }
+ } else if (args[i] == sinceOption) {
+ ++i;
+ if (i < n) {
+ String8 value(args[i]);
+ char *endp;
+ const char *p = value.string();
+ long long sec = strtoll(p, &endp, 10);
+ if (endp == p || *endp != '\0' || sec == 0) {
+ sinceNs = 0;
+ } else if (sec < 0) {
+ sinceNs = systemTime(SYSTEM_TIME_REALTIME) + sec * NANOS_PER_SECOND;
+ } else {
+ sinceNs = sec * NANOS_PER_SECOND;
+ }
+ }
} else if (args[i] == unreachableOption) {
unreachable = true;
}
@@ -278,21 +275,23 @@
{
std::lock_guard _l(mLock);
- result.appendFormat("Dump of the %s process:\n", kServiceName);
- dumpHeaders_l(result, ts_since);
- dumpRecent_l(result, ts_since, only.c_str());
-
if (clear) {
mItemsDiscarded += mItems.size();
mItems.clear();
- // shall we clear the summary data too?
- }
- // TODO: maybe consider a better way of dumping audio analytics info.
- constexpr int32_t linesToDump = 1000;
- auto [ dumpString, lines ] = mAudioAnalytics.dump(linesToDump);
- result.append(dumpString.c_str());
- if (lines == linesToDump) {
- result.append("-- some lines may be truncated --\n");
+ mAudioAnalytics.clear();
+ } else {
+ result.appendFormat("Dump of the %s process:\n", kServiceName);
+ const char *prefixptr = prefix.size() > 0 ? prefix.c_str() : nullptr;
+ dumpHeaders_l(result, sinceNs, prefixptr);
+ dumpQueue_l(result, sinceNs, prefixptr);
+
+ // TODO: maybe consider a better way of dumping audio analytics info.
+ const int32_t linesToDump = all ? INT32_MAX : 1000;
+ auto [ dumpString, lines ] = mAudioAnalytics.dump(linesToDump, sinceNs, prefixptr);
+ result.append(dumpString.c_str());
+ if (lines == linesToDump) {
+ result.append("-- some lines may be truncated --\n");
+ }
}
}
write(fd, result.string(), result.size());
@@ -313,7 +312,7 @@
}
// dump headers
-void MediaMetricsService::dumpHeaders_l(String8 &result, nsecs_t ts_since)
+void MediaMetricsService::dumpHeaders_l(String8 &result, int64_t sinceNs, const char* prefix)
{
if (mediametrics::Item::isEnabled()) {
result.append("Metrics gathering: enabled\n");
@@ -327,54 +326,36 @@
"Records Discarded: %lld (by Count: %lld by Expiration: %lld)\n",
(long long)mItemsDiscarded, (long long)mItemsDiscardedCount,
(long long)mItemsDiscardedExpire);
- if (ts_since != 0) {
+ if (prefix != nullptr) {
+ result.appendFormat("Restricting to prefix %s", prefix);
+ }
+ if (sinceNs != 0) {
result.appendFormat(
"Emitting Queue entries more recent than: %lld\n",
- (long long)ts_since);
+ (long long)sinceNs);
}
}
-void MediaMetricsService::dumpRecent_l(
- String8 &result, nsecs_t ts_since, const char * only)
+// TODO: should prefix be a set<string>?
+void MediaMetricsService::dumpQueue_l(String8 &result, int64_t sinceNs, const char* prefix)
{
- if (only != nullptr && *only == '\0') {
- only = nullptr;
- }
- result.append("\nFinalized Metrics (oldest first):\n");
- dumpQueue_l(result, ts_since, only);
-
- // show who is connected and injecting records?
- // talk about # records fed to the 'readers'
- // talk about # records we discarded, perhaps "discarded w/o reading" too
-}
-
-void MediaMetricsService::dumpQueue_l(String8 &result) {
- dumpQueue_l(result, (nsecs_t) 0, nullptr /* only */);
-}
-
-void MediaMetricsService::dumpQueue_l(
- String8 &result, nsecs_t ts_since, const char * only) {
- int slot = 0;
-
if (mItems.empty()) {
result.append("empty\n");
- } else {
- for (const auto &item : mItems) {
- nsecs_t when = item->getTimestamp();
- if (when < ts_since) {
- continue;
- }
- // TODO: Only should be a set<string>
- if (only != nullptr &&
- item->getKey() /* std::string */ != only) {
- ALOGV("%s: omit '%s', it's not '%s'",
- __func__, item->getKey().c_str(), only);
- continue;
- }
- result.appendFormat("%5d: %s\n",
- slot, item->toString().c_str());
- slot++;
+ return;
+ }
+
+ int slot = 0;
+ for (const auto &item : mItems) { // TODO: consider std::lower_bound() on mItems
+ if (item->getTimestamp() < sinceNs) { // sinceNs == 0 means all items shown
+ continue;
}
+ if (prefix != nullptr && !startsWith(item->getKey(), prefix)) {
+ ALOGV("%s: omit '%s', it's not '%s'",
+ __func__, item->getKey().c_str(), prefix);
+ continue;
+ }
+ result.appendFormat("%5d: %s\n", slot, item->toString().c_str());
+ slot++;
}
}