MediaMetrics: Collect report for aaudio stream
Test: adb shell dumpsys media.metrics
Test: statsd_testdrive
Bug: 171345744
Change-Id: I71f5ab0d80334c26ac709df9853fcded4a519ab7
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 431f0fa..a4beaf4 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -56,6 +56,12 @@
ALOGE_IF(mHasThread, "%s() callback thread never join()ed", __func__);
+ if (!mMetricsId.empty()) {
+ android::mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM)
+ .record();
+ }
+
// If the stream is deleted when OPEN or in use then audio resources will leak.
// This would indicate an internal error. So we want to find this ASAP.
LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index 84388c9..2af7eee 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -170,6 +170,7 @@
#define AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR "ctor"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT "disconnect"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR "dtor"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM "endAAudioStream" // AAudioStream
#define AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP "endAudioIntervalGroup"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_FLUSH "flush" // AudioTrack
#define AMEDIAMETRICS_PROP_EVENT_VALUE_INVALIDATE "invalidate" // server track, record
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index d78d1e3..3b2de76 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -136,6 +136,25 @@
"connection_count",
};
+// static constexpr const char * const AAudioStreamFields[] {
+// "mediametrics_aaudiostream_reported",
+// "caller_name",
+// "path",
+// "direction",
+// "frames_per_burst",
+// "buffer_size",
+// "buffer_capacity",
+// "channel_count",
+// "total_frames_transferred",
+// "perf_mode_requested",
+// "perf_mode_actual",
+// "sharing",
+// "xrun_count",
+// "device_type",
+// "format_app",
+// "format_device",
+// };
+
/**
* sendToStatsd is a helper method that sends the arguments to statsd
* and returns a pair { result, summary_string }.
@@ -192,6 +211,24 @@
});
}));
+ // Handle legacy aaudio stream statistics
+ mActions.addAction(
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
+ std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
+ std::make_shared<AnalyticsActions::Function>(
+ [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
+ mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
+ }));
+
+ // Handle mmap aaudio stream statistics
+ mActions.addAction(
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*." AMEDIAMETRICS_PROP_EVENT,
+ std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
+ std::make_shared<AnalyticsActions::Function>(
+ [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
+ mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_MMAP);
+ }));
+
// Handle device use record statistics
mActions.addAction(
AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
@@ -843,4 +880,109 @@
}
}
+void AudioAnalytics::AAudioStreamInfo::endAAudioStream(
+ const std::shared_ptr<const android::mediametrics::Item> &item, CallerPath path) const {
+ const std::string& key = item->getKey();
+
+ std::string callerNameStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_CALLERNAME, &callerNameStr);
+
+ const auto callerName = types::lookup<types::CALLER_NAME, int32_t>(callerNameStr);
+
+ std::string directionStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_DIRECTION, &directionStr);
+ const auto direction = types::lookup<types::AAUDIO_DIRECTION, int32_t>(directionStr);
+
+ int32_t framesPerBurst = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_BURSTFRAMES, &framesPerBurst);
+
+ int32_t bufferSizeInFrames = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, &bufferSizeInFrames);
+
+ int32_t bufferCapacityInFrames = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, &bufferCapacityInFrames);
+
+ int32_t channelCount = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_CHANNELCOUNT, &channelCount);
+
+ int64_t totalFramesTransferred = -1;
+ // TODO: log and get total frames transferred
+
+ std::string perfModeRequestedStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_PERFORMANCEMODE, &perfModeRequestedStr);
+ const auto perfModeRequested =
+ types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeRequestedStr);
+
+ int32_t perfModeActual = 0;
+ // TODO: log and get actual performance mode
+
+ std::string sharingModeStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_SHARINGMODE, &sharingModeStr);
+ const auto sharingMode = types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeStr);
+
+ int32_t xrunCount = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_UNDERRUN, &xrunCount);
+
+ std::string deviceType;
+ // TODO: only routed device id is logged, but no device type
+
+ int32_t formatApp = 0;
+ // TODO: log format from app
+
+ std::string formatDeviceStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_ENCODING, &formatDeviceStr);
+ const auto formatDevice = types::lookup<types::ENCODING, int32_t>(formatDeviceStr);
+
+ LOG(LOG_LEVEL) << "key:" << key
+ << " caller_name:" << callerName << "(" << callerNameStr << ")"
+ << " path:" << path
+ << " direction:" << direction << "(" << directionStr << ")"
+ << " frames_per_burst:" << framesPerBurst
+ << " buffer_size:" << bufferSizeInFrames
+ << " buffer_capacity:" << bufferCapacityInFrames
+ << " channel_count:" << channelCount
+ << " total_frames_transferred:" << totalFramesTransferred
+ << " perf_mode_requested:" << perfModeRequested << "(" << perfModeRequestedStr << ")"
+ << " perf_mode_actual:" << perfModeActual
+ << " sharing:" << sharingMode << "(" << sharingModeStr << ")"
+ << " xrun_count:" << xrunCount
+ << " device_type:" << deviceType
+ << " format_app:" << formatApp
+ << " format_device: " << formatDevice << "(" << formatDeviceStr << ")";
+
+ // TODO: send the metric to statsd when the proto is ready
+ // if (mAudioAnalytics.mDeliverStatistics) {
+ // const auto [ result, str ] = sendToStatsd(AAudioStreamFields,
+ // CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
+ // , callerName
+ // , path
+ // , direction
+ // , framesPerBurst
+ // , bufferSizeInFrames
+ // , bufferCapacityInFrames
+ // , channelCount
+ // , totalFramesTransferred
+ // , perfModeRequested
+ // , perfModeActual
+ // , sharingMode
+ // , xrunCount
+ // , deviceType.c_str()
+ // , formatApp
+ // , formatDevice
+ // );
+ // ALOGV("%s: statsd %s", __func__, str.c_str());
+ // mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
+ // }
+}
+
} // namespace android::mediametrics
diff --git a/services/mediametrics/AudioAnalytics.h b/services/mediametrics/AudioAnalytics.h
index df097b1..07872ef 100644
--- a/services/mediametrics/AudioAnalytics.h
+++ b/services/mediametrics/AudioAnalytics.h
@@ -189,6 +189,29 @@
int32_t mA2dpConnectionUnknowns GUARDED_BY(mLock) = 0;
} mDeviceConnection{*this};
+ // AAudioStreamInfo is a nested class which collect aaudio stream info from both client and
+ // server side.
+ class AAudioStreamInfo {
+ public:
+ // All the enum here must be kept the same as the ones defined in atoms.proto
+ enum CallerPath {
+ CALLER_PATH_UNKNOWN = 0,
+ CALLER_PATH_LEGACY = 1,
+ CALLER_PATH_MMAP = 2,
+ };
+
+ explicit AAudioStreamInfo(AudioAnalytics &audioAnalytics)
+ : mAudioAnalytics(audioAnalytics) {}
+
+ void endAAudioStream(
+ const std::shared_ptr<const android::mediametrics::Item> &item,
+ CallerPath path) const;
+
+ private:
+
+ AudioAnalytics &mAudioAnalytics;
+ } mAAudioStreamInfo{*this};
+
AudioPowerUsage mAudioPowerUsage{this};
};
diff --git a/services/mediametrics/AudioTypes.cpp b/services/mediametrics/AudioTypes.cpp
index 5d044bb..44e96ec 100644
--- a/services/mediametrics/AudioTypes.cpp
+++ b/services/mediametrics/AudioTypes.cpp
@@ -154,6 +154,40 @@
return map;
}
+const std::unordered_map<std::string, int32_t>& getAAudioDirection() {
+ // DO NOT MODIFY VALUES(OK to add new ones).
+ // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
+ static std::unordered_map<std::string, int32_t> map {
+ // UNKNOWN is -1
+ {"AAUDIO_DIRECTION_OUTPUT", 0},
+ {"AAUDIO_DIRECTION_INPUT", 1},
+ };
+ return map;
+}
+
+const std::unordered_map<std::string, int32_t>& getAAudioPerformanceMode() {
+ // DO NOT MODIFY VALUES(OK to add new ones).
+ // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
+ static std::unordered_map<std::string, int32_t> map {
+ // UNKNOWN is -1
+ {"AAUDIO_PERFORMANCE_MODE_NONE", 10},
+ {"AAUDIO_PERFORMANCE_MODE_POWER_SAVING", 11},
+ {"AAUDIO_PERFORMANCE_MODE_LOW_LATENCY", 12},
+ };
+ return map;
+}
+
+const std::unordered_map<std::string, int32_t>& getAAudioSharingMode() {
+ // DO NOT MODIFY VALUES(OK to add new ones).
+ // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
+ static std::unordered_map<std::string, int32_t> map {
+ // UNKNOWN is -1
+ {"AAUDIO_SHARING_MODE_EXCLUSIVE", 0},
+ {"AAUDIO_SHARING_MODE_SHARED", 1},
+ };
+ return map;
+}
+
// Helper: Create the corresponding int32 from string flags split with '|'.
template <typename Traits>
int32_t int32FromFlags(const std::string &flags)
@@ -433,4 +467,70 @@
return flagsFromMap(traits, getAudioTrackTraitsMap());
}
+template <>
+std::string lookup<AAUDIO_DIRECTION>(const std::string &direction)
+{
+ auto& map = getAAudioDirection();
+ auto it = map.find(direction);
+ if (it == map.end()) {
+ return "";
+ }
+ return direction;
+}
+
+template <>
+int32_t lookup<AAUDIO_DIRECTION>(const std::string &direction)
+{
+ auto& map = getAAudioDirection();
+ auto it = map.find(direction);
+ if (it == map.end()) {
+ return -1; // return unknown
+ }
+ return it->second;
+}
+
+template <>
+std::string lookup<AAUDIO_PERFORMANCE_MODE>(const std::string &performanceMode)
+{
+ auto& map = getAAudioPerformanceMode();
+ auto it = map.find(performanceMode);
+ if (it == map.end()) {
+ return "";
+ }
+ return performanceMode;
+}
+
+template <>
+int32_t lookup<AAUDIO_PERFORMANCE_MODE>(const std::string &performanceMode)
+{
+ auto& map = getAAudioPerformanceMode();
+ auto it = map.find(performanceMode);
+ if (it == map.end()) {
+ return -1; // return unknown
+ }
+ return it->second;
+}
+
+template <>
+std::string lookup<AAUDIO_SHARING_MODE>(const std::string &sharingMode)
+{
+ auto& map = getAAudioSharingMode();
+ auto it = map.find(sharingMode);
+ if (it == map.end()) {
+ return "";
+ }
+ return sharingMode;
+}
+
+template <>
+int32_t lookup<AAUDIO_SHARING_MODE>(const std::string &sharingMode)
+{
+ auto& map = getAAudioSharingMode();
+ auto it = map.find(sharingMode);
+ if (it == map.end()) {
+ return -1; // return unknown
+ }
+ return it->second;
+}
+
} // namespace android::mediametrics::types
diff --git a/services/mediametrics/AudioTypes.h b/services/mediametrics/AudioTypes.h
index e1deeb1..4394d79 100644
--- a/services/mediametrics/AudioTypes.h
+++ b/services/mediametrics/AudioTypes.h
@@ -40,6 +40,9 @@
// Enumeration for all the string translations to integers (generally int32_t) unless noted.
enum AudioEnumCategory {
+ AAUDIO_DIRECTION,
+ AAUDIO_PERFORMANCE_MODE,
+ AAUDIO_SHARING_MODE,
CALLER_NAME,
CONTENT_TYPE,
ENCODING,