periodically push AudioFlinger thread statistics to media metrics
Test: dumpsys media.metrics
Bug: 68148948
Change-Id: I9b1538a8cff3f89f4689dceda800132349338a0d
diff --git a/media/libnblog/ReportPerformance.cpp b/media/libnblog/ReportPerformance.cpp
index 98e11cd..aab67c6 100644
--- a/media/libnblog/ReportPerformance.cpp
+++ b/media/libnblog/ReportPerformance.cpp
@@ -29,6 +29,7 @@
#include <sys/time.h>
#include <utility>
#include <json/json.h>
+#include <media/MediaAnalyticsItem.h>
#include <media/nblog/NBLog.h>
#include <media/nblog/PerformanceAnalysis.h>
#include <media/nblog/ReportPerformance.h>
@@ -37,6 +38,8 @@
namespace android {
+namespace ReportPerformance {
+
std::unique_ptr<Json::Value> dumpToJson(const PerformanceData& data)
{
std::unique_ptr<Json::Value> rootPtr = std::make_unique<Json::Value>(Json::objectValue);
@@ -54,16 +57,76 @@
return rootPtr;
}
-//------------------------------------------------------------------------------
+bool sendToMediaMetrics(const PerformanceData& data)
+{
+ // See documentation for these metrics here:
+ // docs.google.com/document/d/11--6dyOXVOpacYQLZiaOY5QVtQjUyqNx2zT9cCzLKYE/edit?usp=sharing
+ static constexpr char kThreadType[] = "android.media.audiothread.type";
+ static constexpr char kThreadFrameCount[] = "android.media.audiothread.framecount";
+ static constexpr char kThreadSampleRate[] = "android.media.audiothread.samplerate";
+ static constexpr char kThreadWorkHist[] = "android.media.audiothread.workMs.hist";
+ static constexpr char kThreadLatencyHist[] = "android.media.audiothread.latencyMs.hist";
+ static constexpr char kThreadWarmupHist[] = "android.media.audiothread.warmupMs.hist";
+ static constexpr char kThreadUnderruns[] = "android.media.audiothread.underruns";
+ static constexpr char kThreadOverruns[] = "android.media.audiothread.overruns";
+ static constexpr char kThreadActive[] = "android.media.audiothread.activeMs";
+ static constexpr char kThreadDuration[] = "android.media.audiothread.durationMs";
-namespace ReportPerformance {
+ std::unique_ptr<MediaAnalyticsItem> item(new MediaAnalyticsItem("audiothread"));
+
+ const Histogram &workHist = data.workHist;
+ if (workHist.totalCount() > 0) {
+ item->setCString(kThreadWorkHist, workHist.toString().c_str());
+ }
+
+ const Histogram &latencyHist = data.latencyHist;
+ if (latencyHist.totalCount() > 0) {
+ item->setCString(kThreadLatencyHist, latencyHist.toString().c_str());
+ }
+
+ const Histogram &warmupHist = data.warmupHist;
+ if (warmupHist.totalCount() > 0) {
+ item->setCString(kThreadWarmupHist, warmupHist.toString().c_str());
+ }
+
+ if (data.underruns > 0) {
+ item->setInt64(kThreadUnderruns, data.underruns);
+ }
+
+ if (data.overruns > 0) {
+ item->setInt64(kThreadOverruns, data.overruns);
+ }
+
+ // Send to Media Metrics if the record is not empty.
+ // The thread and time info are added inside the if statement because
+ // we want to send them only if there are performance metrics to send.
+ if (item->count() > 0) {
+ // Add thread info fields.
+ const int type = data.type;
+ // TODO have a int-to-string mapping defined somewhere else for other thread types.
+ if (type == 2) {
+ item->setCString(kThreadType, "FASTMIXER");
+ } else {
+ item->setCString(kThreadType, "UNKNOWN");
+ }
+ item->setInt32(kThreadFrameCount, data.frameCount);
+ item->setInt32(kThreadSampleRate, data.sampleRate);
+ // Add time info fields.
+ item->setInt64(kThreadActive, data.active / 1000000);
+ item->setInt64(kThreadDuration, (systemTime() - data.start) / 1000000);
+ return item->selfrecord();
+ }
+ return false;
+}
+
+//------------------------------------------------------------------------------
// TODO: use a function like this to extract logic from writeToFile
// https://stackoverflow.com/a/9279620
// Writes outlier intervals, timestamps, and histograms spanning long time intervals to file.
// TODO: write data in binary format
-void writeToFile(const std::deque<std::pair<timestamp, Histogram>> &hists,
+void writeToFile(const std::deque<std::pair<timestamp, Hist>> &hists,
const std::deque<std::pair<msInterval, timestamp>> &outlierData,
const std::deque<timestamp> &peakTimestamps,
const char * directory, bool append, int author, log_hash_t hash) {