blob: a936ac85534b7e1ed066a6175e1f35564e23bc93 [file] [log] [blame]
Andy Hung06f3aba2019-12-03 16:36:42 -08001/*
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 Hung1ea842e2020-05-18 10:47:31 -070019#include <android-base/logging.h>
Andy Hung06f3aba2019-12-03 16:36:42 -080020#include <utils/Log.h>
21
22#include "AudioAnalytics.h"
Andy Hung1ea842e2020-05-18 10:47:31 -070023
Andy Hung73dc2f92021-12-07 21:50:04 -080024#include <aaudio/AAudio.h> // error codes
Andy Hungce9b6632020-04-28 20:15:17 -070025#include <audio_utils/clock.h> // clock conversions
Andy Hung1ea842e2020-05-18 10:47:31 -070026#include <cutils/properties.h>
Andy Hungce9b6632020-04-28 20:15:17 -070027#include <statslog.h> // statsd
jiabinfbf20302021-07-28 22:15:01 +000028#include <system/audio.h>
Andy Hung06f3aba2019-12-03 16:36:42 -080029
Andy Hung1ea842e2020-05-18 10:47:31 -070030#include "AudioTypes.h" // string to int conversions
31#include "MediaMetricsService.h" // package info
32#include "StringUtils.h"
Andy Hungc9b6f8b2021-07-08 10:17:55 -070033#include "ValidateId.h"
Andy Hung1ea842e2020-05-18 10:47:31 -070034
35#define PROP_AUDIO_ANALYTICS_CLOUD_ENABLED "persist.audio.analytics.cloud.enabled"
36
Andy Hunga629bd12020-06-05 16:03:53 -070037namespace android::mediametrics {
Andy Hung1ea842e2020-05-18 10:47:31 -070038
Andy Hunga629bd12020-06-05 16:03:53 -070039// Enable for testing of delivery to statsd. Caution if this is enabled, all protos MUST exist.
Andy Hunga0a5ad22020-06-12 09:30:34 -070040#define STATSD_ENABLE
Andy Hung1ea842e2020-05-18 10:47:31 -070041
Andy Hunga629bd12020-06-05 16:03:53 -070042#ifdef STATSD_ENABLE
43#define CONDITION(INT_VALUE) (INT_VALUE) // allow value
Andy Hung1ea842e2020-05-18 10:47:31 -070044#else
Andy Hunga629bd12020-06-05 16:03:53 -070045#define CONDITION(INT_VALUE) (int(0)) // mask value since the proto may not be defined yet.
Andy Hung1ea842e2020-05-18 10:47:31 -070046#endif
47
Andy Hunga629bd12020-06-05 16:03:53 -070048// Maximum length of a device name.
Andy Hung3deef2b2020-07-17 12:58:54 -070049// static constexpr size_t STATSD_DEVICE_NAME_MAX_LENGTH = 32; // unused since we suppress
Andy Hung06f3aba2019-12-03 16:36:42 -080050
Andy Hunga629bd12020-06-05 16:03:53 -070051// Transmit Enums to statsd in integer or strings (this must match the atoms.proto)
52static constexpr bool STATSD_USE_INT_FOR_ENUM = false;
53
54// derive types based on integer or strings.
55using short_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int32_t, std::string>;
56using long_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int64_t, std::string>;
57
58// Convert std::string to char *
59template <typename T>
60auto ENUM_EXTRACT(const T& x) {
61 if constexpr (std::is_same_v<std::decay_t<T>, std::string>) {
62 return x.c_str();
63 } else {
64 return x;
65 }
66}
67
Andy Hung73dc2f92021-12-07 21:50:04 -080068// The status variable contains status_t codes which are used by
69// the core audio framework. We also consider AAudio status codes.
70//
71// Compare with mediametrics::statusToStatusString
72//
73inline constexpr const char* extendedStatusToStatusString(status_t status) {
74 switch (status) {
75 case BAD_VALUE: // status_t
76 case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
77 case AAUDIO_ERROR_INVALID_FORMAT:
78 case AAUDIO_ERROR_INVALID_RATE:
79 case AAUDIO_ERROR_NULL:
80 case AAUDIO_ERROR_OUT_OF_RANGE:
81 return AMEDIAMETRICS_PROP_STATUS_VALUE_ARGUMENT;
82 case DEAD_OBJECT: // status_t
83 case FAILED_TRANSACTION: // status_t
84 case AAUDIO_ERROR_DISCONNECTED:
85 case AAUDIO_ERROR_INVALID_HANDLE:
86 case AAUDIO_ERROR_NO_SERVICE:
87 return AMEDIAMETRICS_PROP_STATUS_VALUE_IO;
88 case NO_MEMORY: // status_t
89 case AAUDIO_ERROR_NO_FREE_HANDLES:
90 case AAUDIO_ERROR_NO_MEMORY:
91 return AMEDIAMETRICS_PROP_STATUS_VALUE_MEMORY;
92 case PERMISSION_DENIED: // status_t
93 return AMEDIAMETRICS_PROP_STATUS_VALUE_SECURITY;
94 case INVALID_OPERATION: // status_t
95 case NO_INIT: // status_t
96 case AAUDIO_ERROR_INVALID_STATE:
97 case AAUDIO_ERROR_UNAVAILABLE:
98 case AAUDIO_ERROR_UNIMPLEMENTED:
99 return AMEDIAMETRICS_PROP_STATUS_VALUE_STATE;
100 case WOULD_BLOCK: // status_t
101 case AAUDIO_ERROR_TIMEOUT:
102 case AAUDIO_ERROR_WOULD_BLOCK:
103 return AMEDIAMETRICS_PROP_STATUS_VALUE_TIMEOUT;
104 default:
105 if (status >= 0) return AMEDIAMETRICS_PROP_STATUS_VALUE_OK; // non-negative values "OK"
106 [[fallthrough]]; // negative values are error.
107 case UNKNOWN_ERROR: // status_t
108 return AMEDIAMETRICS_PROP_STATUS_VALUE_UNKNOWN;
109 }
110}
111
Andy Hunga629bd12020-06-05 16:03:53 -0700112static constexpr const auto LOG_LEVEL = android::base::VERBOSE;
113
Andy Hungb18f5062020-06-18 23:10:08 -0700114static constexpr int PREVIOUS_STATE_EXPIRE_SEC = 60 * 60; // 1 hour.
115
Andy Hung3deef2b2020-07-17 12:58:54 -0700116static constexpr const char * SUPPRESSED = "SUPPRESSED";
117
Andy Hunga629bd12020-06-05 16:03:53 -0700118/*
119 * For logging purposes, we list all of the MediaMetrics atom fields,
120 * which can then be associated with consecutive arguments to the statsd write.
121 */
122
123static constexpr const char * const AudioRecordDeviceUsageFields[] = {
124 "mediametrics_audiorecorddeviceusage_reported", // proto number
125 "devices",
126 "device_names",
127 "device_time_nanos",
128 "encoding",
129 "frame_count",
130 "interval_count",
131 "sample_rate",
132 "flags",
133 "package_name",
134 "selected_device_id",
135 "caller",
136 "source",
Andy Hungcbcfaa22021-02-23 13:54:49 -0800137 "log_session_id",
Andy Hunga629bd12020-06-05 16:03:53 -0700138};
139
140static constexpr const char * const AudioThreadDeviceUsageFields[] = {
141 "mediametrics_audiothreaddeviceusage_reported",
142 "devices",
143 "device_names",
144 "device_time_nanos",
145 "encoding",
146 "frame_count",
147 "interval_count",
148 "sample_rate",
149 "flags",
150 "xruns",
151 "type",
152};
153
154static constexpr const char * const AudioTrackDeviceUsageFields[] = {
155 "mediametrics_audiotrackdeviceusage_reported",
156 "devices",
157 "device_names",
158 "device_time_nanos",
159 "encoding",
160 "frame_count",
161 "interval_count",
162 "sample_rate",
163 "flags",
164 "xruns",
165 "package_name",
166 "device_latency_millis",
167 "device_startup_millis",
168 "device_volume",
169 "selected_device_id",
170 "stream_type",
171 "usage",
172 "content_type",
173 "caller",
174 "traits",
Andy Hungcbcfaa22021-02-23 13:54:49 -0800175 "log_session_id",
Andy Hunga629bd12020-06-05 16:03:53 -0700176};
177
Andy Hungb8918b52021-12-14 22:15:40 -0800178static constexpr const char * const AudioTrackStatusFields[] {
179 "mediametrics_audiotrackstatus_reported",
180 "status",
181 "debug_message",
Andy Hungcb40b982022-01-31 20:08:25 -0800182 "status_subcode",
Andy Hungb8918b52021-12-14 22:15:40 -0800183 "uid",
184 "event",
Andy Hungcb40b982022-01-31 20:08:25 -0800185 "output_flags",
Andy Hungb8918b52021-12-14 22:15:40 -0800186 "content_type",
187 "usage",
188 "encoding",
189 "channel_mask",
190 "buffer_frame_count",
191 "sample_rate",
192 "speed",
193 "pitch",
194};
195
Andy Hunga629bd12020-06-05 16:03:53 -0700196static constexpr const char * const AudioDeviceConnectionFields[] = {
197 "mediametrics_audiodeviceconnection_reported",
198 "input_devices",
199 "output_devices",
200 "device_names",
201 "result",
202 "time_to_connect_millis",
203 "connection_count",
204};
205
jiabin92c9a522021-02-12 22:37:42 +0000206static constexpr const char * const AAudioStreamFields[] {
207 "mediametrics_aaudiostream_reported",
jiabin92c9a522021-02-12 22:37:42 +0000208 "path",
209 "direction",
210 "frames_per_burst",
211 "buffer_size",
212 "buffer_capacity",
213 "channel_count",
214 "total_frames_transferred",
215 "perf_mode_requested",
216 "perf_mode_actual",
217 "sharing",
218 "xrun_count",
219 "device_type",
220 "format_app",
221 "format_device",
222 "log_session_id",
jiabinc4c331c2021-03-23 17:11:01 +0000223 "sample_rate",
224 "content_type",
jiabinc8da9032021-04-28 20:42:36 +0000225 "sharing_requested",
jiabin92c9a522021-02-12 22:37:42 +0000226};
227
228/**
229 * printFields is a helper method that prints the fields and corresponding values
230 * in a human readable style.
231 */
232template <size_t N, typename ...Types>
233std::string printFields(const char * const (& fields)[N], Types ... args)
234{
235 std::stringstream ss;
236 ss << " { ";
237 stringutils::fieldPrint(ss, fields, args...);
238 ss << "}";
239 return ss.str();
240}
241
242/**
243 * sendToStatsd is a helper method that sends the arguments to statsd
244 */
245template <typename ...Types>
246int sendToStatsd(Types ... args)
247{
248 int result = 0;
249
250#ifdef STATSD_ENABLE
251 result = android::util::stats_write(args...);
252#endif
253 return result;
254}
jiabin515eb092020-11-18 17:55:52 -0800255
Andy Hunga629bd12020-06-05 16:03:53 -0700256/**
257 * sendToStatsd is a helper method that sends the arguments to statsd
258 * and returns a pair { result, summary_string }.
259 */
260template <size_t N, typename ...Types>
261std::pair<int, std::string> sendToStatsd(const char * const (& fields)[N], Types ... args)
262{
263 int result = 0;
264 std::stringstream ss;
265
266#ifdef STATSD_ENABLE
267 result = android::util::stats_write(args...);
268 ss << "result:" << result;
269#endif
270 ss << " { ";
271 stringutils::fieldPrint(ss, fields, args...);
272 ss << "}";
273 return { result, ss.str() };
274}
Andy Hung06f3aba2019-12-03 16:36:42 -0800275
Andy Hung5be90c82021-03-30 14:30:20 -0700276AudioAnalytics::AudioAnalytics(const std::shared_ptr<StatsdLog>& statsdLog)
Andy Hung1ea842e2020-05-18 10:47:31 -0700277 : mDeliverStatistics(property_get_bool(PROP_AUDIO_ANALYTICS_CLOUD_ENABLED, true))
Andy Hung5be90c82021-03-30 14:30:20 -0700278 , mStatsdLog(statsdLog)
279 , mAudioPowerUsage(this, statsdLog)
Andy Hung06f3aba2019-12-03 16:36:42 -0800280{
Andy Hunga629bd12020-06-05 16:03:53 -0700281 SetMinimumLogSeverity(android::base::DEBUG); // for LOG().
Andy Hung06f3aba2019-12-03 16:36:42 -0800282 ALOGD("%s", __func__);
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800283
284 // Add action to save AnalyticsState if audioserver is restarted.
285 // This triggers on an item of "audio.flinger"
286 // with a property "event" set to "AudioFlinger" (the constructor).
287 mActions.addAction(
Andy Hungea186fa2020-01-09 18:13:15 -0800288 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
289 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR),
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800290 std::make_shared<AnalyticsActions::Function>(
Andy Hungea186fa2020-01-09 18:13:15 -0800291 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
292 ALOGW("(key=%s) Audioflinger constructor event detected", item->getKey().c_str());
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800293 mPreviousAnalyticsState.set(std::make_shared<AnalyticsState>(
294 *mAnalyticsState.get()));
295 // Note: get returns shared_ptr temp, whose lifetime is extended
296 // to end of full expression.
297 mAnalyticsState->clear(); // TODO: filter the analytics state.
Andy Hungea186fa2020-01-09 18:13:15 -0800298 // Perhaps report this.
Andy Hungb18f5062020-06-18 23:10:08 -0700299
300 // Set up a timer to expire the previous audio state to save space.
301 // Use the transaction log size as a cookie to see if it is the
302 // same as before. A benign race is possible where a state is cleared early.
303 const size_t size = mPreviousAnalyticsState->transactionLog().size();
304 mTimedAction.postIn(
305 std::chrono::seconds(PREVIOUS_STATE_EXPIRE_SEC), [this, size](){
306 if (mPreviousAnalyticsState->transactionLog().size() == size) {
307 ALOGD("expiring previous audio state after %d seconds.",
308 PREVIOUS_STATE_EXPIRE_SEC);
309 mPreviousAnalyticsState->clear(); // removes data from the state.
310 }
311 });
Andy Hungea186fa2020-01-09 18:13:15 -0800312 }));
313
jiabin97247ea2021-04-07 00:33:38 +0000314 // Handle legacy aaudio playback stream statistics
jiabin515eb092020-11-18 17:55:52 -0800315 mActions.addAction(
316 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
317 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
318 std::make_shared<AnalyticsActions::Function>(
319 [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
320 mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
321 }));
322
jiabin97247ea2021-04-07 00:33:38 +0000323 // Handle legacy aaudio capture stream statistics
324 mActions.addAction(
325 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
326 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
327 std::make_shared<AnalyticsActions::Function>(
328 [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
329 mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
330 }));
331
jiabin515eb092020-11-18 17:55:52 -0800332 // Handle mmap aaudio stream statistics
333 mActions.addAction(
334 AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*." AMEDIAMETRICS_PROP_EVENT,
335 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
336 std::make_shared<AnalyticsActions::Function>(
337 [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
338 mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_MMAP);
339 }));
340
Andy Hungea840382020-05-05 21:50:17 -0700341 // Handle device use record statistics
Andy Hungea186fa2020-01-09 18:13:15 -0800342 mActions.addAction(
Andy Hungea840382020-05-05 21:50:17 -0700343 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
344 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
Andy Hungea186fa2020-01-09 18:13:15 -0800345 std::make_shared<AnalyticsActions::Function>(
346 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
Andy Hungea840382020-05-05 21:50:17 -0700347 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::RECORD);
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800348 }));
Andy Hungce9b6632020-04-28 20:15:17 -0700349
350 // Handle device use thread statistics
351 mActions.addAction(
352 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
353 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
354 std::make_shared<AnalyticsActions::Function>(
355 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
Andy Hungea840382020-05-05 21:50:17 -0700356 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::THREAD);
Andy Hungce9b6632020-04-28 20:15:17 -0700357 }));
358
359 // Handle device use track statistics
360 mActions.addAction(
361 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
362 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
363 std::make_shared<AnalyticsActions::Function>(
364 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
Andy Hungea840382020-05-05 21:50:17 -0700365 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::TRACK);
Andy Hungce9b6632020-04-28 20:15:17 -0700366 }));
367
Andy Hungea840382020-05-05 21:50:17 -0700368
369 // Handle device connection statistics
Andy Hungce9b6632020-04-28 20:15:17 -0700370
371 // We track connections (not disconnections) for the time to connect.
372 // TODO: consider BT requests in their A2dp service
373 // AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
374 // AudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
375 // AudioDeviceBroker.postA2dpActiveDeviceChange
376 mActions.addAction(
377 "audio.device.a2dp.state",
Andy Hungea840382020-05-05 21:50:17 -0700378 "connected",
Andy Hungce9b6632020-04-28 20:15:17 -0700379 std::make_shared<AnalyticsActions::Function>(
380 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
381 mDeviceConnection.a2dpConnected(item);
382 }));
383 // If audio is active, we expect to see a createAudioPatch after the device is connected.
384 mActions.addAction(
385 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
386 std::string("createAudioPatch"),
387 std::make_shared<AnalyticsActions::Function>(
388 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
389 mDeviceConnection.createPatch(item);
390 }));
Joey Poomarin52989982020-03-05 17:40:49 +0800391
Andy Hungea840382020-05-05 21:50:17 -0700392 // Called from BT service
393 mActions.addAction(
394 AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE
395 "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent"
396 "." AMEDIAMETRICS_PROP_STATE,
397 "connected",
398 std::make_shared<AnalyticsActions::Function>(
399 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
400 mDeviceConnection.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(item);
401 }));
402
Joey Poomarin52989982020-03-05 17:40:49 +0800403 // Handle power usage
404 mActions.addAction(
405 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
406 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
407 std::make_shared<AnalyticsActions::Function>(
408 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
409 mAudioPowerUsage.checkTrackRecord(item, true /* isTrack */);
410 }));
411
412 mActions.addAction(
413 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
414 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
415 std::make_shared<AnalyticsActions::Function>(
416 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
417 mAudioPowerUsage.checkTrackRecord(item, false /* isTrack */);
418 }));
419
420 mActions.addAction(
421 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
422 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE),
423 std::make_shared<AnalyticsActions::Function>(
424 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
425 // ALOGD("(key=%s) Audioflinger setMode", item->getKey().c_str());
426 mAudioPowerUsage.checkMode(item);
427 }));
428
429 mActions.addAction(
430 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
431 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME),
432 std::make_shared<AnalyticsActions::Function>(
433 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
434 // ALOGD("(key=%s) Audioflinger setVoiceVolume", item->getKey().c_str());
435 mAudioPowerUsage.checkVoiceVolume(item);
436 }));
437
438 mActions.addAction(
439 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
440 std::string("createAudioPatch"),
441 std::make_shared<AnalyticsActions::Function>(
442 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
443 mAudioPowerUsage.checkCreatePatch(item);
444 }));
Andy Hung06f3aba2019-12-03 16:36:42 -0800445}
446
447AudioAnalytics::~AudioAnalytics()
448{
449 ALOGD("%s", __func__);
Andy Hungce9b6632020-04-28 20:15:17 -0700450 mTimedAction.quit(); // ensure no deferred access during destructor.
Andy Hung06f3aba2019-12-03 16:36:42 -0800451}
452
453status_t AudioAnalytics::submit(
Ray Essickf27e9872019-12-07 06:28:46 -0800454 const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted)
Andy Hung06f3aba2019-12-03 16:36:42 -0800455{
Andy Hungea186fa2020-01-09 18:13:15 -0800456 if (!startsWith(item->getKey(), AMEDIAMETRICS_KEY_PREFIX_AUDIO)) return BAD_VALUE;
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800457 status_t status = mAnalyticsState->submit(item, isTrusted);
Andy Hung73dc2f92021-12-07 21:50:04 -0800458
459 // Status is selectively authenticated.
460 processStatus(item);
461
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800462 if (status != NO_ERROR) return status; // may not be permitted.
463
464 // Only if the item was successfully submitted (permission)
465 // do we check triggered actions.
Andy Hung73dc2f92021-12-07 21:50:04 -0800466 processActions(item);
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800467 return NO_ERROR;
Andy Hung06f3aba2019-12-03 16:36:42 -0800468}
469
Andy Hung709b91e2020-04-04 14:23:36 -0700470std::pair<std::string, int32_t> AudioAnalytics::dump(
471 int32_t lines, int64_t sinceNs, const char *prefix) const
Andy Hung06f3aba2019-12-03 16:36:42 -0800472{
473 std::stringstream ss;
474 int32_t ll = lines;
475
476 if (ll > 0) {
Andy Hung709b91e2020-04-04 14:23:36 -0700477 auto [s, l] = mAnalyticsState->dump(ll, sinceNs, prefix);
Andy Hungb744faf2020-04-09 13:09:26 -0700478 ss << s;
Andy Hung06f3aba2019-12-03 16:36:42 -0800479 ll -= l;
480 }
481 if (ll > 0) {
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800482 ss << "Prior audioserver state:\n";
Andy Hung06f3aba2019-12-03 16:36:42 -0800483 --ll;
484 }
485 if (ll > 0) {
Andy Hung709b91e2020-04-04 14:23:36 -0700486 auto [s, l] = mPreviousAnalyticsState->dump(ll, sinceNs, prefix);
Andy Hungb744faf2020-04-09 13:09:26 -0700487 ss << s;
Andy Hung06f3aba2019-12-03 16:36:42 -0800488 ll -= l;
489 }
Joey Poomarin52989982020-03-05 17:40:49 +0800490
491 if (ll > 0 && prefix == nullptr) {
492 auto [s, l] = mAudioPowerUsage.dump(ll);
493 ss << s;
494 ll -= l;
495 }
Andy Hunga629bd12020-06-05 16:03:53 -0700496
Andy Hung06f3aba2019-12-03 16:36:42 -0800497 return { ss.str(), lines - ll };
498}
499
Andy Hung73dc2f92021-12-07 21:50:04 -0800500void AudioAnalytics::processActions(const std::shared_ptr<const mediametrics::Item>& item)
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800501{
502 auto actions = mActions.getActionsForItem(item); // internally locked.
503 // Execute actions with no lock held.
504 for (const auto& action : actions) {
505 (*action)(item);
506 }
507}
508
Andy Hung73dc2f92021-12-07 21:50:04 -0800509void AudioAnalytics::processStatus(const std::shared_ptr<const mediametrics::Item>& item)
510{
511 int32_t status;
512 if (!item->get(AMEDIAMETRICS_PROP_STATUS, &status)) return;
513
514 // Any record with a status will automatically be added to a heat map.
515 // Standard information.
516 const auto key = item->getKey();
517 const auto uid = item->getUid();
518
519 // from audio.track.10 -> prefix = audio.track, suffix = 10
520 // from audio.track.error -> prefix = audio.track, suffix = error
521 const auto [prefixKey, suffixKey] = stringutils::splitPrefixKey(key);
522
523 std::string message;
524 item->get(AMEDIAMETRICS_PROP_STATUSMESSAGE, &message); // optional
525
526 int32_t subCode = 0; // not used
527 (void)item->get(AMEDIAMETRICS_PROP_STATUSSUBCODE, &subCode); // optional
528
529 std::string eventStr; // optional
530 item->get(AMEDIAMETRICS_PROP_EVENT, &eventStr);
531
532 const std::string statusString = extendedStatusToStatusString(status);
533
534 // Add to the heat map - we automatically track every item's status to see
535 // the types of errors and the frequency of errors.
536 mHeatMap.add(prefixKey, suffixKey, eventStr, statusString, uid, message, subCode);
Andy Hungb8918b52021-12-14 22:15:40 -0800537
538 // Certain keys/event pairs are sent to statsd.
539 // Note that the prefixes often end with a '.' so we use startsWith.
540 if (startsWith(key, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
541 && eventStr == AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE) {
542 const int atom_status = types::lookup<types::STATUS, int32_t>(statusString);
543
544 // currently we only send create status events.
Andy Hungcb40b982022-01-31 20:08:25 -0800545 const int32_t event = android::util::
546 MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__EVENT__AUDIO_TRACK_EVENT_CREATE;
Andy Hungb8918b52021-12-14 22:15:40 -0800547
548 // The following fields should all be present in a create event.
549 std::string flagsStr;
550 ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_ORIGINALFLAGS, &flagsStr),
551 "%s: %s missing %s field",
552 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_ORIGINALFLAGS);
553 const auto flags = types::lookup<types::OUTPUT_FLAG, int32_t>(flagsStr);
554
555 // AMEDIAMETRICS_PROP_SESSIONID omitted from atom
556
557 std::string contentTypeStr;
558 ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_CONTENTTYPE, &contentTypeStr),
559 "%s: %s missing %s field",
560 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_CONTENTTYPE);
561 const auto contentType = types::lookup<types::CONTENT_TYPE, int32_t>(contentTypeStr);
562
563 std::string usageStr;
564 ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_USAGE, &usageStr),
565 "%s: %s missing %s field",
566 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_USAGE);
567 const auto usage = types::lookup<types::USAGE, int32_t>(usageStr);
568
569 // AMEDIAMETRICS_PROP_SELECTEDDEVICEID omitted from atom
570
571 std::string encodingStr;
572 ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_ENCODING, &encodingStr),
573 "%s: %s missing %s field",
574 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_ENCODING);
575 const auto encoding = types::lookup<types::ENCODING, int32_t>(encodingStr);
576
577 int32_t channelMask = 0;
578 ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_CHANNELMASK, &channelMask),
579 "%s: %s missing %s field",
580 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_CHANNELMASK);
581 int32_t frameCount = 0;
582 ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount),
583 "%s: %s missing %s field",
584 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_FRAMECOUNT);
585 int32_t sampleRate = 0;
586 ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate),
587 "%s: %s missing %s field",
588 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_SAMPLERATE);
589 double speed = 0.f; // default is 1.f
590 ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_PLAYBACK_SPEED, &speed),
591 "%s: %s missing %s field",
592 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_PLAYBACK_SPEED);
593 double pitch = 0.f; // default is 1.f
594 ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_PLAYBACK_PITCH, &pitch),
595 "%s: %s missing %s field",
596 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_PLAYBACK_PITCH);
597 const auto [ result, str ] = sendToStatsd(AudioTrackStatusFields,
598 CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED)
599 , atom_status
600 , message.c_str()
601 , subCode
602 , uid
603 , event
604 , flags
605 , contentType
606 , usage
607 , encoding
608 , (int64_t)channelMask
609 , frameCount
610 , sampleRate
611 , (float)speed
612 , (float)pitch
613 );
614 ALOGV("%s: statsd %s", __func__, str.c_str());
615 mStatsdLog->log(android::util::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED, str);
616 }
Andy Hung73dc2f92021-12-07 21:50:04 -0800617}
618
Andy Hungea186fa2020-01-09 18:13:15 -0800619// HELPER METHODS
620
621std::string AudioAnalytics::getThreadFromTrack(const std::string& track) const
622{
623 int32_t threadId_int32{};
624 if (mAnalyticsState->timeMachine().get(
625 track, AMEDIAMETRICS_PROP_THREADID, &threadId_int32) != NO_ERROR) {
626 return {};
627 }
628 return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(threadId_int32);
629}
630
Andy Hungce9b6632020-04-28 20:15:17 -0700631// DeviceUse helper class.
632void AudioAnalytics::DeviceUse::endAudioIntervalGroup(
Andy Hungea840382020-05-05 21:50:17 -0700633 const std::shared_ptr<const android::mediametrics::Item> &item, ItemType itemType) const {
Andy Hungce9b6632020-04-28 20:15:17 -0700634 const std::string& key = item->getKey();
635 const std::string id = key.substr(
Andy Hungea840382020-05-05 21:50:17 -0700636 (itemType == THREAD ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD)
637 : itemType == TRACK ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
638 : sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD))
Andy Hungce9b6632020-04-28 20:15:17 -0700639 - 1);
640 // deliver statistics
641 int64_t deviceTimeNs = 0;
642 mAudioAnalytics.mAnalyticsState->timeMachine().get(
643 key, AMEDIAMETRICS_PROP_DEVICETIMENS, &deviceTimeNs);
644 std::string encoding;
645 mAudioAnalytics.mAnalyticsState->timeMachine().get(
646 key, AMEDIAMETRICS_PROP_ENCODING, &encoding);
647 int32_t frameCount = 0;
648 mAudioAnalytics.mAnalyticsState->timeMachine().get(
649 key, AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount);
Andy Hung1ea842e2020-05-18 10:47:31 -0700650 std::string inputDevicePairs;
Andy Hungea840382020-05-05 21:50:17 -0700651 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hung1ea842e2020-05-18 10:47:31 -0700652 key, AMEDIAMETRICS_PROP_INPUTDEVICES, &inputDevicePairs);
Andy Hungce9b6632020-04-28 20:15:17 -0700653 int32_t intervalCount = 0;
654 mAudioAnalytics.mAnalyticsState->timeMachine().get(
655 key, AMEDIAMETRICS_PROP_INTERVALCOUNT, &intervalCount);
Andy Hung1ea842e2020-05-18 10:47:31 -0700656 std::string outputDevicePairs;
Andy Hungce9b6632020-04-28 20:15:17 -0700657 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hung1ea842e2020-05-18 10:47:31 -0700658 key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevicePairs);
Andy Hungce9b6632020-04-28 20:15:17 -0700659 int32_t sampleRate = 0;
660 mAudioAnalytics.mAnalyticsState->timeMachine().get(
661 key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
Andy Hungea840382020-05-05 21:50:17 -0700662 std::string flags;
Andy Hungce9b6632020-04-28 20:15:17 -0700663 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hungea840382020-05-05 21:50:17 -0700664 key, AMEDIAMETRICS_PROP_FLAGS, &flags);
Andy Hung1ea842e2020-05-18 10:47:31 -0700665
Andy Hungea840382020-05-05 21:50:17 -0700666 // We may have several devices.
Andy Hung1ea842e2020-05-18 10:47:31 -0700667 // Accumulate the bit flags for input and output devices.
668 std::stringstream oss;
669 long_enum_type_t outputDeviceBits{};
670 { // compute outputDevices
671 const auto devaddrvec = stringutils::getDeviceAddressPairs(outputDevicePairs);
Andy Hungea840382020-05-05 21:50:17 -0700672 for (const auto& [device, addr] : devaddrvec) {
Andy Hung1ea842e2020-05-18 10:47:31 -0700673 if (oss.tellp() > 0) oss << "|"; // delimit devices with '|'.
674 oss << device;
675 outputDeviceBits += types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(device);
Andy Hungea840382020-05-05 21:50:17 -0700676 }
677 }
Andy Hung1ea842e2020-05-18 10:47:31 -0700678 const std::string outputDevices = oss.str();
679
680 std::stringstream iss;
681 long_enum_type_t inputDeviceBits{};
682 { // compute inputDevices
683 const auto devaddrvec = stringutils::getDeviceAddressPairs(inputDevicePairs);
684 for (const auto& [device, addr] : devaddrvec) {
685 if (iss.tellp() > 0) iss << "|"; // delimit devices with '|'.
686 iss << device;
687 inputDeviceBits += types::lookup<types::INPUT_DEVICE, long_enum_type_t>(device);
688 }
689 }
690 const std::string inputDevices = iss.str();
Andy Hungce9b6632020-04-28 20:15:17 -0700691
692 // Get connected device name if from bluetooth.
693 bool isBluetooth = false;
Andy Hunga629bd12020-06-05 16:03:53 -0700694
695 std::string inputDeviceNames; // not filled currently.
696 std::string outputDeviceNames;
Andy Hungce9b6632020-04-28 20:15:17 -0700697 if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos) {
698 isBluetooth = true;
Andy Hung3deef2b2020-07-17 12:58:54 -0700699 outputDeviceNames = SUPPRESSED;
700#if 0 // TODO(b/161554630) sanitize name
Andy Hungce9b6632020-04-28 20:15:17 -0700701 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hunga629bd12020-06-05 16:03:53 -0700702 "audio.device.bt_a2dp", AMEDIAMETRICS_PROP_NAME, &outputDeviceNames);
Andy Hung1ea842e2020-05-18 10:47:31 -0700703 // Remove | if present
Andy Hunga629bd12020-06-05 16:03:53 -0700704 stringutils::replace(outputDeviceNames, "|", '?');
705 if (outputDeviceNames.size() > STATSD_DEVICE_NAME_MAX_LENGTH) {
706 outputDeviceNames.resize(STATSD_DEVICE_NAME_MAX_LENGTH); // truncate
707 }
Andy Hung3deef2b2020-07-17 12:58:54 -0700708#endif
Andy Hungce9b6632020-04-28 20:15:17 -0700709 }
710
Andy Hungea840382020-05-05 21:50:17 -0700711 switch (itemType) {
712 case RECORD: {
713 std::string callerName;
Andy Hunga629bd12020-06-05 16:03:53 -0700714 const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
715 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
Andy Hungce9b6632020-04-28 20:15:17 -0700716
Andy Hungea840382020-05-05 21:50:17 -0700717 std::string packageName;
718 int64_t versionCode = 0;
719 int32_t uid = -1;
720 mAudioAnalytics.mAnalyticsState->timeMachine().get(
721 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
722 if (uid != -1) {
723 std::tie(packageName, versionCode) =
724 MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
725 }
726
727 int32_t selectedDeviceId = 0;
728 mAudioAnalytics.mAnalyticsState->timeMachine().get(
729 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
730 std::string source;
731 mAudioAnalytics.mAnalyticsState->timeMachine().get(
732 key, AMEDIAMETRICS_PROP_SOURCE, &source);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800733 // Android S
734 std::string logSessionId;
735 mAudioAnalytics.mAnalyticsState->timeMachine().get(
736 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
Andy Hungea840382020-05-05 21:50:17 -0700737
Andy Hung1ea842e2020-05-18 10:47:31 -0700738 const auto callerNameForStats =
739 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
740 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
741 const auto flagsForStats = types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags);
742 const auto sourceForStats = types::lookup<types::SOURCE_TYPE, short_enum_type_t>(source);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800743 // Android S
Andy Hungc9b6f8b2021-07-08 10:17:55 -0700744 const auto logSessionIdForStats = ValidateId::get()->validateId(logSessionId);
Andy Hungea840382020-05-05 21:50:17 -0700745
Andy Hunga629bd12020-06-05 16:03:53 -0700746 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700747 << " id:" << id
748 << " inputDevices:" << inputDevices << "(" << inputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700749 << ") inputDeviceNames:" << inputDeviceNames
Andy Hung1ea842e2020-05-18 10:47:31 -0700750 << " deviceTimeNs:" << deviceTimeNs
751 << " encoding:" << encoding << "(" << encodingForStats
752 << ") frameCount:" << frameCount
753 << " intervalCount:" << intervalCount
754 << " sampleRate:" << sampleRate
755 << " flags:" << flags << "(" << flagsForStats
756 << ") packageName:" << packageName
757 << " selectedDeviceId:" << selectedDeviceId
758 << " callerName:" << callerName << "(" << callerNameForStats
Andy Hungcbcfaa22021-02-23 13:54:49 -0800759 << ") source:" << source << "(" << sourceForStats
760 << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats
761 << ")";
Andy Hunga629bd12020-06-05 16:03:53 -0700762 if (clientCalled // only log if client app called AudioRecord.
763 && mAudioAnalytics.mDeliverStatistics) {
764 const auto [ result, str ] = sendToStatsd(AudioRecordDeviceUsageFields,
765 CONDITION(android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700766 , ENUM_EXTRACT(inputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700767 , inputDeviceNames.c_str()
Andy Hungea840382020-05-05 21:50:17 -0700768 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700769 , ENUM_EXTRACT(encodingForStats)
Andy Hungea840382020-05-05 21:50:17 -0700770 , frameCount
771 , intervalCount
772 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700773 , ENUM_EXTRACT(flagsForStats)
Andy Hungea840382020-05-05 21:50:17 -0700774
775 , packageName.c_str()
776 , selectedDeviceId
Andy Hung1ea842e2020-05-18 10:47:31 -0700777 , ENUM_EXTRACT(callerNameForStats)
778 , ENUM_EXTRACT(sourceForStats)
Andy Hungcbcfaa22021-02-23 13:54:49 -0800779 , logSessionIdForStats.c_str()
Andy Hungea840382020-05-05 21:50:17 -0700780 );
Andy Hunga629bd12020-06-05 16:03:53 -0700781 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700782 mAudioAnalytics.mStatsdLog->log(
783 android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -0700784 }
Andy Hungea840382020-05-05 21:50:17 -0700785 } break;
786 case THREAD: {
787 std::string type;
788 mAudioAnalytics.mAnalyticsState->timeMachine().get(
789 key, AMEDIAMETRICS_PROP_TYPE, &type);
790 int32_t underrun = 0; // zero for record types
791 mAudioAnalytics.mAnalyticsState->timeMachine().get(
792 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
Andy Hung1ea842e2020-05-18 10:47:31 -0700793
794 const bool isInput = types::isInputThreadType(type);
795 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
796 const auto flagsForStats =
797 (isInput ? types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags)
798 : types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags));
799 const auto typeForStats = types::lookup<types::THREAD_TYPE, short_enum_type_t>(type);
800
Andy Hunga629bd12020-06-05 16:03:53 -0700801 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700802 << " id:" << id
803 << " inputDevices:" << inputDevices << "(" << inputDeviceBits
804 << ") outputDevices:" << outputDevices << "(" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700805 << ") inputDeviceNames:" << inputDeviceNames
806 << " outputDeviceNames:" << outputDeviceNames
Andy Hung1ea842e2020-05-18 10:47:31 -0700807 << " deviceTimeNs:" << deviceTimeNs
808 << " encoding:" << encoding << "(" << encodingForStats
809 << ") frameCount:" << frameCount
810 << " intervalCount:" << intervalCount
811 << " sampleRate:" << sampleRate
812 << " underrun:" << underrun
813 << " flags:" << flags << "(" << flagsForStats
814 << ") type:" << type << "(" << typeForStats
815 << ")";
Andy Hungea840382020-05-05 21:50:17 -0700816 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -0700817 const auto [ result, str ] = sendToStatsd(AudioThreadDeviceUsageFields,
818 CONDITION(android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
819 , isInput ? ENUM_EXTRACT(inputDeviceBits) : ENUM_EXTRACT(outputDeviceBits)
820 , isInput ? inputDeviceNames.c_str() : outputDeviceNames.c_str()
Andy Hungea840382020-05-05 21:50:17 -0700821 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700822 , ENUM_EXTRACT(encodingForStats)
Andy Hungea840382020-05-05 21:50:17 -0700823 , frameCount
824 , intervalCount
825 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700826 , ENUM_EXTRACT(flagsForStats)
Andy Hungea840382020-05-05 21:50:17 -0700827 , underrun
Andy Hung1ea842e2020-05-18 10:47:31 -0700828 , ENUM_EXTRACT(typeForStats)
Andy Hungea840382020-05-05 21:50:17 -0700829 );
Andy Hunga629bd12020-06-05 16:03:53 -0700830 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700831 mAudioAnalytics.mStatsdLog->log(
832 android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -0700833 }
Andy Hungea840382020-05-05 21:50:17 -0700834 } break;
835 case TRACK: {
Andy Hungce9b6632020-04-28 20:15:17 -0700836 std::string callerName;
Andy Hunga629bd12020-06-05 16:03:53 -0700837 const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
838 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
839
Andy Hungce9b6632020-04-28 20:15:17 -0700840 std::string contentType;
841 mAudioAnalytics.mAnalyticsState->timeMachine().get(
842 key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentType);
843 double deviceLatencyMs = 0.;
844 mAudioAnalytics.mAnalyticsState->timeMachine().get(
845 key, AMEDIAMETRICS_PROP_DEVICELATENCYMS, &deviceLatencyMs);
846 double deviceStartupMs = 0.;
847 mAudioAnalytics.mAnalyticsState->timeMachine().get(
848 key, AMEDIAMETRICS_PROP_DEVICESTARTUPMS, &deviceStartupMs);
849 double deviceVolume = 0.;
850 mAudioAnalytics.mAnalyticsState->timeMachine().get(
851 key, AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume);
852 std::string packageName;
853 int64_t versionCode = 0;
854 int32_t uid = -1;
855 mAudioAnalytics.mAnalyticsState->timeMachine().get(
856 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
857 if (uid != -1) {
858 std::tie(packageName, versionCode) =
859 MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
860 }
861 double playbackPitch = 0.;
862 mAudioAnalytics.mAnalyticsState->timeMachine().get(
863 key, AMEDIAMETRICS_PROP_PLAYBACK_PITCH, &playbackPitch);
864 double playbackSpeed = 0.;
865 mAudioAnalytics.mAnalyticsState->timeMachine().get(
866 key, AMEDIAMETRICS_PROP_PLAYBACK_SPEED, &playbackSpeed);
867 int32_t selectedDeviceId = 0;
868 mAudioAnalytics.mAnalyticsState->timeMachine().get(
869 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
Andy Hungea840382020-05-05 21:50:17 -0700870 std::string streamType;
871 mAudioAnalytics.mAnalyticsState->timeMachine().get(
872 key, AMEDIAMETRICS_PROP_STREAMTYPE, &streamType);
Andy Hunga629bd12020-06-05 16:03:53 -0700873 std::string traits;
874 mAudioAnalytics.mAnalyticsState->timeMachine().get(
875 key, AMEDIAMETRICS_PROP_TRAITS, &traits);
Andy Hungea840382020-05-05 21:50:17 -0700876 int32_t underrun = 0;
877 mAudioAnalytics.mAnalyticsState->timeMachine().get(
878 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
Andy Hungce9b6632020-04-28 20:15:17 -0700879 std::string usage;
880 mAudioAnalytics.mAnalyticsState->timeMachine().get(
881 key, AMEDIAMETRICS_PROP_USAGE, &usage);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800882 // Android S
883 std::string logSessionId;
884 mAudioAnalytics.mAnalyticsState->timeMachine().get(
885 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
Andy Hungce9b6632020-04-28 20:15:17 -0700886
Andy Hung1ea842e2020-05-18 10:47:31 -0700887 const auto callerNameForStats =
888 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
889 const auto contentTypeForStats =
890 types::lookup<types::CONTENT_TYPE, short_enum_type_t>(contentType);
891 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
892 const auto flagsForStats = types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags);
893 const auto streamTypeForStats =
894 types::lookup<types::STREAM_TYPE, short_enum_type_t>(streamType);
Andy Hunga629bd12020-06-05 16:03:53 -0700895 const auto traitsForStats =
896 types::lookup<types::TRACK_TRAITS, short_enum_type_t>(traits);
Andy Hung1ea842e2020-05-18 10:47:31 -0700897 const auto usageForStats = types::lookup<types::USAGE, short_enum_type_t>(usage);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800898 // Android S
Andy Hungc9b6f8b2021-07-08 10:17:55 -0700899 const auto logSessionIdForStats = ValidateId::get()->validateId(logSessionId);
Andy Hung1ea842e2020-05-18 10:47:31 -0700900
Andy Hunga629bd12020-06-05 16:03:53 -0700901 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700902 << " id:" << id
903 << " outputDevices:" << outputDevices << "(" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700904 << ") outputDeviceNames:" << outputDeviceNames
Andy Hung1ea842e2020-05-18 10:47:31 -0700905 << " deviceTimeNs:" << deviceTimeNs
906 << " encoding:" << encoding << "(" << encodingForStats
907 << ") frameCount:" << frameCount
908 << " intervalCount:" << intervalCount
909 << " sampleRate:" << sampleRate
910 << " underrun:" << underrun
911 << " flags:" << flags << "(" << flagsForStats
912 << ") callerName:" << callerName << "(" << callerNameForStats
913 << ") contentType:" << contentType << "(" << contentTypeForStats
914 << ") deviceLatencyMs:" << deviceLatencyMs
915 << " deviceStartupMs:" << deviceStartupMs
916 << " deviceVolume:" << deviceVolume
917 << " packageName:" << packageName
918 << " playbackPitch:" << playbackPitch
919 << " playbackSpeed:" << playbackSpeed
920 << " selectedDeviceId:" << selectedDeviceId
921 << " streamType:" << streamType << "(" << streamTypeForStats
Andy Hunga629bd12020-06-05 16:03:53 -0700922 << ") traits:" << traits << "(" << traitsForStats
Andy Hung1ea842e2020-05-18 10:47:31 -0700923 << ") usage:" << usage << "(" << usageForStats
Andy Hungcbcfaa22021-02-23 13:54:49 -0800924 << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats
Andy Hung1ea842e2020-05-18 10:47:31 -0700925 << ")";
Andy Hunga629bd12020-06-05 16:03:53 -0700926 if (clientCalled // only log if client app called AudioTracks
927 && mAudioAnalytics.mDeliverStatistics) {
928 const auto [ result, str ] = sendToStatsd(AudioTrackDeviceUsageFields,
929 CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700930 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700931 , outputDeviceNames.c_str()
Andy Hungce9b6632020-04-28 20:15:17 -0700932 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700933 , ENUM_EXTRACT(encodingForStats)
Andy Hungce9b6632020-04-28 20:15:17 -0700934 , frameCount
935 , intervalCount
936 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700937 , ENUM_EXTRACT(flagsForStats)
Andy Hungce9b6632020-04-28 20:15:17 -0700938 , underrun
Andy Hungce9b6632020-04-28 20:15:17 -0700939 , packageName.c_str()
940 , (float)deviceLatencyMs
941 , (float)deviceStartupMs
942 , (float)deviceVolume
943 , selectedDeviceId
Andy Hung1ea842e2020-05-18 10:47:31 -0700944 , ENUM_EXTRACT(streamTypeForStats)
945 , ENUM_EXTRACT(usageForStats)
946 , ENUM_EXTRACT(contentTypeForStats)
947 , ENUM_EXTRACT(callerNameForStats)
Andy Hunga629bd12020-06-05 16:03:53 -0700948 , ENUM_EXTRACT(traitsForStats)
Andy Hungcbcfaa22021-02-23 13:54:49 -0800949 , logSessionIdForStats.c_str()
Andy Hungce9b6632020-04-28 20:15:17 -0700950 );
Andy Hunga629bd12020-06-05 16:03:53 -0700951 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700952 mAudioAnalytics.mStatsdLog->log(
953 android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED, str);
Andy Hungce9b6632020-04-28 20:15:17 -0700954 }
Andy Hungea840382020-05-05 21:50:17 -0700955 } break;
Andy Hungce9b6632020-04-28 20:15:17 -0700956 }
957
958 // Report this as needed.
959 if (isBluetooth) {
960 // report this for Bluetooth
961 }
962}
963
964// DeviceConnection helper class.
965void AudioAnalytics::DeviceConnection::a2dpConnected(
966 const std::shared_ptr<const android::mediametrics::Item> &item) {
967 const std::string& key = item->getKey();
Andy Hungea840382020-05-05 21:50:17 -0700968 const int64_t atNs = item->getTimestamp();
Andy Hungce9b6632020-04-28 20:15:17 -0700969 {
970 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -0700971 mA2dpConnectionServiceNs = atNs;
972 ++mA2dpConnectionServices;
973
974 if (mA2dpConnectionRequestNs == 0) {
975 mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
976 }
977 // This sets the time we were connected. Now we look for the delta in the future.
Andy Hungce9b6632020-04-28 20:15:17 -0700978 }
979 std::string name;
980 item->get(AMEDIAMETRICS_PROP_NAME, &name);
Andy Hungea840382020-05-05 21:50:17 -0700981 ALOGD("(key=%s) a2dp connected device:%s atNs:%lld",
982 key.c_str(), name.c_str(), (long long)atNs);
Andy Hungce9b6632020-04-28 20:15:17 -0700983}
984
985void AudioAnalytics::DeviceConnection::createPatch(
986 const std::shared_ptr<const android::mediametrics::Item> &item) {
987 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -0700988 if (mA2dpConnectionServiceNs == 0) return; // patch unrelated to us.
Andy Hungce9b6632020-04-28 20:15:17 -0700989 const std::string& key = item->getKey();
990 std::string outputDevices;
991 item->get(AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices);
Andy Hungea840382020-05-05 21:50:17 -0700992 if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH_A2DP") != std::string::npos) {
Andy Hungce9b6632020-04-28 20:15:17 -0700993 // TODO compare address
Andy Hung1ea842e2020-05-18 10:47:31 -0700994 int64_t timeDiffNs = item->getTimestamp();
Andy Hungea840382020-05-05 21:50:17 -0700995 if (mA2dpConnectionRequestNs == 0) {
996 ALOGD("%s: A2DP create patch didn't see a connection request", __func__);
Andy Hung1ea842e2020-05-18 10:47:31 -0700997 timeDiffNs -= mA2dpConnectionServiceNs;
Andy Hungea840382020-05-05 21:50:17 -0700998 } else {
Andy Hung1ea842e2020-05-18 10:47:31 -0700999 timeDiffNs -= mA2dpConnectionRequestNs;
Andy Hungea840382020-05-05 21:50:17 -07001000 }
Andy Hung1ea842e2020-05-18 10:47:31 -07001001
Andy Hungea840382020-05-05 21:50:17 -07001002 mA2dpConnectionRequestNs = 0;
1003 mA2dpConnectionServiceNs = 0;
1004 ++mA2dpConnectionSuccesses;
1005
Andy Hungc14ee142021-03-10 16:39:02 -08001006 const auto connectionTimeMs = float((double)timeDiffNs * 1e-6);
Andy Hung1ea842e2020-05-18 10:47:31 -07001007
1008 const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
1009 "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
1010
Andy Hunga629bd12020-06-05 16:03:53 -07001011 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -07001012 << " A2DP SUCCESS"
1013 << " outputDevices:" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -07001014 << " deviceName:" << mA2dpDeviceName
Andy Hung1ea842e2020-05-18 10:47:31 -07001015 << " connectionTimeMs:" << connectionTimeMs;
Andy Hungea840382020-05-05 21:50:17 -07001016 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hung1ea842e2020-05-18 10:47:31 -07001017 const long_enum_type_t inputDeviceBits{};
Andy Hunga629bd12020-06-05 16:03:53 -07001018
1019 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
1020 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -07001021 , ENUM_EXTRACT(inputDeviceBits)
1022 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -07001023 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -07001024 , types::DEVICE_CONNECTION_RESULT_SUCCESS
1025 , connectionTimeMs
Andy Hungea840382020-05-05 21:50:17 -07001026 , /* connection_count */ 1
1027 );
Andy Hunga629bd12020-06-05 16:03:53 -07001028 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -07001029 mAudioAnalytics.mStatsdLog->log(
1030 android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -07001031 }
Andy Hungce9b6632020-04-28 20:15:17 -07001032 }
1033}
1034
Andy Hungea840382020-05-05 21:50:17 -07001035// Called through AudioManager when the BT service wants to enable
1036void AudioAnalytics::DeviceConnection::postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
1037 const std::shared_ptr<const android::mediametrics::Item> &item) {
1038 const int64_t atNs = item->getTimestamp();
1039 const std::string& key = item->getKey();
1040 std::string state;
1041 item->get(AMEDIAMETRICS_PROP_STATE, &state);
1042 if (state != "connected") return;
Andy Hunga629bd12020-06-05 16:03:53 -07001043
1044 std::string name;
1045 item->get(AMEDIAMETRICS_PROP_NAME, &name);
Andy Hungea840382020-05-05 21:50:17 -07001046 {
1047 std::lock_guard l(mLock);
1048 mA2dpConnectionRequestNs = atNs;
1049 ++mA2dpConnectionRequests;
Andy Hung3deef2b2020-07-17 12:58:54 -07001050 mA2dpDeviceName = SUPPRESSED; // TODO(b/161554630) sanitize name
Andy Hungea840382020-05-05 21:50:17 -07001051 }
Andy Hunga629bd12020-06-05 16:03:53 -07001052 ALOGD("(key=%s) a2dp connection name:%s request atNs:%lld",
1053 key.c_str(), name.c_str(), (long long)atNs);
Andy Hungea840382020-05-05 21:50:17 -07001054 // TODO: attempt to cancel a timed event, rather than let it expire.
1055 mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
1056}
1057
Andy Hungce9b6632020-04-28 20:15:17 -07001058void AudioAnalytics::DeviceConnection::expire() {
1059 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -07001060 if (mA2dpConnectionRequestNs == 0) return; // ignore (this was an internal connection).
Andy Hung1ea842e2020-05-18 10:47:31 -07001061
Andy Hung1ea842e2020-05-18 10:47:31 -07001062 const long_enum_type_t inputDeviceBits{};
Andy Hung1ea842e2020-05-18 10:47:31 -07001063 const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
1064 "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
1065
Andy Hungea840382020-05-05 21:50:17 -07001066 if (mA2dpConnectionServiceNs == 0) {
Andy Hungea840382020-05-05 21:50:17 -07001067 ++mA2dpConnectionJavaServiceCancels; // service did not connect to A2DP
Andy Hungce9b6632020-04-28 20:15:17 -07001068
Andy Hunga629bd12020-06-05 16:03:53 -07001069 LOG(LOG_LEVEL) << "A2DP CANCEL"
1070 << " outputDevices:" << outputDeviceBits
1071 << " deviceName:" << mA2dpDeviceName;
Andy Hungea840382020-05-05 21:50:17 -07001072 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -07001073 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
1074 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -07001075 , ENUM_EXTRACT(inputDeviceBits)
1076 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -07001077 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -07001078 , types::DEVICE_CONNECTION_RESULT_JAVA_SERVICE_CANCEL
Andy Hungea840382020-05-05 21:50:17 -07001079 , /* connection_time_ms */ 0.f
1080 , /* connection_count */ 1
1081 );
Andy Hunga629bd12020-06-05 16:03:53 -07001082 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -07001083 mAudioAnalytics.mStatsdLog->log(
1084 android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -07001085 }
Andy Hungea840382020-05-05 21:50:17 -07001086 return;
1087 }
1088
1089 // AudioFlinger didn't play - an expiration may occur because there is no audio playing.
1090 // Should we check elsewhere?
Andy Hungce9b6632020-04-28 20:15:17 -07001091 // TODO: disambiguate this case.
Andy Hungea840382020-05-05 21:50:17 -07001092 mA2dpConnectionRequestNs = 0;
1093 mA2dpConnectionServiceNs = 0;
1094 ++mA2dpConnectionUnknowns; // connection result unknown
Andy Hung1ea842e2020-05-18 10:47:31 -07001095
Andy Hunga629bd12020-06-05 16:03:53 -07001096 LOG(LOG_LEVEL) << "A2DP UNKNOWN"
1097 << " outputDevices:" << outputDeviceBits
1098 << " deviceName:" << mA2dpDeviceName;
Andy Hungea840382020-05-05 21:50:17 -07001099 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -07001100 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
1101 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -07001102 , ENUM_EXTRACT(inputDeviceBits)
1103 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -07001104 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -07001105 , types::DEVICE_CONNECTION_RESULT_UNKNOWN
Andy Hungea840382020-05-05 21:50:17 -07001106 , /* connection_time_ms */ 0.f
1107 , /* connection_count */ 1
1108 );
Andy Hunga629bd12020-06-05 16:03:53 -07001109 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -07001110 mAudioAnalytics.mStatsdLog->log(
1111 android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -07001112 }
Andy Hungce9b6632020-04-28 20:15:17 -07001113}
1114
jiabin515eb092020-11-18 17:55:52 -08001115void AudioAnalytics::AAudioStreamInfo::endAAudioStream(
1116 const std::shared_ptr<const android::mediametrics::Item> &item, CallerPath path) const {
1117 const std::string& key = item->getKey();
1118
jiabin515eb092020-11-18 17:55:52 -08001119 std::string directionStr;
1120 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1121 key, AMEDIAMETRICS_PROP_DIRECTION, &directionStr);
1122 const auto direction = types::lookup<types::AAUDIO_DIRECTION, int32_t>(directionStr);
1123
1124 int32_t framesPerBurst = -1;
1125 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1126 key, AMEDIAMETRICS_PROP_BURSTFRAMES, &framesPerBurst);
1127
1128 int32_t bufferSizeInFrames = -1;
1129 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1130 key, AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, &bufferSizeInFrames);
1131
1132 int32_t bufferCapacityInFrames = -1;
1133 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1134 key, AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, &bufferCapacityInFrames);
1135
1136 int32_t channelCount = -1;
1137 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1138 key, AMEDIAMETRICS_PROP_CHANNELCOUNT, &channelCount);
jiabinfbf20302021-07-28 22:15:01 +00001139 if (channelCount == -1) {
1140 // Try to get channel count from channel mask. From the legacy path,
1141 // only channel mask are logged.
1142 int32_t channelMask = 0;
1143 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1144 key, AMEDIAMETRICS_PROP_CHANNELMASK, &channelMask);
1145 if (channelMask != 0) {
1146 switch (direction) {
1147 case 1: // Output, keep sync with AudioTypes#getAAudioDirection()
1148 channelCount = audio_channel_count_from_out_mask(channelMask);
1149 break;
1150 case 2: // Input, keep sync with AudioTypes#getAAudioDirection()
1151 channelCount = audio_channel_count_from_in_mask(channelMask);
1152 break;
1153 default:
1154 ALOGW("Invalid direction %d", direction);
1155 }
1156 }
1157 }
jiabin515eb092020-11-18 17:55:52 -08001158
1159 int64_t totalFramesTransferred = -1;
jiabin97247ea2021-04-07 00:33:38 +00001160 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1161 key, AMEDIAMETRICS_PROP_FRAMESTRANSFERRED, &totalFramesTransferred);
jiabin515eb092020-11-18 17:55:52 -08001162
1163 std::string perfModeRequestedStr;
1164 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1165 key, AMEDIAMETRICS_PROP_PERFORMANCEMODE, &perfModeRequestedStr);
1166 const auto perfModeRequested =
1167 types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeRequestedStr);
1168
jiabin97247ea2021-04-07 00:33:38 +00001169 std::string perfModeActualStr;
1170 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1171 key, AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL, &perfModeActualStr);
1172 const auto perfModeActual =
1173 types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeActualStr);
jiabin515eb092020-11-18 17:55:52 -08001174
jiabinc8da9032021-04-28 20:42:36 +00001175 std::string sharingModeActualStr;
jiabin515eb092020-11-18 17:55:52 -08001176 mAudioAnalytics.mAnalyticsState->timeMachine().get(
jiabinc8da9032021-04-28 20:42:36 +00001177 key, AMEDIAMETRICS_PROP_SHARINGMODEACTUAL, &sharingModeActualStr);
1178 const auto sharingModeActual =
1179 types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeActualStr);
jiabin515eb092020-11-18 17:55:52 -08001180
1181 int32_t xrunCount = -1;
1182 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1183 key, AMEDIAMETRICS_PROP_UNDERRUN, &xrunCount);
1184
jiabin92c9a522021-02-12 22:37:42 +00001185 std::string serializedDeviceTypes;
jiabin515eb092020-11-18 17:55:52 -08001186 // TODO: only routed device id is logged, but no device type
1187
jiabin97247ea2021-04-07 00:33:38 +00001188 std::string formatAppStr;
1189 mAudioAnalytics.mAnalyticsState->timeMachine().get(
jiabinef348b82021-04-19 16:53:08 +00001190 key, AMEDIAMETRICS_PROP_ENCODINGCLIENT, &formatAppStr);
jiabin97247ea2021-04-07 00:33:38 +00001191 const auto formatApp = types::lookup<types::ENCODING, int32_t>(formatAppStr);
jiabin515eb092020-11-18 17:55:52 -08001192
1193 std::string formatDeviceStr;
1194 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1195 key, AMEDIAMETRICS_PROP_ENCODING, &formatDeviceStr);
1196 const auto formatDevice = types::lookup<types::ENCODING, int32_t>(formatDeviceStr);
1197
jiabin92c9a522021-02-12 22:37:42 +00001198 std::string logSessionId;
jiabin97247ea2021-04-07 00:33:38 +00001199 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1200 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
jiabin92c9a522021-02-12 22:37:42 +00001201
jiabinc4c331c2021-03-23 17:11:01 +00001202 int32_t sampleRate = 0;
1203 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1204 key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
1205
1206 std::string contentTypeStr;
1207 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1208 key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentTypeStr);
1209 const auto contentType = types::lookup<types::CONTENT_TYPE, int32_t>(contentTypeStr);
1210
jiabinc8da9032021-04-28 20:42:36 +00001211 std::string sharingModeRequestedStr;
1212 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1213 key, AMEDIAMETRICS_PROP_SHARINGMODE, &sharingModeRequestedStr);
1214 const auto sharingModeRequested =
1215 types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeRequestedStr);
1216
jiabin515eb092020-11-18 17:55:52 -08001217 LOG(LOG_LEVEL) << "key:" << key
jiabin515eb092020-11-18 17:55:52 -08001218 << " path:" << path
1219 << " direction:" << direction << "(" << directionStr << ")"
1220 << " frames_per_burst:" << framesPerBurst
1221 << " buffer_size:" << bufferSizeInFrames
1222 << " buffer_capacity:" << bufferCapacityInFrames
1223 << " channel_count:" << channelCount
1224 << " total_frames_transferred:" << totalFramesTransferred
1225 << " perf_mode_requested:" << perfModeRequested << "(" << perfModeRequestedStr << ")"
jiabin97247ea2021-04-07 00:33:38 +00001226 << " perf_mode_actual:" << perfModeActual << "(" << perfModeActualStr << ")"
jiabinc8da9032021-04-28 20:42:36 +00001227 << " sharing:" << sharingModeActual << "(" << sharingModeActualStr << ")"
jiabin515eb092020-11-18 17:55:52 -08001228 << " xrun_count:" << xrunCount
jiabin92c9a522021-02-12 22:37:42 +00001229 << " device_type:" << serializedDeviceTypes
jiabin97247ea2021-04-07 00:33:38 +00001230 << " format_app:" << formatApp << "(" << formatAppStr << ")"
jiabin92c9a522021-02-12 22:37:42 +00001231 << " format_device: " << formatDevice << "(" << formatDeviceStr << ")"
jiabinc4c331c2021-03-23 17:11:01 +00001232 << " log_session_id: " << logSessionId
1233 << " sample_rate: " << sampleRate
jiabinc8da9032021-04-28 20:42:36 +00001234 << " content_type: " << contentType << "(" << contentTypeStr << ")"
1235 << " sharing_requested:" << sharingModeRequested
1236 << "(" << sharingModeRequestedStr << ")";
jiabin515eb092020-11-18 17:55:52 -08001237
jiabin92c9a522021-02-12 22:37:42 +00001238 if (mAudioAnalytics.mDeliverStatistics) {
1239 android::util::BytesField bf_serialized(
1240 serializedDeviceTypes.c_str(), serializedDeviceTypes.size());
1241 const auto result = sendToStatsd(
1242 CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
jiabin92c9a522021-02-12 22:37:42 +00001243 , path
1244 , direction
1245 , framesPerBurst
1246 , bufferSizeInFrames
1247 , bufferCapacityInFrames
1248 , channelCount
1249 , totalFramesTransferred
1250 , perfModeRequested
1251 , perfModeActual
jiabinc8da9032021-04-28 20:42:36 +00001252 , sharingModeActual
jiabin92c9a522021-02-12 22:37:42 +00001253 , xrunCount
1254 , bf_serialized
1255 , formatApp
1256 , formatDevice
1257 , logSessionId.c_str()
jiabinc4c331c2021-03-23 17:11:01 +00001258 , sampleRate
1259 , contentType
jiabinc8da9032021-04-28 20:42:36 +00001260 , sharingModeRequested
jiabin92c9a522021-02-12 22:37:42 +00001261 );
1262 std::stringstream ss;
1263 ss << "result:" << result;
1264 const auto fieldsStr = printFields(AAudioStreamFields,
1265 CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
jiabin92c9a522021-02-12 22:37:42 +00001266 , path
1267 , direction
1268 , framesPerBurst
1269 , bufferSizeInFrames
1270 , bufferCapacityInFrames
1271 , channelCount
1272 , totalFramesTransferred
1273 , perfModeRequested
1274 , perfModeActual
jiabinc8da9032021-04-28 20:42:36 +00001275 , sharingModeActual
jiabin92c9a522021-02-12 22:37:42 +00001276 , xrunCount
1277 , serializedDeviceTypes.c_str()
1278 , formatApp
1279 , formatDevice
1280 , logSessionId.c_str()
jiabinc4c331c2021-03-23 17:11:01 +00001281 , sampleRate
1282 , contentType
jiabinc8da9032021-04-28 20:42:36 +00001283 , sharingModeRequested
jiabin92c9a522021-02-12 22:37:42 +00001284 );
1285 ss << " " << fieldsStr;
1286 std::string str = ss.str();
1287 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -07001288 mAudioAnalytics.mStatsdLog->log(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED, str);
jiabin92c9a522021-02-12 22:37:42 +00001289 }
jiabin515eb092020-11-18 17:55:52 -08001290}
1291
Andy Hung3ab1b322020-05-18 10:47:31 -07001292} // namespace android::mediametrics