Loading media/libaaudio/src/core/AudioStream.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,12 @@ AudioStream::~AudioStream() { 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 Loading media/libmediametrics/include/MediaMetricsConstants.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading services/mediametrics/AudioAnalytics.cpp +142 −0 Original line number Diff line number Diff line Loading @@ -136,6 +136,25 @@ static constexpr const char * const AudioDeviceConnectionFields[] = { "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 }. Loading Loading @@ -192,6 +211,24 @@ AudioAnalytics::AudioAnalytics() }); })); // 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, Loading Loading @@ -843,4 +880,109 @@ void AudioAnalytics::DeviceConnection::expire() { } } 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 services/mediametrics/AudioAnalytics.h +23 −0 Original line number Diff line number Diff line Loading @@ -189,6 +189,29 @@ private: 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}; }; Loading services/mediametrics/AudioTypes.cpp +100 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,40 @@ const std::unordered_map<std::string, int32_t>& getAudioTrackTraitsMap() { 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) Loading Loading @@ -433,4 +467,70 @@ int32_t lookup<TRACK_TRAITS>(const std::string &traits) 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 Loading
media/libaaudio/src/core/AudioStream.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,12 @@ AudioStream::~AudioStream() { 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 Loading
media/libmediametrics/include/MediaMetricsConstants.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
services/mediametrics/AudioAnalytics.cpp +142 −0 Original line number Diff line number Diff line Loading @@ -136,6 +136,25 @@ static constexpr const char * const AudioDeviceConnectionFields[] = { "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 }. Loading Loading @@ -192,6 +211,24 @@ AudioAnalytics::AudioAnalytics() }); })); // 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, Loading Loading @@ -843,4 +880,109 @@ void AudioAnalytics::DeviceConnection::expire() { } } 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
services/mediametrics/AudioAnalytics.h +23 −0 Original line number Diff line number Diff line Loading @@ -189,6 +189,29 @@ private: 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}; }; Loading
services/mediametrics/AudioTypes.cpp +100 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,40 @@ const std::unordered_map<std::string, int32_t>& getAudioTrackTraitsMap() { 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) Loading Loading @@ -433,4 +467,70 @@ int32_t lookup<TRACK_TRAITS>(const std::string &traits) 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