| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2019 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | //#define LOG_NDEBUG 0 | 
 | 18 | #define LOG_TAG "AudioAnalytics" | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 19 | #include <android-base/logging.h> | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 20 | #include <utils/Log.h> | 
 | 21 |  | 
 | 22 | #include "AudioAnalytics.h" | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 23 |  | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 24 | #include <audio_utils/clock.h>    // clock conversions | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 25 | #include <cutils/properties.h> | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 26 | #include <statslog.h>             // statsd | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 27 |  | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 28 | #include "AudioTypes.h"           // string to int conversions | 
 | 29 | #include "MediaMetricsService.h"  // package info | 
 | 30 | #include "StringUtils.h" | 
 | 31 |  | 
 | 32 | #define PROP_AUDIO_ANALYTICS_CLOUD_ENABLED "persist.audio.analytics.cloud.enabled" | 
 | 33 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 34 | namespace android::mediametrics { | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 35 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 36 | // Enable for testing of delivery to statsd. Caution if this is enabled, all protos MUST exist. | 
| Andy Hung | a0a5ad2 | 2020-06-12 09:30:34 -0700 | [diff] [blame] | 37 | #define STATSD_ENABLE | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 38 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 39 | #ifdef STATSD_ENABLE | 
 | 40 | #define CONDITION(INT_VALUE) (INT_VALUE)  // allow value | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 41 | #else | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 42 | #define CONDITION(INT_VALUE) (int(0))     // mask value since the proto may not be defined yet. | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 43 | #endif | 
 | 44 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 45 | // Maximum length of a device name. | 
| Andy Hung | 3deef2b | 2020-07-17 12:58:54 -0700 | [diff] [blame] | 46 | // static constexpr size_t STATSD_DEVICE_NAME_MAX_LENGTH = 32; // unused since we suppress | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 47 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 48 | // Transmit Enums to statsd in integer or strings  (this must match the atoms.proto) | 
 | 49 | static constexpr bool STATSD_USE_INT_FOR_ENUM = false; | 
 | 50 |  | 
 | 51 | // derive types based on integer or strings. | 
 | 52 | using short_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int32_t, std::string>; | 
 | 53 | using long_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int64_t, std::string>; | 
 | 54 |  | 
 | 55 | // Convert std::string to char * | 
 | 56 | template <typename T> | 
 | 57 | auto ENUM_EXTRACT(const T& x) { | 
 | 58 |     if constexpr (std::is_same_v<std::decay_t<T>, std::string>) { | 
 | 59 |         return x.c_str(); | 
 | 60 |     } else { | 
 | 61 |         return x; | 
 | 62 |     } | 
 | 63 | } | 
 | 64 |  | 
 | 65 | static constexpr const auto LOG_LEVEL = android::base::VERBOSE; | 
 | 66 |  | 
| Andy Hung | b18f506 | 2020-06-18 23:10:08 -0700 | [diff] [blame] | 67 | static constexpr int PREVIOUS_STATE_EXPIRE_SEC = 60 * 60; // 1 hour. | 
 | 68 |  | 
| Andy Hung | 3deef2b | 2020-07-17 12:58:54 -0700 | [diff] [blame] | 69 | static constexpr const char * SUPPRESSED = "SUPPRESSED"; | 
 | 70 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 71 | /* | 
 | 72 |  * For logging purposes, we list all of the MediaMetrics atom fields, | 
 | 73 |  * which can then be associated with consecutive arguments to the statsd write. | 
 | 74 |  */ | 
 | 75 |  | 
 | 76 | static constexpr const char * const AudioRecordDeviceUsageFields[] = { | 
 | 77 |     "mediametrics_audiorecorddeviceusage_reported", // proto number | 
 | 78 |     "devices", | 
 | 79 |     "device_names", | 
 | 80 |     "device_time_nanos", | 
 | 81 |     "encoding", | 
 | 82 |     "frame_count", | 
 | 83 |     "interval_count", | 
 | 84 |     "sample_rate", | 
 | 85 |     "flags", | 
 | 86 |     "package_name", | 
 | 87 |     "selected_device_id", | 
 | 88 |     "caller", | 
 | 89 |     "source", | 
| Andy Hung | cbcfaa2 | 2021-02-23 13:54:49 -0800 | [diff] [blame^] | 90 |     "log_session_id", | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 91 | }; | 
 | 92 |  | 
 | 93 | static constexpr const char * const AudioThreadDeviceUsageFields[] = { | 
 | 94 |     "mediametrics_audiothreaddeviceusage_reported", | 
 | 95 |     "devices", | 
 | 96 |     "device_names", | 
 | 97 |     "device_time_nanos", | 
 | 98 |     "encoding", | 
 | 99 |     "frame_count", | 
 | 100 |     "interval_count", | 
 | 101 |     "sample_rate", | 
 | 102 |     "flags", | 
 | 103 |     "xruns", | 
 | 104 |     "type", | 
 | 105 | }; | 
 | 106 |  | 
 | 107 | static constexpr const char * const AudioTrackDeviceUsageFields[] = { | 
 | 108 |     "mediametrics_audiotrackdeviceusage_reported", | 
 | 109 |     "devices", | 
 | 110 |     "device_names", | 
 | 111 |     "device_time_nanos", | 
 | 112 |     "encoding", | 
 | 113 |     "frame_count", | 
 | 114 |     "interval_count", | 
 | 115 |     "sample_rate", | 
 | 116 |     "flags", | 
 | 117 |     "xruns", | 
 | 118 |     "package_name", | 
 | 119 |     "device_latency_millis", | 
 | 120 |     "device_startup_millis", | 
 | 121 |     "device_volume", | 
 | 122 |     "selected_device_id", | 
 | 123 |     "stream_type", | 
 | 124 |     "usage", | 
 | 125 |     "content_type", | 
 | 126 |     "caller", | 
 | 127 |     "traits", | 
| Andy Hung | cbcfaa2 | 2021-02-23 13:54:49 -0800 | [diff] [blame^] | 128 |     "log_session_id", | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 129 | }; | 
 | 130 |  | 
 | 131 | static constexpr const char * const AudioDeviceConnectionFields[] = { | 
 | 132 |     "mediametrics_audiodeviceconnection_reported", | 
 | 133 |     "input_devices", | 
 | 134 |     "output_devices", | 
 | 135 |     "device_names", | 
 | 136 |     "result", | 
 | 137 |     "time_to_connect_millis", | 
 | 138 |     "connection_count", | 
 | 139 | }; | 
 | 140 |  | 
| jiabin | 515eb09 | 2020-11-18 17:55:52 -0800 | [diff] [blame] | 141 | // static constexpr const char * const AAudioStreamFields[] { | 
 | 142 | //     "mediametrics_aaudiostream_reported", | 
 | 143 | //     "caller_name", | 
 | 144 | //     "path", | 
 | 145 | //     "direction", | 
 | 146 | //     "frames_per_burst", | 
 | 147 | //     "buffer_size", | 
 | 148 | //     "buffer_capacity", | 
 | 149 | //     "channel_count", | 
 | 150 | //     "total_frames_transferred", | 
 | 151 | //     "perf_mode_requested", | 
 | 152 | //     "perf_mode_actual", | 
 | 153 | //     "sharing", | 
 | 154 | //     "xrun_count", | 
 | 155 | //     "device_type", | 
 | 156 | //     "format_app", | 
 | 157 | //     "format_device", | 
 | 158 | // }; | 
 | 159 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 160 | /** | 
 | 161 |  * sendToStatsd is a helper method that sends the arguments to statsd | 
 | 162 |  * and returns a pair { result, summary_string }. | 
 | 163 |  */ | 
 | 164 | template <size_t N, typename ...Types> | 
 | 165 | std::pair<int, std::string> sendToStatsd(const char * const (& fields)[N], Types ... args) | 
 | 166 | { | 
 | 167 |     int result = 0; | 
 | 168 |     std::stringstream ss; | 
 | 169 |  | 
 | 170 | #ifdef STATSD_ENABLE | 
 | 171 |     result = android::util::stats_write(args...); | 
 | 172 |     ss << "result:" << result; | 
 | 173 | #endif | 
 | 174 |     ss << " { "; | 
 | 175 |     stringutils::fieldPrint(ss, fields, args...); | 
 | 176 |     ss << "}"; | 
 | 177 |     return { result, ss.str() }; | 
 | 178 | } | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 179 |  | 
 | 180 | AudioAnalytics::AudioAnalytics() | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 181 |     : mDeliverStatistics(property_get_bool(PROP_AUDIO_ANALYTICS_CLOUD_ENABLED, true)) | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 182 | { | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 183 |     SetMinimumLogSeverity(android::base::DEBUG); // for LOG(). | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 184 |     ALOGD("%s", __func__); | 
| Andy Hung | 0f7ad8c | 2020-01-03 13:24:34 -0800 | [diff] [blame] | 185 |  | 
 | 186 |     // Add action to save AnalyticsState if audioserver is restarted. | 
 | 187 |     // This triggers on an item of "audio.flinger" | 
 | 188 |     // with a property "event" set to "AudioFlinger" (the constructor). | 
 | 189 |     mActions.addAction( | 
| Andy Hung | ea186fa | 2020-01-09 18:13:15 -0800 | [diff] [blame] | 190 |         AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT, | 
 | 191 |         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR), | 
| Andy Hung | 0f7ad8c | 2020-01-03 13:24:34 -0800 | [diff] [blame] | 192 |         std::make_shared<AnalyticsActions::Function>( | 
| Andy Hung | ea186fa | 2020-01-09 18:13:15 -0800 | [diff] [blame] | 193 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
 | 194 |                 ALOGW("(key=%s) Audioflinger constructor event detected", item->getKey().c_str()); | 
| Andy Hung | 0f7ad8c | 2020-01-03 13:24:34 -0800 | [diff] [blame] | 195 |                 mPreviousAnalyticsState.set(std::make_shared<AnalyticsState>( | 
 | 196 |                         *mAnalyticsState.get())); | 
 | 197 |                 // Note: get returns shared_ptr temp, whose lifetime is extended | 
 | 198 |                 // to end of full expression. | 
 | 199 |                 mAnalyticsState->clear();  // TODO: filter the analytics state. | 
| Andy Hung | ea186fa | 2020-01-09 18:13:15 -0800 | [diff] [blame] | 200 |                 // Perhaps report this. | 
| Andy Hung | b18f506 | 2020-06-18 23:10:08 -0700 | [diff] [blame] | 201 |  | 
 | 202 |                 // Set up a timer to expire the previous audio state to save space. | 
 | 203 |                 // Use the transaction log size as a cookie to see if it is the | 
 | 204 |                 // same as before.  A benign race is possible where a state is cleared early. | 
 | 205 |                 const size_t size = mPreviousAnalyticsState->transactionLog().size(); | 
 | 206 |                 mTimedAction.postIn( | 
 | 207 |                         std::chrono::seconds(PREVIOUS_STATE_EXPIRE_SEC), [this, size](){ | 
 | 208 |                     if (mPreviousAnalyticsState->transactionLog().size() == size) { | 
 | 209 |                         ALOGD("expiring previous audio state after %d seconds.", | 
 | 210 |                                 PREVIOUS_STATE_EXPIRE_SEC); | 
 | 211 |                         mPreviousAnalyticsState->clear();  // removes data from the state. | 
 | 212 |                     } | 
 | 213 |                 }); | 
| Andy Hung | ea186fa | 2020-01-09 18:13:15 -0800 | [diff] [blame] | 214 |             })); | 
 | 215 |  | 
| jiabin | 515eb09 | 2020-11-18 17:55:52 -0800 | [diff] [blame] | 216 |     // Handle legacy aaudio stream statistics | 
 | 217 |     mActions.addAction( | 
 | 218 |         AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT, | 
 | 219 |         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM), | 
 | 220 |         std::make_shared<AnalyticsActions::Function>( | 
 | 221 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item) { | 
 | 222 |                 mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY); | 
 | 223 |             })); | 
 | 224 |  | 
 | 225 |     // Handle mmap aaudio stream statistics | 
 | 226 |     mActions.addAction( | 
 | 227 |         AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*." AMEDIAMETRICS_PROP_EVENT, | 
 | 228 |         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM), | 
 | 229 |         std::make_shared<AnalyticsActions::Function>( | 
 | 230 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item) { | 
 | 231 |                 mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_MMAP); | 
 | 232 |             })); | 
 | 233 |  | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 234 |     // Handle device use record statistics | 
| Andy Hung | ea186fa | 2020-01-09 18:13:15 -0800 | [diff] [blame] | 235 |     mActions.addAction( | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 236 |         AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT, | 
 | 237 |         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP), | 
| Andy Hung | ea186fa | 2020-01-09 18:13:15 -0800 | [diff] [blame] | 238 |         std::make_shared<AnalyticsActions::Function>( | 
 | 239 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 240 |                 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::RECORD); | 
| Andy Hung | 0f7ad8c | 2020-01-03 13:24:34 -0800 | [diff] [blame] | 241 |             })); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 242 |  | 
 | 243 |     // Handle device use thread statistics | 
 | 244 |     mActions.addAction( | 
 | 245 |         AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT, | 
 | 246 |         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP), | 
 | 247 |         std::make_shared<AnalyticsActions::Function>( | 
 | 248 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 249 |                 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::THREAD); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 250 |             })); | 
 | 251 |  | 
 | 252 |     // Handle device use track statistics | 
 | 253 |     mActions.addAction( | 
 | 254 |         AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT, | 
 | 255 |         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP), | 
 | 256 |         std::make_shared<AnalyticsActions::Function>( | 
 | 257 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 258 |                 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::TRACK); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 259 |             })); | 
 | 260 |  | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 261 |  | 
 | 262 |     // Handle device connection statistics | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 263 |  | 
 | 264 |     // We track connections (not disconnections) for the time to connect. | 
 | 265 |     // TODO: consider BT requests in their A2dp service | 
 | 266 |     // AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent | 
 | 267 |     // AudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent | 
 | 268 |     // AudioDeviceBroker.postA2dpActiveDeviceChange | 
 | 269 |     mActions.addAction( | 
 | 270 |         "audio.device.a2dp.state", | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 271 |         "connected", | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 272 |         std::make_shared<AnalyticsActions::Function>( | 
 | 273 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
 | 274 |                 mDeviceConnection.a2dpConnected(item); | 
 | 275 |             })); | 
 | 276 |     // If audio is active, we expect to see a createAudioPatch after the device is connected. | 
 | 277 |     mActions.addAction( | 
 | 278 |         AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT, | 
 | 279 |         std::string("createAudioPatch"), | 
 | 280 |         std::make_shared<AnalyticsActions::Function>( | 
 | 281 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
 | 282 |                 mDeviceConnection.createPatch(item); | 
 | 283 |             })); | 
| Joey Poomarin | 5298998 | 2020-03-05 17:40:49 +0800 | [diff] [blame] | 284 |  | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 285 |     // Called from BT service | 
 | 286 |     mActions.addAction( | 
 | 287 |         AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE | 
 | 288 |         "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent" | 
 | 289 |         "." AMEDIAMETRICS_PROP_STATE, | 
 | 290 |         "connected", | 
 | 291 |         std::make_shared<AnalyticsActions::Function>( | 
 | 292 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
 | 293 |                 mDeviceConnection.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(item); | 
 | 294 |             })); | 
 | 295 |  | 
| Joey Poomarin | 5298998 | 2020-03-05 17:40:49 +0800 | [diff] [blame] | 296 |     // Handle power usage | 
 | 297 |     mActions.addAction( | 
 | 298 |         AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT, | 
 | 299 |         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP), | 
 | 300 |         std::make_shared<AnalyticsActions::Function>( | 
 | 301 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
 | 302 |                 mAudioPowerUsage.checkTrackRecord(item, true /* isTrack */); | 
 | 303 |             })); | 
 | 304 |  | 
 | 305 |     mActions.addAction( | 
 | 306 |         AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT, | 
 | 307 |         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP), | 
 | 308 |         std::make_shared<AnalyticsActions::Function>( | 
 | 309 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
 | 310 |                 mAudioPowerUsage.checkTrackRecord(item, false /* isTrack */); | 
 | 311 |             })); | 
 | 312 |  | 
 | 313 |     mActions.addAction( | 
 | 314 |         AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT, | 
 | 315 |         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE), | 
 | 316 |         std::make_shared<AnalyticsActions::Function>( | 
 | 317 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
 | 318 |                 // ALOGD("(key=%s) Audioflinger setMode", item->getKey().c_str()); | 
 | 319 |                 mAudioPowerUsage.checkMode(item); | 
 | 320 |             })); | 
 | 321 |  | 
 | 322 |     mActions.addAction( | 
 | 323 |         AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT, | 
 | 324 |         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME), | 
 | 325 |         std::make_shared<AnalyticsActions::Function>( | 
 | 326 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
 | 327 |                 // ALOGD("(key=%s) Audioflinger setVoiceVolume", item->getKey().c_str()); | 
 | 328 |                 mAudioPowerUsage.checkVoiceVolume(item); | 
 | 329 |             })); | 
 | 330 |  | 
 | 331 |     mActions.addAction( | 
 | 332 |         AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT, | 
 | 333 |         std::string("createAudioPatch"), | 
 | 334 |         std::make_shared<AnalyticsActions::Function>( | 
 | 335 |             [this](const std::shared_ptr<const android::mediametrics::Item> &item){ | 
 | 336 |                 mAudioPowerUsage.checkCreatePatch(item); | 
 | 337 |             })); | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 338 | } | 
 | 339 |  | 
 | 340 | AudioAnalytics::~AudioAnalytics() | 
 | 341 | { | 
 | 342 |     ALOGD("%s", __func__); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 343 |     mTimedAction.quit(); // ensure no deferred access during destructor. | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 344 | } | 
 | 345 |  | 
 | 346 | status_t AudioAnalytics::submit( | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 347 |         const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted) | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 348 | { | 
| Andy Hung | ea186fa | 2020-01-09 18:13:15 -0800 | [diff] [blame] | 349 |     if (!startsWith(item->getKey(), AMEDIAMETRICS_KEY_PREFIX_AUDIO)) return BAD_VALUE; | 
| Andy Hung | 0f7ad8c | 2020-01-03 13:24:34 -0800 | [diff] [blame] | 350 |     status_t status = mAnalyticsState->submit(item, isTrusted); | 
 | 351 |     if (status != NO_ERROR) return status;  // may not be permitted. | 
 | 352 |  | 
 | 353 |     // Only if the item was successfully submitted (permission) | 
 | 354 |     // do we check triggered actions. | 
 | 355 |     checkActions(item); | 
 | 356 |     return NO_ERROR; | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 357 | } | 
 | 358 |  | 
| Andy Hung | 709b91e | 2020-04-04 14:23:36 -0700 | [diff] [blame] | 359 | std::pair<std::string, int32_t> AudioAnalytics::dump( | 
 | 360 |         int32_t lines, int64_t sinceNs, const char *prefix) const | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 361 | { | 
 | 362 |     std::stringstream ss; | 
 | 363 |     int32_t ll = lines; | 
 | 364 |  | 
 | 365 |     if (ll > 0) { | 
| Andy Hung | 709b91e | 2020-04-04 14:23:36 -0700 | [diff] [blame] | 366 |         auto [s, l] = mAnalyticsState->dump(ll, sinceNs, prefix); | 
| Andy Hung | b744faf | 2020-04-09 13:09:26 -0700 | [diff] [blame] | 367 |         ss << s; | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 368 |         ll -= l; | 
 | 369 |     } | 
 | 370 |     if (ll > 0) { | 
| Andy Hung | 0f7ad8c | 2020-01-03 13:24:34 -0800 | [diff] [blame] | 371 |         ss << "Prior audioserver state:\n"; | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 372 |         --ll; | 
 | 373 |     } | 
 | 374 |     if (ll > 0) { | 
| Andy Hung | 709b91e | 2020-04-04 14:23:36 -0700 | [diff] [blame] | 375 |         auto [s, l] = mPreviousAnalyticsState->dump(ll, sinceNs, prefix); | 
| Andy Hung | b744faf | 2020-04-09 13:09:26 -0700 | [diff] [blame] | 376 |         ss << s; | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 377 |         ll -= l; | 
 | 378 |     } | 
| Joey Poomarin | 5298998 | 2020-03-05 17:40:49 +0800 | [diff] [blame] | 379 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 380 |     if (ll > 0) { | 
 | 381 |         // Print the statsd atoms we sent out. | 
 | 382 |         const std::string statsd = mStatsdLog.dumpToString("  " /* prefix */, ll - 1); | 
 | 383 |         const size_t n = std::count(statsd.begin(), statsd.end(), '\n') + 1; // we control this. | 
 | 384 |         if ((size_t)ll >= n) { | 
 | 385 |             if (n == 1) { | 
 | 386 |                 ss << "Statsd atoms: empty or truncated\n"; | 
 | 387 |             } else { | 
 | 388 |                 ss << "Statsd atoms:\n" << statsd; | 
 | 389 |             } | 
 | 390 |             ll -= n; | 
 | 391 |         } | 
 | 392 |     } | 
 | 393 |  | 
| Joey Poomarin | 5298998 | 2020-03-05 17:40:49 +0800 | [diff] [blame] | 394 |     if (ll > 0 && prefix == nullptr) { | 
 | 395 |         auto [s, l] = mAudioPowerUsage.dump(ll); | 
 | 396 |         ss << s; | 
 | 397 |         ll -= l; | 
 | 398 |     } | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 399 |  | 
| Andy Hung | 06f3aba | 2019-12-03 16:36:42 -0800 | [diff] [blame] | 400 |     return { ss.str(), lines - ll }; | 
 | 401 | } | 
 | 402 |  | 
| Andy Hung | 0f7ad8c | 2020-01-03 13:24:34 -0800 | [diff] [blame] | 403 | void AudioAnalytics::checkActions(const std::shared_ptr<const mediametrics::Item>& item) | 
 | 404 | { | 
 | 405 |     auto actions = mActions.getActionsForItem(item); // internally locked. | 
 | 406 |     // Execute actions with no lock held. | 
 | 407 |     for (const auto& action : actions) { | 
 | 408 |         (*action)(item); | 
 | 409 |     } | 
 | 410 | } | 
 | 411 |  | 
| Andy Hung | ea186fa | 2020-01-09 18:13:15 -0800 | [diff] [blame] | 412 | // HELPER METHODS | 
 | 413 |  | 
 | 414 | std::string AudioAnalytics::getThreadFromTrack(const std::string& track) const | 
 | 415 | { | 
 | 416 |     int32_t threadId_int32{}; | 
 | 417 |     if (mAnalyticsState->timeMachine().get( | 
 | 418 |             track, AMEDIAMETRICS_PROP_THREADID, &threadId_int32) != NO_ERROR) { | 
 | 419 |         return {}; | 
 | 420 |     } | 
 | 421 |     return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(threadId_int32); | 
 | 422 | } | 
 | 423 |  | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 424 | // DeviceUse helper class. | 
 | 425 | void AudioAnalytics::DeviceUse::endAudioIntervalGroup( | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 426 |        const std::shared_ptr<const android::mediametrics::Item> &item, ItemType itemType) const { | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 427 |     const std::string& key = item->getKey(); | 
 | 428 |     const std::string id = key.substr( | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 429 |             (itemType == THREAD ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) | 
 | 430 |             : itemType == TRACK ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) | 
 | 431 |             : sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD)) | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 432 |              - 1); | 
 | 433 |     // deliver statistics | 
 | 434 |     int64_t deviceTimeNs = 0; | 
 | 435 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 436 |             key, AMEDIAMETRICS_PROP_DEVICETIMENS, &deviceTimeNs); | 
 | 437 |     std::string encoding; | 
 | 438 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 439 |             key, AMEDIAMETRICS_PROP_ENCODING, &encoding); | 
 | 440 |     int32_t frameCount = 0; | 
 | 441 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 442 |             key, AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount); | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 443 |     std::string inputDevicePairs; | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 444 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 445 |             key, AMEDIAMETRICS_PROP_INPUTDEVICES, &inputDevicePairs); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 446 |     int32_t intervalCount = 0; | 
 | 447 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 448 |             key, AMEDIAMETRICS_PROP_INTERVALCOUNT, &intervalCount); | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 449 |     std::string outputDevicePairs; | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 450 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 451 |             key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevicePairs); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 452 |     int32_t sampleRate = 0; | 
 | 453 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 454 |             key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 455 |     std::string flags; | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 456 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 457 |             key, AMEDIAMETRICS_PROP_FLAGS, &flags); | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 458 |  | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 459 |     // We may have several devices. | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 460 |     // Accumulate the bit flags for input and output devices. | 
 | 461 |     std::stringstream oss; | 
 | 462 |     long_enum_type_t outputDeviceBits{}; | 
 | 463 |     {   // compute outputDevices | 
 | 464 |         const auto devaddrvec = stringutils::getDeviceAddressPairs(outputDevicePairs); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 465 |         for (const auto& [device, addr] : devaddrvec) { | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 466 |             if (oss.tellp() > 0) oss << "|";  // delimit devices with '|'. | 
 | 467 |             oss << device; | 
 | 468 |             outputDeviceBits += types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(device); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 469 |         } | 
 | 470 |     } | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 471 |     const std::string outputDevices = oss.str(); | 
 | 472 |  | 
 | 473 |     std::stringstream iss; | 
 | 474 |     long_enum_type_t inputDeviceBits{}; | 
 | 475 |     {   // compute inputDevices | 
 | 476 |         const auto devaddrvec = stringutils::getDeviceAddressPairs(inputDevicePairs); | 
 | 477 |         for (const auto& [device, addr] : devaddrvec) { | 
 | 478 |             if (iss.tellp() > 0) iss << "|";  // delimit devices with '|'. | 
 | 479 |             iss << device; | 
 | 480 |             inputDeviceBits += types::lookup<types::INPUT_DEVICE, long_enum_type_t>(device); | 
 | 481 |         } | 
 | 482 |     } | 
 | 483 |     const std::string inputDevices = iss.str(); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 484 |  | 
 | 485 |     // Get connected device name if from bluetooth. | 
 | 486 |     bool isBluetooth = false; | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 487 |  | 
 | 488 |     std::string inputDeviceNames;  // not filled currently. | 
 | 489 |     std::string outputDeviceNames; | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 490 |     if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos) { | 
 | 491 |         isBluetooth = true; | 
| Andy Hung | 3deef2b | 2020-07-17 12:58:54 -0700 | [diff] [blame] | 492 |         outputDeviceNames = SUPPRESSED; | 
 | 493 | #if 0   // TODO(b/161554630) sanitize name | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 494 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 495 |             "audio.device.bt_a2dp", AMEDIAMETRICS_PROP_NAME, &outputDeviceNames); | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 496 |         // Remove | if present | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 497 |         stringutils::replace(outputDeviceNames, "|", '?'); | 
 | 498 |         if (outputDeviceNames.size() > STATSD_DEVICE_NAME_MAX_LENGTH) { | 
 | 499 |             outputDeviceNames.resize(STATSD_DEVICE_NAME_MAX_LENGTH); // truncate | 
 | 500 |         } | 
| Andy Hung | 3deef2b | 2020-07-17 12:58:54 -0700 | [diff] [blame] | 501 | #endif | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 502 |     } | 
 | 503 |  | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 504 |     switch (itemType) { | 
 | 505 |     case RECORD: { | 
 | 506 |         std::string callerName; | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 507 |         const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 508 |                 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK; | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 509 |  | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 510 |         std::string packageName; | 
 | 511 |         int64_t versionCode = 0; | 
 | 512 |         int32_t uid = -1; | 
 | 513 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 514 |                 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid); | 
 | 515 |         if (uid != -1) { | 
 | 516 |             std::tie(packageName, versionCode) = | 
 | 517 |                     MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid); | 
 | 518 |         } | 
 | 519 |  | 
 | 520 |         int32_t selectedDeviceId = 0; | 
 | 521 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 522 |                 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId); | 
 | 523 |         std::string source; | 
 | 524 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 525 |                 key, AMEDIAMETRICS_PROP_SOURCE, &source); | 
| Andy Hung | cbcfaa2 | 2021-02-23 13:54:49 -0800 | [diff] [blame^] | 526 |         // Android S | 
 | 527 |         std::string logSessionId; | 
 | 528 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 529 |                 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 530 |  | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 531 |         const auto callerNameForStats = | 
 | 532 |                 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName); | 
 | 533 |         const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding); | 
 | 534 |         const auto flagsForStats = types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags); | 
 | 535 |         const auto sourceForStats = types::lookup<types::SOURCE_TYPE, short_enum_type_t>(source); | 
| Andy Hung | cbcfaa2 | 2021-02-23 13:54:49 -0800 | [diff] [blame^] | 536 |         // Android S | 
 | 537 |         const auto logSessionIdForStats = stringutils::sanitizeLogSessionId(logSessionId); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 538 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 539 |         LOG(LOG_LEVEL) << "key:" << key | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 540 |               << " id:" << id | 
 | 541 |               << " inputDevices:" << inputDevices << "(" << inputDeviceBits | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 542 |               << ") inputDeviceNames:" << inputDeviceNames | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 543 |               << " deviceTimeNs:" << deviceTimeNs | 
 | 544 |               << " encoding:" << encoding << "(" << encodingForStats | 
 | 545 |               << ") frameCount:" << frameCount | 
 | 546 |               << " intervalCount:" << intervalCount | 
 | 547 |               << " sampleRate:" << sampleRate | 
 | 548 |               << " flags:" << flags << "(" << flagsForStats | 
 | 549 |               << ") packageName:" << packageName | 
 | 550 |               << " selectedDeviceId:" << selectedDeviceId | 
 | 551 |               << " callerName:" << callerName << "(" << callerNameForStats | 
| Andy Hung | cbcfaa2 | 2021-02-23 13:54:49 -0800 | [diff] [blame^] | 552 |               << ") source:" << source << "(" << sourceForStats | 
 | 553 |               << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats | 
 | 554 |               << ")"; | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 555 |         if (clientCalled  // only log if client app called AudioRecord. | 
 | 556 |                 && mAudioAnalytics.mDeliverStatistics) { | 
 | 557 |             const auto [ result, str ] = sendToStatsd(AudioRecordDeviceUsageFields, | 
 | 558 |                     CONDITION(android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED) | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 559 |                     , ENUM_EXTRACT(inputDeviceBits) | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 560 |                     , inputDeviceNames.c_str() | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 561 |                     , deviceTimeNs | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 562 |                     , ENUM_EXTRACT(encodingForStats) | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 563 |                     , frameCount | 
 | 564 |                     , intervalCount | 
 | 565 |                     , sampleRate | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 566 |                     , ENUM_EXTRACT(flagsForStats) | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 567 |  | 
 | 568 |                     , packageName.c_str() | 
 | 569 |                     , selectedDeviceId | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 570 |                     , ENUM_EXTRACT(callerNameForStats) | 
 | 571 |                     , ENUM_EXTRACT(sourceForStats) | 
| Andy Hung | cbcfaa2 | 2021-02-23 13:54:49 -0800 | [diff] [blame^] | 572 |                     , logSessionIdForStats.c_str() | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 573 |                     ); | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 574 |             ALOGV("%s: statsd %s", __func__, str.c_str()); | 
 | 575 |             mAudioAnalytics.mStatsdLog.log("%s", str.c_str()); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 576 |         } | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 577 |     } break; | 
 | 578 |     case THREAD: { | 
 | 579 |         std::string type; | 
 | 580 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 581 |                 key, AMEDIAMETRICS_PROP_TYPE, &type); | 
 | 582 |         int32_t underrun = 0; // zero for record types | 
 | 583 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 584 |                 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun); | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 585 |  | 
 | 586 |         const bool isInput = types::isInputThreadType(type); | 
 | 587 |         const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding); | 
 | 588 |         const auto flagsForStats = | 
 | 589 |                 (isInput ? types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags) | 
 | 590 |                         : types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags)); | 
 | 591 |         const auto typeForStats = types::lookup<types::THREAD_TYPE, short_enum_type_t>(type); | 
 | 592 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 593 |         LOG(LOG_LEVEL) << "key:" << key | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 594 |               << " id:" << id | 
 | 595 |               << " inputDevices:" << inputDevices << "(" << inputDeviceBits | 
 | 596 |               << ") outputDevices:" << outputDevices << "(" << outputDeviceBits | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 597 |               << ") inputDeviceNames:" << inputDeviceNames | 
 | 598 |               << " outputDeviceNames:" << outputDeviceNames | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 599 |               << " deviceTimeNs:" << deviceTimeNs | 
 | 600 |               << " encoding:" << encoding << "(" << encodingForStats | 
 | 601 |               << ") frameCount:" << frameCount | 
 | 602 |               << " intervalCount:" << intervalCount | 
 | 603 |               << " sampleRate:" << sampleRate | 
 | 604 |               << " underrun:" << underrun | 
 | 605 |               << " flags:" << flags << "(" << flagsForStats | 
 | 606 |               << ") type:" << type << "(" << typeForStats | 
 | 607 |               << ")"; | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 608 |         if (mAudioAnalytics.mDeliverStatistics) { | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 609 |             const auto [ result, str ] = sendToStatsd(AudioThreadDeviceUsageFields, | 
 | 610 |                 CONDITION(android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED) | 
 | 611 |                 , isInput ? ENUM_EXTRACT(inputDeviceBits) : ENUM_EXTRACT(outputDeviceBits) | 
 | 612 |                 , isInput ? inputDeviceNames.c_str() : outputDeviceNames.c_str() | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 613 |                 , deviceTimeNs | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 614 |                 , ENUM_EXTRACT(encodingForStats) | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 615 |                 , frameCount | 
 | 616 |                 , intervalCount | 
 | 617 |                 , sampleRate | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 618 |                 , ENUM_EXTRACT(flagsForStats) | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 619 |                 , underrun | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 620 |                 , ENUM_EXTRACT(typeForStats) | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 621 |             ); | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 622 |             ALOGV("%s: statsd %s", __func__, str.c_str()); | 
 | 623 |             mAudioAnalytics.mStatsdLog.log("%s", str.c_str()); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 624 |         } | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 625 |     } break; | 
 | 626 |     case TRACK: { | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 627 |         std::string callerName; | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 628 |         const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 629 |                 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK; | 
 | 630 |  | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 631 |         std::string contentType; | 
 | 632 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 633 |                 key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentType); | 
 | 634 |         double deviceLatencyMs = 0.; | 
 | 635 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 636 |                 key, AMEDIAMETRICS_PROP_DEVICELATENCYMS, &deviceLatencyMs); | 
 | 637 |         double deviceStartupMs = 0.; | 
 | 638 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 639 |                 key, AMEDIAMETRICS_PROP_DEVICESTARTUPMS, &deviceStartupMs); | 
 | 640 |         double deviceVolume = 0.; | 
 | 641 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 642 |                 key, AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume); | 
 | 643 |         std::string packageName; | 
 | 644 |         int64_t versionCode = 0; | 
 | 645 |         int32_t uid = -1; | 
 | 646 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 647 |                 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid); | 
 | 648 |         if (uid != -1) { | 
 | 649 |             std::tie(packageName, versionCode) = | 
 | 650 |                     MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid); | 
 | 651 |         } | 
 | 652 |         double playbackPitch = 0.; | 
 | 653 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 654 |                 key, AMEDIAMETRICS_PROP_PLAYBACK_PITCH, &playbackPitch); | 
 | 655 |         double playbackSpeed = 0.; | 
 | 656 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 657 |                 key, AMEDIAMETRICS_PROP_PLAYBACK_SPEED, &playbackSpeed); | 
 | 658 |         int32_t selectedDeviceId = 0; | 
 | 659 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 660 |                 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 661 |         std::string streamType; | 
 | 662 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 663 |                 key, AMEDIAMETRICS_PROP_STREAMTYPE, &streamType); | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 664 |         std::string traits; | 
 | 665 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 666 |                 key, AMEDIAMETRICS_PROP_TRAITS, &traits); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 667 |         int32_t underrun = 0; | 
 | 668 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 669 |                 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 670 |         std::string usage; | 
 | 671 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 672 |                 key, AMEDIAMETRICS_PROP_USAGE, &usage); | 
| Andy Hung | cbcfaa2 | 2021-02-23 13:54:49 -0800 | [diff] [blame^] | 673 |         // Android S | 
 | 674 |         std::string logSessionId; | 
 | 675 |         mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 676 |                 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 677 |  | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 678 |         const auto callerNameForStats = | 
 | 679 |                 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName); | 
 | 680 |         const auto contentTypeForStats = | 
 | 681 |                 types::lookup<types::CONTENT_TYPE, short_enum_type_t>(contentType); | 
 | 682 |         const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding); | 
 | 683 |         const auto flagsForStats = types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags); | 
 | 684 |         const auto streamTypeForStats = | 
 | 685 |                 types::lookup<types::STREAM_TYPE, short_enum_type_t>(streamType); | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 686 |         const auto traitsForStats = | 
 | 687 |                  types::lookup<types::TRACK_TRAITS, short_enum_type_t>(traits); | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 688 |         const auto usageForStats = types::lookup<types::USAGE, short_enum_type_t>(usage); | 
| Andy Hung | cbcfaa2 | 2021-02-23 13:54:49 -0800 | [diff] [blame^] | 689 |         // Android S | 
 | 690 |         const auto logSessionIdForStats = stringutils::sanitizeLogSessionId(logSessionId); | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 691 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 692 |         LOG(LOG_LEVEL) << "key:" << key | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 693 |               << " id:" << id | 
 | 694 |               << " outputDevices:" << outputDevices << "(" << outputDeviceBits | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 695 |               << ") outputDeviceNames:" << outputDeviceNames | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 696 |               << " deviceTimeNs:" << deviceTimeNs | 
 | 697 |               << " encoding:" << encoding << "(" << encodingForStats | 
 | 698 |               << ") frameCount:" << frameCount | 
 | 699 |               << " intervalCount:" << intervalCount | 
 | 700 |               << " sampleRate:" << sampleRate | 
 | 701 |               << " underrun:" << underrun | 
 | 702 |               << " flags:" << flags << "(" << flagsForStats | 
 | 703 |               << ") callerName:" << callerName << "(" << callerNameForStats | 
 | 704 |               << ") contentType:" << contentType << "(" << contentTypeForStats | 
 | 705 |               << ") deviceLatencyMs:" << deviceLatencyMs | 
 | 706 |               << " deviceStartupMs:" << deviceStartupMs | 
 | 707 |               << " deviceVolume:" << deviceVolume | 
 | 708 |               << " packageName:" << packageName | 
 | 709 |               << " playbackPitch:" << playbackPitch | 
 | 710 |               << " playbackSpeed:" << playbackSpeed | 
 | 711 |               << " selectedDeviceId:" << selectedDeviceId | 
 | 712 |               << " streamType:" << streamType << "(" << streamTypeForStats | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 713 |               << ") traits:" << traits << "(" << traitsForStats | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 714 |               << ") usage:" << usage << "(" << usageForStats | 
| Andy Hung | cbcfaa2 | 2021-02-23 13:54:49 -0800 | [diff] [blame^] | 715 |               << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 716 |               << ")"; | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 717 |         if (clientCalled // only log if client app called AudioTracks | 
 | 718 |                 && mAudioAnalytics.mDeliverStatistics) { | 
 | 719 |             const auto [ result, str ] = sendToStatsd(AudioTrackDeviceUsageFields, | 
 | 720 |                     CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED) | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 721 |                     , ENUM_EXTRACT(outputDeviceBits) | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 722 |                     , outputDeviceNames.c_str() | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 723 |                     , deviceTimeNs | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 724 |                     , ENUM_EXTRACT(encodingForStats) | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 725 |                     , frameCount | 
 | 726 |                     , intervalCount | 
 | 727 |                     , sampleRate | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 728 |                     , ENUM_EXTRACT(flagsForStats) | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 729 |                     , underrun | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 730 |                     , packageName.c_str() | 
 | 731 |                     , (float)deviceLatencyMs | 
 | 732 |                     , (float)deviceStartupMs | 
 | 733 |                     , (float)deviceVolume | 
 | 734 |                     , selectedDeviceId | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 735 |                     , ENUM_EXTRACT(streamTypeForStats) | 
 | 736 |                     , ENUM_EXTRACT(usageForStats) | 
 | 737 |                     , ENUM_EXTRACT(contentTypeForStats) | 
 | 738 |                     , ENUM_EXTRACT(callerNameForStats) | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 739 |                     , ENUM_EXTRACT(traitsForStats) | 
| Andy Hung | cbcfaa2 | 2021-02-23 13:54:49 -0800 | [diff] [blame^] | 740 |                     , logSessionIdForStats.c_str() | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 741 |                     ); | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 742 |             ALOGV("%s: statsd %s", __func__, str.c_str()); | 
 | 743 |             mAudioAnalytics.mStatsdLog.log("%s", str.c_str()); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 744 |         } | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 745 |         } break; | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 746 |     } | 
 | 747 |  | 
 | 748 |     // Report this as needed. | 
 | 749 |     if (isBluetooth) { | 
 | 750 |         // report this for Bluetooth | 
 | 751 |     } | 
 | 752 | } | 
 | 753 |  | 
 | 754 | // DeviceConnection helper class. | 
 | 755 | void AudioAnalytics::DeviceConnection::a2dpConnected( | 
 | 756 |        const std::shared_ptr<const android::mediametrics::Item> &item) { | 
 | 757 |     const std::string& key = item->getKey(); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 758 |     const int64_t atNs = item->getTimestamp(); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 759 |     { | 
 | 760 |         std::lock_guard l(mLock); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 761 |         mA2dpConnectionServiceNs = atNs; | 
 | 762 |         ++mA2dpConnectionServices; | 
 | 763 |  | 
 | 764 |         if (mA2dpConnectionRequestNs == 0) { | 
 | 765 |             mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); }); | 
 | 766 |         } | 
 | 767 |         // This sets the time we were connected.  Now we look for the delta in the future. | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 768 |     } | 
 | 769 |     std::string name; | 
 | 770 |     item->get(AMEDIAMETRICS_PROP_NAME, &name); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 771 |     ALOGD("(key=%s) a2dp connected device:%s atNs:%lld", | 
 | 772 |             key.c_str(), name.c_str(), (long long)atNs); | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 773 | } | 
 | 774 |  | 
 | 775 | void AudioAnalytics::DeviceConnection::createPatch( | 
 | 776 |        const std::shared_ptr<const android::mediametrics::Item> &item) { | 
 | 777 |     std::lock_guard l(mLock); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 778 |     if (mA2dpConnectionServiceNs == 0) return; // patch unrelated to us. | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 779 |     const std::string& key = item->getKey(); | 
 | 780 |     std::string outputDevices; | 
 | 781 |     item->get(AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 782 |     if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH_A2DP") != std::string::npos) { | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 783 |         // TODO compare address | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 784 |         int64_t timeDiffNs = item->getTimestamp(); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 785 |         if (mA2dpConnectionRequestNs == 0) { | 
 | 786 |             ALOGD("%s: A2DP create patch didn't see a connection request", __func__); | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 787 |             timeDiffNs -= mA2dpConnectionServiceNs; | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 788 |         } else { | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 789 |             timeDiffNs -= mA2dpConnectionRequestNs; | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 790 |         } | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 791 |  | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 792 |         mA2dpConnectionRequestNs = 0; | 
 | 793 |         mA2dpConnectionServiceNs = 0; | 
 | 794 |         ++mA2dpConnectionSuccesses; | 
 | 795 |  | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 796 |         const auto connectionTimeMs = float(timeDiffNs * 1e-6); | 
 | 797 |  | 
 | 798 |         const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>( | 
 | 799 |                 "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"); | 
 | 800 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 801 |         LOG(LOG_LEVEL) << "key:" << key | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 802 |                 << " A2DP SUCCESS" | 
 | 803 |                 << " outputDevices:" << outputDeviceBits | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 804 |                 << " deviceName:" << mA2dpDeviceName | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 805 |                 << " connectionTimeMs:" <<  connectionTimeMs; | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 806 |         if (mAudioAnalytics.mDeliverStatistics) { | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 807 |             const long_enum_type_t inputDeviceBits{}; | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 808 |  | 
 | 809 |             const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields, | 
 | 810 |                     CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED) | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 811 |                     , ENUM_EXTRACT(inputDeviceBits) | 
 | 812 |                     , ENUM_EXTRACT(outputDeviceBits) | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 813 |                     , mA2dpDeviceName.c_str() | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 814 |                     , types::DEVICE_CONNECTION_RESULT_SUCCESS | 
 | 815 |                     , connectionTimeMs | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 816 |                     , /* connection_count */ 1 | 
 | 817 |                     ); | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 818 |             ALOGV("%s: statsd %s", __func__, str.c_str()); | 
 | 819 |             mAudioAnalytics.mStatsdLog.log("%s", str.c_str()); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 820 |         } | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 821 |     } | 
 | 822 | } | 
 | 823 |  | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 824 | // Called through AudioManager when the BT service wants to enable | 
 | 825 | void AudioAnalytics::DeviceConnection::postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( | 
 | 826 |         const std::shared_ptr<const android::mediametrics::Item> &item) { | 
 | 827 |     const int64_t atNs = item->getTimestamp(); | 
 | 828 |     const std::string& key = item->getKey(); | 
 | 829 |     std::string state; | 
 | 830 |     item->get(AMEDIAMETRICS_PROP_STATE, &state); | 
 | 831 |     if (state != "connected") return; | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 832 |  | 
 | 833 |     std::string name; | 
 | 834 |     item->get(AMEDIAMETRICS_PROP_NAME, &name); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 835 |     { | 
 | 836 |         std::lock_guard l(mLock); | 
 | 837 |         mA2dpConnectionRequestNs = atNs; | 
 | 838 |         ++mA2dpConnectionRequests; | 
| Andy Hung | 3deef2b | 2020-07-17 12:58:54 -0700 | [diff] [blame] | 839 |         mA2dpDeviceName = SUPPRESSED; // TODO(b/161554630) sanitize name | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 840 |     } | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 841 |     ALOGD("(key=%s) a2dp connection name:%s request atNs:%lld", | 
 | 842 |             key.c_str(), name.c_str(), (long long)atNs); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 843 |     // TODO: attempt to cancel a timed event, rather than let it expire. | 
 | 844 |     mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); }); | 
 | 845 | } | 
 | 846 |  | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 847 | void AudioAnalytics::DeviceConnection::expire() { | 
 | 848 |     std::lock_guard l(mLock); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 849 |     if (mA2dpConnectionRequestNs == 0) return; // ignore (this was an internal connection). | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 850 |  | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 851 |     const long_enum_type_t inputDeviceBits{}; | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 852 |     const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>( | 
 | 853 |             "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"); | 
 | 854 |  | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 855 |     if (mA2dpConnectionServiceNs == 0) { | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 856 |         ++mA2dpConnectionJavaServiceCancels;  // service did not connect to A2DP | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 857 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 858 |         LOG(LOG_LEVEL) << "A2DP CANCEL" | 
 | 859 |                 << " outputDevices:" << outputDeviceBits | 
 | 860 |                 << " deviceName:" << mA2dpDeviceName; | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 861 |         if (mAudioAnalytics.mDeliverStatistics) { | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 862 |             const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields, | 
 | 863 |                     CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED) | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 864 |                     , ENUM_EXTRACT(inputDeviceBits) | 
 | 865 |                     , ENUM_EXTRACT(outputDeviceBits) | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 866 |                     , mA2dpDeviceName.c_str() | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 867 |                     , types::DEVICE_CONNECTION_RESULT_JAVA_SERVICE_CANCEL | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 868 |                     , /* connection_time_ms */ 0.f | 
 | 869 |                     , /* connection_count */ 1 | 
 | 870 |                     ); | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 871 |             ALOGV("%s: statsd %s", __func__, str.c_str()); | 
 | 872 |             mAudioAnalytics.mStatsdLog.log("%s", str.c_str()); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 873 |         } | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 874 |         return; | 
 | 875 |     } | 
 | 876 |  | 
 | 877 |     // AudioFlinger didn't play - an expiration may occur because there is no audio playing. | 
 | 878 |     // Should we check elsewhere? | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 879 |     // TODO: disambiguate this case. | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 880 |     mA2dpConnectionRequestNs = 0; | 
 | 881 |     mA2dpConnectionServiceNs = 0; | 
 | 882 |     ++mA2dpConnectionUnknowns;  // connection result unknown | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 883 |  | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 884 |     LOG(LOG_LEVEL) << "A2DP UNKNOWN" | 
 | 885 |             << " outputDevices:" << outputDeviceBits | 
 | 886 |             << " deviceName:" << mA2dpDeviceName; | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 887 |     if (mAudioAnalytics.mDeliverStatistics) { | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 888 |         const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields, | 
 | 889 |                 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED) | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 890 |                 , ENUM_EXTRACT(inputDeviceBits) | 
 | 891 |                 , ENUM_EXTRACT(outputDeviceBits) | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 892 |                 , mA2dpDeviceName.c_str() | 
| Andy Hung | 1ea842e | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 893 |                 , types::DEVICE_CONNECTION_RESULT_UNKNOWN | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 894 |                 , /* connection_time_ms */ 0.f | 
 | 895 |                 , /* connection_count */ 1 | 
 | 896 |                 ); | 
| Andy Hung | a629bd1 | 2020-06-05 16:03:53 -0700 | [diff] [blame] | 897 |         ALOGV("%s: statsd %s", __func__, str.c_str()); | 
 | 898 |         mAudioAnalytics.mStatsdLog.log("%s", str.c_str()); | 
| Andy Hung | ea84038 | 2020-05-05 21:50:17 -0700 | [diff] [blame] | 899 |     } | 
| Andy Hung | ce9b663 | 2020-04-28 20:15:17 -0700 | [diff] [blame] | 900 | } | 
 | 901 |  | 
| jiabin | 515eb09 | 2020-11-18 17:55:52 -0800 | [diff] [blame] | 902 | void AudioAnalytics::AAudioStreamInfo::endAAudioStream( | 
 | 903 |         const std::shared_ptr<const android::mediametrics::Item> &item, CallerPath path) const { | 
 | 904 |     const std::string& key = item->getKey(); | 
 | 905 |  | 
 | 906 |     std::string callerNameStr; | 
 | 907 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 908 |             key, AMEDIAMETRICS_PROP_CALLERNAME, &callerNameStr); | 
 | 909 |  | 
 | 910 |     const auto callerName = types::lookup<types::CALLER_NAME, int32_t>(callerNameStr); | 
 | 911 |  | 
 | 912 |     std::string directionStr; | 
 | 913 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 914 |             key, AMEDIAMETRICS_PROP_DIRECTION, &directionStr); | 
 | 915 |     const auto direction = types::lookup<types::AAUDIO_DIRECTION, int32_t>(directionStr); | 
 | 916 |  | 
 | 917 |     int32_t framesPerBurst = -1; | 
 | 918 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 919 |             key, AMEDIAMETRICS_PROP_BURSTFRAMES, &framesPerBurst); | 
 | 920 |  | 
 | 921 |     int32_t bufferSizeInFrames = -1; | 
 | 922 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 923 |             key, AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, &bufferSizeInFrames); | 
 | 924 |  | 
 | 925 |     int32_t bufferCapacityInFrames = -1; | 
 | 926 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 927 |             key, AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, &bufferCapacityInFrames); | 
 | 928 |  | 
 | 929 |     int32_t channelCount = -1; | 
 | 930 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 931 |             key, AMEDIAMETRICS_PROP_CHANNELCOUNT, &channelCount); | 
 | 932 |  | 
 | 933 |     int64_t totalFramesTransferred = -1; | 
 | 934 |     // TODO: log and get total frames transferred | 
 | 935 |  | 
 | 936 |     std::string perfModeRequestedStr; | 
 | 937 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 938 |             key, AMEDIAMETRICS_PROP_PERFORMANCEMODE, &perfModeRequestedStr); | 
 | 939 |     const auto perfModeRequested = | 
 | 940 |             types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeRequestedStr); | 
 | 941 |  | 
 | 942 |     int32_t perfModeActual = 0; | 
 | 943 |     // TODO: log and get actual performance mode | 
 | 944 |  | 
 | 945 |     std::string sharingModeStr; | 
 | 946 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 947 |             key, AMEDIAMETRICS_PROP_SHARINGMODE, &sharingModeStr); | 
 | 948 |     const auto sharingMode = types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeStr); | 
 | 949 |  | 
 | 950 |     int32_t xrunCount = -1; | 
 | 951 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 952 |             key, AMEDIAMETRICS_PROP_UNDERRUN, &xrunCount); | 
 | 953 |  | 
 | 954 |     std::string deviceType; | 
 | 955 |     // TODO: only routed device id is logged, but no device type | 
 | 956 |  | 
 | 957 |     int32_t formatApp = 0; | 
 | 958 |     // TODO: log format from app | 
 | 959 |  | 
 | 960 |     std::string formatDeviceStr; | 
 | 961 |     mAudioAnalytics.mAnalyticsState->timeMachine().get( | 
 | 962 |             key, AMEDIAMETRICS_PROP_ENCODING, &formatDeviceStr); | 
 | 963 |     const auto formatDevice = types::lookup<types::ENCODING, int32_t>(formatDeviceStr); | 
 | 964 |  | 
 | 965 |     LOG(LOG_LEVEL) << "key:" << key | 
 | 966 |             << " caller_name:" << callerName << "(" << callerNameStr << ")" | 
 | 967 |             << " path:" << path | 
 | 968 |             << " direction:" << direction << "(" << directionStr << ")" | 
 | 969 |             << " frames_per_burst:" << framesPerBurst | 
 | 970 |             << " buffer_size:" << bufferSizeInFrames | 
 | 971 |             << " buffer_capacity:" << bufferCapacityInFrames | 
 | 972 |             << " channel_count:" << channelCount | 
 | 973 |             << " total_frames_transferred:" << totalFramesTransferred | 
 | 974 |             << " perf_mode_requested:" << perfModeRequested << "(" << perfModeRequestedStr << ")" | 
 | 975 |             << " perf_mode_actual:" << perfModeActual | 
 | 976 |             << " sharing:" << sharingMode << "(" << sharingModeStr << ")" | 
 | 977 |             << " xrun_count:" << xrunCount | 
 | 978 |             << " device_type:" << deviceType | 
 | 979 |             << " format_app:" << formatApp | 
 | 980 |             << " format_device: " << formatDevice << "(" << formatDeviceStr << ")"; | 
 | 981 |  | 
 | 982 |     // TODO: send the metric to statsd when the proto is ready | 
 | 983 |     // if (mAudioAnalytics.mDeliverStatistics) { | 
 | 984 |     //     const auto [ result, str ] = sendToStatsd(AAudioStreamFields, | 
 | 985 |     //             CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED) | 
 | 986 |     //             , callerName | 
 | 987 |     //             , path | 
 | 988 |     //             , direction | 
 | 989 |     //             , framesPerBurst | 
 | 990 |     //             , bufferSizeInFrames | 
 | 991 |     //             , bufferCapacityInFrames | 
 | 992 |     //             , channelCount | 
 | 993 |     //             , totalFramesTransferred | 
 | 994 |     //             , perfModeRequested | 
 | 995 |     //             , perfModeActual | 
 | 996 |     //             , sharingMode | 
 | 997 |     //             , xrunCount | 
 | 998 |     //             , deviceType.c_str() | 
 | 999 |     //             , formatApp | 
 | 1000 |     //             , formatDevice | 
 | 1001 |     //             ); | 
 | 1002 |     //     ALOGV("%s: statsd %s", __func__, str.c_str()); | 
 | 1003 |     //     mAudioAnalytics.mStatsdLog.log("%s", str.c_str()); | 
 | 1004 |     // } | 
 | 1005 | } | 
 | 1006 |  | 
| Andy Hung | 3ab1b32 | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 1007 | } // namespace android::mediametrics |