blob: 46c701c090e92de0b9b4fca8c3ee6f3e4a27f4a5 [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
178static constexpr const char * const AudioDeviceConnectionFields[] = {
179 "mediametrics_audiodeviceconnection_reported",
180 "input_devices",
181 "output_devices",
182 "device_names",
183 "result",
184 "time_to_connect_millis",
185 "connection_count",
186};
187
jiabin92c9a522021-02-12 22:37:42 +0000188static constexpr const char * const AAudioStreamFields[] {
189 "mediametrics_aaudiostream_reported",
jiabin92c9a522021-02-12 22:37:42 +0000190 "path",
191 "direction",
192 "frames_per_burst",
193 "buffer_size",
194 "buffer_capacity",
195 "channel_count",
196 "total_frames_transferred",
197 "perf_mode_requested",
198 "perf_mode_actual",
199 "sharing",
200 "xrun_count",
201 "device_type",
202 "format_app",
203 "format_device",
204 "log_session_id",
jiabinc4c331c2021-03-23 17:11:01 +0000205 "sample_rate",
206 "content_type",
jiabinc8da9032021-04-28 20:42:36 +0000207 "sharing_requested",
jiabin92c9a522021-02-12 22:37:42 +0000208};
209
210/**
211 * printFields is a helper method that prints the fields and corresponding values
212 * in a human readable style.
213 */
214template <size_t N, typename ...Types>
215std::string printFields(const char * const (& fields)[N], Types ... args)
216{
217 std::stringstream ss;
218 ss << " { ";
219 stringutils::fieldPrint(ss, fields, args...);
220 ss << "}";
221 return ss.str();
222}
223
224/**
225 * sendToStatsd is a helper method that sends the arguments to statsd
226 */
227template <typename ...Types>
228int sendToStatsd(Types ... args)
229{
230 int result = 0;
231
232#ifdef STATSD_ENABLE
233 result = android::util::stats_write(args...);
234#endif
235 return result;
236}
jiabin515eb092020-11-18 17:55:52 -0800237
Andy Hunga629bd12020-06-05 16:03:53 -0700238/**
239 * sendToStatsd is a helper method that sends the arguments to statsd
240 * and returns a pair { result, summary_string }.
241 */
242template <size_t N, typename ...Types>
243std::pair<int, std::string> sendToStatsd(const char * const (& fields)[N], Types ... args)
244{
245 int result = 0;
246 std::stringstream ss;
247
248#ifdef STATSD_ENABLE
249 result = android::util::stats_write(args...);
250 ss << "result:" << result;
251#endif
252 ss << " { ";
253 stringutils::fieldPrint(ss, fields, args...);
254 ss << "}";
255 return { result, ss.str() };
256}
Andy Hung06f3aba2019-12-03 16:36:42 -0800257
Andy Hung5be90c82021-03-30 14:30:20 -0700258AudioAnalytics::AudioAnalytics(const std::shared_ptr<StatsdLog>& statsdLog)
Andy Hung1ea842e2020-05-18 10:47:31 -0700259 : mDeliverStatistics(property_get_bool(PROP_AUDIO_ANALYTICS_CLOUD_ENABLED, true))
Andy Hung5be90c82021-03-30 14:30:20 -0700260 , mStatsdLog(statsdLog)
261 , mAudioPowerUsage(this, statsdLog)
Andy Hung06f3aba2019-12-03 16:36:42 -0800262{
Andy Hunga629bd12020-06-05 16:03:53 -0700263 SetMinimumLogSeverity(android::base::DEBUG); // for LOG().
Andy Hung06f3aba2019-12-03 16:36:42 -0800264 ALOGD("%s", __func__);
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800265
266 // Add action to save AnalyticsState if audioserver is restarted.
267 // This triggers on an item of "audio.flinger"
268 // with a property "event" set to "AudioFlinger" (the constructor).
269 mActions.addAction(
Andy Hungea186fa2020-01-09 18:13:15 -0800270 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
271 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR),
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800272 std::make_shared<AnalyticsActions::Function>(
Andy Hungea186fa2020-01-09 18:13:15 -0800273 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
274 ALOGW("(key=%s) Audioflinger constructor event detected", item->getKey().c_str());
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800275 mPreviousAnalyticsState.set(std::make_shared<AnalyticsState>(
276 *mAnalyticsState.get()));
277 // Note: get returns shared_ptr temp, whose lifetime is extended
278 // to end of full expression.
279 mAnalyticsState->clear(); // TODO: filter the analytics state.
Andy Hungea186fa2020-01-09 18:13:15 -0800280 // Perhaps report this.
Andy Hungb18f5062020-06-18 23:10:08 -0700281
282 // Set up a timer to expire the previous audio state to save space.
283 // Use the transaction log size as a cookie to see if it is the
284 // same as before. A benign race is possible where a state is cleared early.
285 const size_t size = mPreviousAnalyticsState->transactionLog().size();
286 mTimedAction.postIn(
287 std::chrono::seconds(PREVIOUS_STATE_EXPIRE_SEC), [this, size](){
288 if (mPreviousAnalyticsState->transactionLog().size() == size) {
289 ALOGD("expiring previous audio state after %d seconds.",
290 PREVIOUS_STATE_EXPIRE_SEC);
291 mPreviousAnalyticsState->clear(); // removes data from the state.
292 }
293 });
Andy Hungea186fa2020-01-09 18:13:15 -0800294 }));
295
jiabin97247ea2021-04-07 00:33:38 +0000296 // Handle legacy aaudio playback stream statistics
jiabin515eb092020-11-18 17:55:52 -0800297 mActions.addAction(
298 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
299 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
300 std::make_shared<AnalyticsActions::Function>(
301 [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
302 mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
303 }));
304
jiabin97247ea2021-04-07 00:33:38 +0000305 // Handle legacy aaudio capture stream statistics
306 mActions.addAction(
307 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
308 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
309 std::make_shared<AnalyticsActions::Function>(
310 [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
311 mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
312 }));
313
jiabin515eb092020-11-18 17:55:52 -0800314 // Handle mmap aaudio stream statistics
315 mActions.addAction(
316 AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*." 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_MMAP);
321 }));
322
Andy Hungea840382020-05-05 21:50:17 -0700323 // Handle device use record statistics
Andy Hungea186fa2020-01-09 18:13:15 -0800324 mActions.addAction(
Andy Hungea840382020-05-05 21:50:17 -0700325 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
326 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
Andy Hungea186fa2020-01-09 18:13:15 -0800327 std::make_shared<AnalyticsActions::Function>(
328 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
Andy Hungea840382020-05-05 21:50:17 -0700329 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::RECORD);
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800330 }));
Andy Hungce9b6632020-04-28 20:15:17 -0700331
332 // Handle device use thread statistics
333 mActions.addAction(
334 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
335 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
336 std::make_shared<AnalyticsActions::Function>(
337 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
Andy Hungea840382020-05-05 21:50:17 -0700338 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::THREAD);
Andy Hungce9b6632020-04-28 20:15:17 -0700339 }));
340
341 // Handle device use track statistics
342 mActions.addAction(
343 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
344 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
345 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::TRACK);
Andy Hungce9b6632020-04-28 20:15:17 -0700348 }));
349
Andy Hungea840382020-05-05 21:50:17 -0700350
351 // Handle device connection statistics
Andy Hungce9b6632020-04-28 20:15:17 -0700352
353 // We track connections (not disconnections) for the time to connect.
354 // TODO: consider BT requests in their A2dp service
355 // AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
356 // AudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
357 // AudioDeviceBroker.postA2dpActiveDeviceChange
358 mActions.addAction(
359 "audio.device.a2dp.state",
Andy Hungea840382020-05-05 21:50:17 -0700360 "connected",
Andy Hungce9b6632020-04-28 20:15:17 -0700361 std::make_shared<AnalyticsActions::Function>(
362 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
363 mDeviceConnection.a2dpConnected(item);
364 }));
365 // If audio is active, we expect to see a createAudioPatch after the device is connected.
366 mActions.addAction(
367 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
368 std::string("createAudioPatch"),
369 std::make_shared<AnalyticsActions::Function>(
370 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
371 mDeviceConnection.createPatch(item);
372 }));
Joey Poomarin52989982020-03-05 17:40:49 +0800373
Andy Hungea840382020-05-05 21:50:17 -0700374 // Called from BT service
375 mActions.addAction(
376 AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE
377 "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent"
378 "." AMEDIAMETRICS_PROP_STATE,
379 "connected",
380 std::make_shared<AnalyticsActions::Function>(
381 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
382 mDeviceConnection.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(item);
383 }));
384
Joey Poomarin52989982020-03-05 17:40:49 +0800385 // Handle power usage
386 mActions.addAction(
387 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
388 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
389 std::make_shared<AnalyticsActions::Function>(
390 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
391 mAudioPowerUsage.checkTrackRecord(item, true /* isTrack */);
392 }));
393
394 mActions.addAction(
395 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
396 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
397 std::make_shared<AnalyticsActions::Function>(
398 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
399 mAudioPowerUsage.checkTrackRecord(item, false /* isTrack */);
400 }));
401
402 mActions.addAction(
403 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
404 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE),
405 std::make_shared<AnalyticsActions::Function>(
406 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
407 // ALOGD("(key=%s) Audioflinger setMode", item->getKey().c_str());
408 mAudioPowerUsage.checkMode(item);
409 }));
410
411 mActions.addAction(
412 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
413 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME),
414 std::make_shared<AnalyticsActions::Function>(
415 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
416 // ALOGD("(key=%s) Audioflinger setVoiceVolume", item->getKey().c_str());
417 mAudioPowerUsage.checkVoiceVolume(item);
418 }));
419
420 mActions.addAction(
421 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
422 std::string("createAudioPatch"),
423 std::make_shared<AnalyticsActions::Function>(
424 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
425 mAudioPowerUsage.checkCreatePatch(item);
426 }));
Andy Hung06f3aba2019-12-03 16:36:42 -0800427}
428
429AudioAnalytics::~AudioAnalytics()
430{
431 ALOGD("%s", __func__);
Andy Hungce9b6632020-04-28 20:15:17 -0700432 mTimedAction.quit(); // ensure no deferred access during destructor.
Andy Hung06f3aba2019-12-03 16:36:42 -0800433}
434
435status_t AudioAnalytics::submit(
Ray Essickf27e9872019-12-07 06:28:46 -0800436 const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted)
Andy Hung06f3aba2019-12-03 16:36:42 -0800437{
Andy Hungea186fa2020-01-09 18:13:15 -0800438 if (!startsWith(item->getKey(), AMEDIAMETRICS_KEY_PREFIX_AUDIO)) return BAD_VALUE;
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800439 status_t status = mAnalyticsState->submit(item, isTrusted);
Andy Hung73dc2f92021-12-07 21:50:04 -0800440
441 // Status is selectively authenticated.
442 processStatus(item);
443
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800444 if (status != NO_ERROR) return status; // may not be permitted.
445
446 // Only if the item was successfully submitted (permission)
447 // do we check triggered actions.
Andy Hung73dc2f92021-12-07 21:50:04 -0800448 processActions(item);
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800449 return NO_ERROR;
Andy Hung06f3aba2019-12-03 16:36:42 -0800450}
451
Andy Hung709b91e2020-04-04 14:23:36 -0700452std::pair<std::string, int32_t> AudioAnalytics::dump(
453 int32_t lines, int64_t sinceNs, const char *prefix) const
Andy Hung06f3aba2019-12-03 16:36:42 -0800454{
455 std::stringstream ss;
456 int32_t ll = lines;
457
458 if (ll > 0) {
Andy Hung709b91e2020-04-04 14:23:36 -0700459 auto [s, l] = mAnalyticsState->dump(ll, sinceNs, prefix);
Andy Hungb744faf2020-04-09 13:09:26 -0700460 ss << s;
Andy Hung06f3aba2019-12-03 16:36:42 -0800461 ll -= l;
462 }
463 if (ll > 0) {
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800464 ss << "Prior audioserver state:\n";
Andy Hung06f3aba2019-12-03 16:36:42 -0800465 --ll;
466 }
467 if (ll > 0) {
Andy Hung709b91e2020-04-04 14:23:36 -0700468 auto [s, l] = mPreviousAnalyticsState->dump(ll, sinceNs, prefix);
Andy Hungb744faf2020-04-09 13:09:26 -0700469 ss << s;
Andy Hung06f3aba2019-12-03 16:36:42 -0800470 ll -= l;
471 }
Joey Poomarin52989982020-03-05 17:40:49 +0800472
473 if (ll > 0 && prefix == nullptr) {
474 auto [s, l] = mAudioPowerUsage.dump(ll);
475 ss << s;
476 ll -= l;
477 }
Andy Hunga629bd12020-06-05 16:03:53 -0700478
Andy Hung06f3aba2019-12-03 16:36:42 -0800479 return { ss.str(), lines - ll };
480}
481
Andy Hung73dc2f92021-12-07 21:50:04 -0800482void AudioAnalytics::processActions(const std::shared_ptr<const mediametrics::Item>& item)
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800483{
484 auto actions = mActions.getActionsForItem(item); // internally locked.
485 // Execute actions with no lock held.
486 for (const auto& action : actions) {
487 (*action)(item);
488 }
489}
490
Andy Hung73dc2f92021-12-07 21:50:04 -0800491void AudioAnalytics::processStatus(const std::shared_ptr<const mediametrics::Item>& item)
492{
493 int32_t status;
494 if (!item->get(AMEDIAMETRICS_PROP_STATUS, &status)) return;
495
496 // Any record with a status will automatically be added to a heat map.
497 // Standard information.
498 const auto key = item->getKey();
499 const auto uid = item->getUid();
500
501 // from audio.track.10 -> prefix = audio.track, suffix = 10
502 // from audio.track.error -> prefix = audio.track, suffix = error
503 const auto [prefixKey, suffixKey] = stringutils::splitPrefixKey(key);
504
505 std::string message;
506 item->get(AMEDIAMETRICS_PROP_STATUSMESSAGE, &message); // optional
507
508 int32_t subCode = 0; // not used
509 (void)item->get(AMEDIAMETRICS_PROP_STATUSSUBCODE, &subCode); // optional
510
511 std::string eventStr; // optional
512 item->get(AMEDIAMETRICS_PROP_EVENT, &eventStr);
513
514 const std::string statusString = extendedStatusToStatusString(status);
515
516 // Add to the heat map - we automatically track every item's status to see
517 // the types of errors and the frequency of errors.
518 mHeatMap.add(prefixKey, suffixKey, eventStr, statusString, uid, message, subCode);
519}
520
Andy Hungea186fa2020-01-09 18:13:15 -0800521// HELPER METHODS
522
523std::string AudioAnalytics::getThreadFromTrack(const std::string& track) const
524{
525 int32_t threadId_int32{};
526 if (mAnalyticsState->timeMachine().get(
527 track, AMEDIAMETRICS_PROP_THREADID, &threadId_int32) != NO_ERROR) {
528 return {};
529 }
530 return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(threadId_int32);
531}
532
Andy Hungce9b6632020-04-28 20:15:17 -0700533// DeviceUse helper class.
534void AudioAnalytics::DeviceUse::endAudioIntervalGroup(
Andy Hungea840382020-05-05 21:50:17 -0700535 const std::shared_ptr<const android::mediametrics::Item> &item, ItemType itemType) const {
Andy Hungce9b6632020-04-28 20:15:17 -0700536 const std::string& key = item->getKey();
537 const std::string id = key.substr(
Andy Hungea840382020-05-05 21:50:17 -0700538 (itemType == THREAD ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD)
539 : itemType == TRACK ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
540 : sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD))
Andy Hungce9b6632020-04-28 20:15:17 -0700541 - 1);
542 // deliver statistics
543 int64_t deviceTimeNs = 0;
544 mAudioAnalytics.mAnalyticsState->timeMachine().get(
545 key, AMEDIAMETRICS_PROP_DEVICETIMENS, &deviceTimeNs);
546 std::string encoding;
547 mAudioAnalytics.mAnalyticsState->timeMachine().get(
548 key, AMEDIAMETRICS_PROP_ENCODING, &encoding);
549 int32_t frameCount = 0;
550 mAudioAnalytics.mAnalyticsState->timeMachine().get(
551 key, AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount);
Andy Hung1ea842e2020-05-18 10:47:31 -0700552 std::string inputDevicePairs;
Andy Hungea840382020-05-05 21:50:17 -0700553 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hung1ea842e2020-05-18 10:47:31 -0700554 key, AMEDIAMETRICS_PROP_INPUTDEVICES, &inputDevicePairs);
Andy Hungce9b6632020-04-28 20:15:17 -0700555 int32_t intervalCount = 0;
556 mAudioAnalytics.mAnalyticsState->timeMachine().get(
557 key, AMEDIAMETRICS_PROP_INTERVALCOUNT, &intervalCount);
Andy Hung1ea842e2020-05-18 10:47:31 -0700558 std::string outputDevicePairs;
Andy Hungce9b6632020-04-28 20:15:17 -0700559 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hung1ea842e2020-05-18 10:47:31 -0700560 key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevicePairs);
Andy Hungce9b6632020-04-28 20:15:17 -0700561 int32_t sampleRate = 0;
562 mAudioAnalytics.mAnalyticsState->timeMachine().get(
563 key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
Andy Hungea840382020-05-05 21:50:17 -0700564 std::string flags;
Andy Hungce9b6632020-04-28 20:15:17 -0700565 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hungea840382020-05-05 21:50:17 -0700566 key, AMEDIAMETRICS_PROP_FLAGS, &flags);
Andy Hung1ea842e2020-05-18 10:47:31 -0700567
Andy Hungea840382020-05-05 21:50:17 -0700568 // We may have several devices.
Andy Hung1ea842e2020-05-18 10:47:31 -0700569 // Accumulate the bit flags for input and output devices.
570 std::stringstream oss;
571 long_enum_type_t outputDeviceBits{};
572 { // compute outputDevices
573 const auto devaddrvec = stringutils::getDeviceAddressPairs(outputDevicePairs);
Andy Hungea840382020-05-05 21:50:17 -0700574 for (const auto& [device, addr] : devaddrvec) {
Andy Hung1ea842e2020-05-18 10:47:31 -0700575 if (oss.tellp() > 0) oss << "|"; // delimit devices with '|'.
576 oss << device;
577 outputDeviceBits += types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(device);
Andy Hungea840382020-05-05 21:50:17 -0700578 }
579 }
Andy Hung1ea842e2020-05-18 10:47:31 -0700580 const std::string outputDevices = oss.str();
581
582 std::stringstream iss;
583 long_enum_type_t inputDeviceBits{};
584 { // compute inputDevices
585 const auto devaddrvec = stringutils::getDeviceAddressPairs(inputDevicePairs);
586 for (const auto& [device, addr] : devaddrvec) {
587 if (iss.tellp() > 0) iss << "|"; // delimit devices with '|'.
588 iss << device;
589 inputDeviceBits += types::lookup<types::INPUT_DEVICE, long_enum_type_t>(device);
590 }
591 }
592 const std::string inputDevices = iss.str();
Andy Hungce9b6632020-04-28 20:15:17 -0700593
594 // Get connected device name if from bluetooth.
595 bool isBluetooth = false;
Andy Hunga629bd12020-06-05 16:03:53 -0700596
597 std::string inputDeviceNames; // not filled currently.
598 std::string outputDeviceNames;
Andy Hungce9b6632020-04-28 20:15:17 -0700599 if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos) {
600 isBluetooth = true;
Andy Hung3deef2b2020-07-17 12:58:54 -0700601 outputDeviceNames = SUPPRESSED;
602#if 0 // TODO(b/161554630) sanitize name
Andy Hungce9b6632020-04-28 20:15:17 -0700603 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hunga629bd12020-06-05 16:03:53 -0700604 "audio.device.bt_a2dp", AMEDIAMETRICS_PROP_NAME, &outputDeviceNames);
Andy Hung1ea842e2020-05-18 10:47:31 -0700605 // Remove | if present
Andy Hunga629bd12020-06-05 16:03:53 -0700606 stringutils::replace(outputDeviceNames, "|", '?');
607 if (outputDeviceNames.size() > STATSD_DEVICE_NAME_MAX_LENGTH) {
608 outputDeviceNames.resize(STATSD_DEVICE_NAME_MAX_LENGTH); // truncate
609 }
Andy Hung3deef2b2020-07-17 12:58:54 -0700610#endif
Andy Hungce9b6632020-04-28 20:15:17 -0700611 }
612
Andy Hungea840382020-05-05 21:50:17 -0700613 switch (itemType) {
614 case RECORD: {
615 std::string callerName;
Andy Hunga629bd12020-06-05 16:03:53 -0700616 const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
617 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
Andy Hungce9b6632020-04-28 20:15:17 -0700618
Andy Hungea840382020-05-05 21:50:17 -0700619 std::string packageName;
620 int64_t versionCode = 0;
621 int32_t uid = -1;
622 mAudioAnalytics.mAnalyticsState->timeMachine().get(
623 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
624 if (uid != -1) {
625 std::tie(packageName, versionCode) =
626 MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
627 }
628
629 int32_t selectedDeviceId = 0;
630 mAudioAnalytics.mAnalyticsState->timeMachine().get(
631 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
632 std::string source;
633 mAudioAnalytics.mAnalyticsState->timeMachine().get(
634 key, AMEDIAMETRICS_PROP_SOURCE, &source);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800635 // Android S
636 std::string logSessionId;
637 mAudioAnalytics.mAnalyticsState->timeMachine().get(
638 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
Andy Hungea840382020-05-05 21:50:17 -0700639
Andy Hung1ea842e2020-05-18 10:47:31 -0700640 const auto callerNameForStats =
641 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
642 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
643 const auto flagsForStats = types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags);
644 const auto sourceForStats = types::lookup<types::SOURCE_TYPE, short_enum_type_t>(source);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800645 // Android S
Andy Hungc9b6f8b2021-07-08 10:17:55 -0700646 const auto logSessionIdForStats = ValidateId::get()->validateId(logSessionId);
Andy Hungea840382020-05-05 21:50:17 -0700647
Andy Hunga629bd12020-06-05 16:03:53 -0700648 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700649 << " id:" << id
650 << " inputDevices:" << inputDevices << "(" << inputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700651 << ") inputDeviceNames:" << inputDeviceNames
Andy Hung1ea842e2020-05-18 10:47:31 -0700652 << " deviceTimeNs:" << deviceTimeNs
653 << " encoding:" << encoding << "(" << encodingForStats
654 << ") frameCount:" << frameCount
655 << " intervalCount:" << intervalCount
656 << " sampleRate:" << sampleRate
657 << " flags:" << flags << "(" << flagsForStats
658 << ") packageName:" << packageName
659 << " selectedDeviceId:" << selectedDeviceId
660 << " callerName:" << callerName << "(" << callerNameForStats
Andy Hungcbcfaa22021-02-23 13:54:49 -0800661 << ") source:" << source << "(" << sourceForStats
662 << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats
663 << ")";
Andy Hunga629bd12020-06-05 16:03:53 -0700664 if (clientCalled // only log if client app called AudioRecord.
665 && mAudioAnalytics.mDeliverStatistics) {
666 const auto [ result, str ] = sendToStatsd(AudioRecordDeviceUsageFields,
667 CONDITION(android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700668 , ENUM_EXTRACT(inputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700669 , inputDeviceNames.c_str()
Andy Hungea840382020-05-05 21:50:17 -0700670 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700671 , ENUM_EXTRACT(encodingForStats)
Andy Hungea840382020-05-05 21:50:17 -0700672 , frameCount
673 , intervalCount
674 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700675 , ENUM_EXTRACT(flagsForStats)
Andy Hungea840382020-05-05 21:50:17 -0700676
677 , packageName.c_str()
678 , selectedDeviceId
Andy Hung1ea842e2020-05-18 10:47:31 -0700679 , ENUM_EXTRACT(callerNameForStats)
680 , ENUM_EXTRACT(sourceForStats)
Andy Hungcbcfaa22021-02-23 13:54:49 -0800681 , logSessionIdForStats.c_str()
Andy Hungea840382020-05-05 21:50:17 -0700682 );
Andy Hunga629bd12020-06-05 16:03:53 -0700683 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700684 mAudioAnalytics.mStatsdLog->log(
685 android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -0700686 }
Andy Hungea840382020-05-05 21:50:17 -0700687 } break;
688 case THREAD: {
689 std::string type;
690 mAudioAnalytics.mAnalyticsState->timeMachine().get(
691 key, AMEDIAMETRICS_PROP_TYPE, &type);
692 int32_t underrun = 0; // zero for record types
693 mAudioAnalytics.mAnalyticsState->timeMachine().get(
694 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
Andy Hung1ea842e2020-05-18 10:47:31 -0700695
696 const bool isInput = types::isInputThreadType(type);
697 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
698 const auto flagsForStats =
699 (isInput ? types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags)
700 : types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags));
701 const auto typeForStats = types::lookup<types::THREAD_TYPE, short_enum_type_t>(type);
702
Andy Hunga629bd12020-06-05 16:03:53 -0700703 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700704 << " id:" << id
705 << " inputDevices:" << inputDevices << "(" << inputDeviceBits
706 << ") outputDevices:" << outputDevices << "(" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700707 << ") inputDeviceNames:" << inputDeviceNames
708 << " outputDeviceNames:" << outputDeviceNames
Andy Hung1ea842e2020-05-18 10:47:31 -0700709 << " deviceTimeNs:" << deviceTimeNs
710 << " encoding:" << encoding << "(" << encodingForStats
711 << ") frameCount:" << frameCount
712 << " intervalCount:" << intervalCount
713 << " sampleRate:" << sampleRate
714 << " underrun:" << underrun
715 << " flags:" << flags << "(" << flagsForStats
716 << ") type:" << type << "(" << typeForStats
717 << ")";
Andy Hungea840382020-05-05 21:50:17 -0700718 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -0700719 const auto [ result, str ] = sendToStatsd(AudioThreadDeviceUsageFields,
720 CONDITION(android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
721 , isInput ? ENUM_EXTRACT(inputDeviceBits) : ENUM_EXTRACT(outputDeviceBits)
722 , isInput ? inputDeviceNames.c_str() : outputDeviceNames.c_str()
Andy Hungea840382020-05-05 21:50:17 -0700723 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700724 , ENUM_EXTRACT(encodingForStats)
Andy Hungea840382020-05-05 21:50:17 -0700725 , frameCount
726 , intervalCount
727 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700728 , ENUM_EXTRACT(flagsForStats)
Andy Hungea840382020-05-05 21:50:17 -0700729 , underrun
Andy Hung1ea842e2020-05-18 10:47:31 -0700730 , ENUM_EXTRACT(typeForStats)
Andy Hungea840382020-05-05 21:50:17 -0700731 );
Andy Hunga629bd12020-06-05 16:03:53 -0700732 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700733 mAudioAnalytics.mStatsdLog->log(
734 android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -0700735 }
Andy Hungea840382020-05-05 21:50:17 -0700736 } break;
737 case TRACK: {
Andy Hungce9b6632020-04-28 20:15:17 -0700738 std::string callerName;
Andy Hunga629bd12020-06-05 16:03:53 -0700739 const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
740 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
741
Andy Hungce9b6632020-04-28 20:15:17 -0700742 std::string contentType;
743 mAudioAnalytics.mAnalyticsState->timeMachine().get(
744 key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentType);
745 double deviceLatencyMs = 0.;
746 mAudioAnalytics.mAnalyticsState->timeMachine().get(
747 key, AMEDIAMETRICS_PROP_DEVICELATENCYMS, &deviceLatencyMs);
748 double deviceStartupMs = 0.;
749 mAudioAnalytics.mAnalyticsState->timeMachine().get(
750 key, AMEDIAMETRICS_PROP_DEVICESTARTUPMS, &deviceStartupMs);
751 double deviceVolume = 0.;
752 mAudioAnalytics.mAnalyticsState->timeMachine().get(
753 key, AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume);
754 std::string packageName;
755 int64_t versionCode = 0;
756 int32_t uid = -1;
757 mAudioAnalytics.mAnalyticsState->timeMachine().get(
758 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
759 if (uid != -1) {
760 std::tie(packageName, versionCode) =
761 MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
762 }
763 double playbackPitch = 0.;
764 mAudioAnalytics.mAnalyticsState->timeMachine().get(
765 key, AMEDIAMETRICS_PROP_PLAYBACK_PITCH, &playbackPitch);
766 double playbackSpeed = 0.;
767 mAudioAnalytics.mAnalyticsState->timeMachine().get(
768 key, AMEDIAMETRICS_PROP_PLAYBACK_SPEED, &playbackSpeed);
769 int32_t selectedDeviceId = 0;
770 mAudioAnalytics.mAnalyticsState->timeMachine().get(
771 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
Andy Hungea840382020-05-05 21:50:17 -0700772 std::string streamType;
773 mAudioAnalytics.mAnalyticsState->timeMachine().get(
774 key, AMEDIAMETRICS_PROP_STREAMTYPE, &streamType);
Andy Hunga629bd12020-06-05 16:03:53 -0700775 std::string traits;
776 mAudioAnalytics.mAnalyticsState->timeMachine().get(
777 key, AMEDIAMETRICS_PROP_TRAITS, &traits);
Andy Hungea840382020-05-05 21:50:17 -0700778 int32_t underrun = 0;
779 mAudioAnalytics.mAnalyticsState->timeMachine().get(
780 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
Andy Hungce9b6632020-04-28 20:15:17 -0700781 std::string usage;
782 mAudioAnalytics.mAnalyticsState->timeMachine().get(
783 key, AMEDIAMETRICS_PROP_USAGE, &usage);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800784 // Android S
785 std::string logSessionId;
786 mAudioAnalytics.mAnalyticsState->timeMachine().get(
787 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
Andy Hungce9b6632020-04-28 20:15:17 -0700788
Andy Hung1ea842e2020-05-18 10:47:31 -0700789 const auto callerNameForStats =
790 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
791 const auto contentTypeForStats =
792 types::lookup<types::CONTENT_TYPE, short_enum_type_t>(contentType);
793 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
794 const auto flagsForStats = types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags);
795 const auto streamTypeForStats =
796 types::lookup<types::STREAM_TYPE, short_enum_type_t>(streamType);
Andy Hunga629bd12020-06-05 16:03:53 -0700797 const auto traitsForStats =
798 types::lookup<types::TRACK_TRAITS, short_enum_type_t>(traits);
Andy Hung1ea842e2020-05-18 10:47:31 -0700799 const auto usageForStats = types::lookup<types::USAGE, short_enum_type_t>(usage);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800800 // Android S
Andy Hungc9b6f8b2021-07-08 10:17:55 -0700801 const auto logSessionIdForStats = ValidateId::get()->validateId(logSessionId);
Andy Hung1ea842e2020-05-18 10:47:31 -0700802
Andy Hunga629bd12020-06-05 16:03:53 -0700803 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700804 << " id:" << id
805 << " outputDevices:" << outputDevices << "(" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700806 << ") 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 << ") callerName:" << callerName << "(" << callerNameForStats
815 << ") contentType:" << contentType << "(" << contentTypeForStats
816 << ") deviceLatencyMs:" << deviceLatencyMs
817 << " deviceStartupMs:" << deviceStartupMs
818 << " deviceVolume:" << deviceVolume
819 << " packageName:" << packageName
820 << " playbackPitch:" << playbackPitch
821 << " playbackSpeed:" << playbackSpeed
822 << " selectedDeviceId:" << selectedDeviceId
823 << " streamType:" << streamType << "(" << streamTypeForStats
Andy Hunga629bd12020-06-05 16:03:53 -0700824 << ") traits:" << traits << "(" << traitsForStats
Andy Hung1ea842e2020-05-18 10:47:31 -0700825 << ") usage:" << usage << "(" << usageForStats
Andy Hungcbcfaa22021-02-23 13:54:49 -0800826 << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats
Andy Hung1ea842e2020-05-18 10:47:31 -0700827 << ")";
Andy Hunga629bd12020-06-05 16:03:53 -0700828 if (clientCalled // only log if client app called AudioTracks
829 && mAudioAnalytics.mDeliverStatistics) {
830 const auto [ result, str ] = sendToStatsd(AudioTrackDeviceUsageFields,
831 CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700832 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700833 , outputDeviceNames.c_str()
Andy Hungce9b6632020-04-28 20:15:17 -0700834 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700835 , ENUM_EXTRACT(encodingForStats)
Andy Hungce9b6632020-04-28 20:15:17 -0700836 , frameCount
837 , intervalCount
838 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700839 , ENUM_EXTRACT(flagsForStats)
Andy Hungce9b6632020-04-28 20:15:17 -0700840 , underrun
Andy Hungce9b6632020-04-28 20:15:17 -0700841 , packageName.c_str()
842 , (float)deviceLatencyMs
843 , (float)deviceStartupMs
844 , (float)deviceVolume
845 , selectedDeviceId
Andy Hung1ea842e2020-05-18 10:47:31 -0700846 , ENUM_EXTRACT(streamTypeForStats)
847 , ENUM_EXTRACT(usageForStats)
848 , ENUM_EXTRACT(contentTypeForStats)
849 , ENUM_EXTRACT(callerNameForStats)
Andy Hunga629bd12020-06-05 16:03:53 -0700850 , ENUM_EXTRACT(traitsForStats)
Andy Hungcbcfaa22021-02-23 13:54:49 -0800851 , logSessionIdForStats.c_str()
Andy Hungce9b6632020-04-28 20:15:17 -0700852 );
Andy Hunga629bd12020-06-05 16:03:53 -0700853 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700854 mAudioAnalytics.mStatsdLog->log(
855 android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED, str);
Andy Hungce9b6632020-04-28 20:15:17 -0700856 }
Andy Hungea840382020-05-05 21:50:17 -0700857 } break;
Andy Hungce9b6632020-04-28 20:15:17 -0700858 }
859
860 // Report this as needed.
861 if (isBluetooth) {
862 // report this for Bluetooth
863 }
864}
865
866// DeviceConnection helper class.
867void AudioAnalytics::DeviceConnection::a2dpConnected(
868 const std::shared_ptr<const android::mediametrics::Item> &item) {
869 const std::string& key = item->getKey();
Andy Hungea840382020-05-05 21:50:17 -0700870 const int64_t atNs = item->getTimestamp();
Andy Hungce9b6632020-04-28 20:15:17 -0700871 {
872 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -0700873 mA2dpConnectionServiceNs = atNs;
874 ++mA2dpConnectionServices;
875
876 if (mA2dpConnectionRequestNs == 0) {
877 mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
878 }
879 // This sets the time we were connected. Now we look for the delta in the future.
Andy Hungce9b6632020-04-28 20:15:17 -0700880 }
881 std::string name;
882 item->get(AMEDIAMETRICS_PROP_NAME, &name);
Andy Hungea840382020-05-05 21:50:17 -0700883 ALOGD("(key=%s) a2dp connected device:%s atNs:%lld",
884 key.c_str(), name.c_str(), (long long)atNs);
Andy Hungce9b6632020-04-28 20:15:17 -0700885}
886
887void AudioAnalytics::DeviceConnection::createPatch(
888 const std::shared_ptr<const android::mediametrics::Item> &item) {
889 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -0700890 if (mA2dpConnectionServiceNs == 0) return; // patch unrelated to us.
Andy Hungce9b6632020-04-28 20:15:17 -0700891 const std::string& key = item->getKey();
892 std::string outputDevices;
893 item->get(AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices);
Andy Hungea840382020-05-05 21:50:17 -0700894 if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH_A2DP") != std::string::npos) {
Andy Hungce9b6632020-04-28 20:15:17 -0700895 // TODO compare address
Andy Hung1ea842e2020-05-18 10:47:31 -0700896 int64_t timeDiffNs = item->getTimestamp();
Andy Hungea840382020-05-05 21:50:17 -0700897 if (mA2dpConnectionRequestNs == 0) {
898 ALOGD("%s: A2DP create patch didn't see a connection request", __func__);
Andy Hung1ea842e2020-05-18 10:47:31 -0700899 timeDiffNs -= mA2dpConnectionServiceNs;
Andy Hungea840382020-05-05 21:50:17 -0700900 } else {
Andy Hung1ea842e2020-05-18 10:47:31 -0700901 timeDiffNs -= mA2dpConnectionRequestNs;
Andy Hungea840382020-05-05 21:50:17 -0700902 }
Andy Hung1ea842e2020-05-18 10:47:31 -0700903
Andy Hungea840382020-05-05 21:50:17 -0700904 mA2dpConnectionRequestNs = 0;
905 mA2dpConnectionServiceNs = 0;
906 ++mA2dpConnectionSuccesses;
907
Andy Hungc14ee142021-03-10 16:39:02 -0800908 const auto connectionTimeMs = float((double)timeDiffNs * 1e-6);
Andy Hung1ea842e2020-05-18 10:47:31 -0700909
910 const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
911 "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
912
Andy Hunga629bd12020-06-05 16:03:53 -0700913 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700914 << " A2DP SUCCESS"
915 << " outputDevices:" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700916 << " deviceName:" << mA2dpDeviceName
Andy Hung1ea842e2020-05-18 10:47:31 -0700917 << " connectionTimeMs:" << connectionTimeMs;
Andy Hungea840382020-05-05 21:50:17 -0700918 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hung1ea842e2020-05-18 10:47:31 -0700919 const long_enum_type_t inputDeviceBits{};
Andy Hunga629bd12020-06-05 16:03:53 -0700920
921 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
922 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700923 , ENUM_EXTRACT(inputDeviceBits)
924 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700925 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -0700926 , types::DEVICE_CONNECTION_RESULT_SUCCESS
927 , connectionTimeMs
Andy Hungea840382020-05-05 21:50:17 -0700928 , /* connection_count */ 1
929 );
Andy Hunga629bd12020-06-05 16:03:53 -0700930 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700931 mAudioAnalytics.mStatsdLog->log(
932 android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -0700933 }
Andy Hungce9b6632020-04-28 20:15:17 -0700934 }
935}
936
Andy Hungea840382020-05-05 21:50:17 -0700937// Called through AudioManager when the BT service wants to enable
938void AudioAnalytics::DeviceConnection::postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
939 const std::shared_ptr<const android::mediametrics::Item> &item) {
940 const int64_t atNs = item->getTimestamp();
941 const std::string& key = item->getKey();
942 std::string state;
943 item->get(AMEDIAMETRICS_PROP_STATE, &state);
944 if (state != "connected") return;
Andy Hunga629bd12020-06-05 16:03:53 -0700945
946 std::string name;
947 item->get(AMEDIAMETRICS_PROP_NAME, &name);
Andy Hungea840382020-05-05 21:50:17 -0700948 {
949 std::lock_guard l(mLock);
950 mA2dpConnectionRequestNs = atNs;
951 ++mA2dpConnectionRequests;
Andy Hung3deef2b2020-07-17 12:58:54 -0700952 mA2dpDeviceName = SUPPRESSED; // TODO(b/161554630) sanitize name
Andy Hungea840382020-05-05 21:50:17 -0700953 }
Andy Hunga629bd12020-06-05 16:03:53 -0700954 ALOGD("(key=%s) a2dp connection name:%s request atNs:%lld",
955 key.c_str(), name.c_str(), (long long)atNs);
Andy Hungea840382020-05-05 21:50:17 -0700956 // TODO: attempt to cancel a timed event, rather than let it expire.
957 mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
958}
959
Andy Hungce9b6632020-04-28 20:15:17 -0700960void AudioAnalytics::DeviceConnection::expire() {
961 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -0700962 if (mA2dpConnectionRequestNs == 0) return; // ignore (this was an internal connection).
Andy Hung1ea842e2020-05-18 10:47:31 -0700963
Andy Hung1ea842e2020-05-18 10:47:31 -0700964 const long_enum_type_t inputDeviceBits{};
Andy Hung1ea842e2020-05-18 10:47:31 -0700965 const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
966 "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
967
Andy Hungea840382020-05-05 21:50:17 -0700968 if (mA2dpConnectionServiceNs == 0) {
Andy Hungea840382020-05-05 21:50:17 -0700969 ++mA2dpConnectionJavaServiceCancels; // service did not connect to A2DP
Andy Hungce9b6632020-04-28 20:15:17 -0700970
Andy Hunga629bd12020-06-05 16:03:53 -0700971 LOG(LOG_LEVEL) << "A2DP CANCEL"
972 << " outputDevices:" << outputDeviceBits
973 << " deviceName:" << mA2dpDeviceName;
Andy Hungea840382020-05-05 21:50:17 -0700974 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -0700975 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
976 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700977 , ENUM_EXTRACT(inputDeviceBits)
978 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700979 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -0700980 , types::DEVICE_CONNECTION_RESULT_JAVA_SERVICE_CANCEL
Andy Hungea840382020-05-05 21:50:17 -0700981 , /* connection_time_ms */ 0.f
982 , /* connection_count */ 1
983 );
Andy Hunga629bd12020-06-05 16:03:53 -0700984 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700985 mAudioAnalytics.mStatsdLog->log(
986 android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -0700987 }
Andy Hungea840382020-05-05 21:50:17 -0700988 return;
989 }
990
991 // AudioFlinger didn't play - an expiration may occur because there is no audio playing.
992 // Should we check elsewhere?
Andy Hungce9b6632020-04-28 20:15:17 -0700993 // TODO: disambiguate this case.
Andy Hungea840382020-05-05 21:50:17 -0700994 mA2dpConnectionRequestNs = 0;
995 mA2dpConnectionServiceNs = 0;
996 ++mA2dpConnectionUnknowns; // connection result unknown
Andy Hung1ea842e2020-05-18 10:47:31 -0700997
Andy Hunga629bd12020-06-05 16:03:53 -0700998 LOG(LOG_LEVEL) << "A2DP UNKNOWN"
999 << " outputDevices:" << outputDeviceBits
1000 << " deviceName:" << mA2dpDeviceName;
Andy Hungea840382020-05-05 21:50:17 -07001001 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -07001002 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
1003 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -07001004 , ENUM_EXTRACT(inputDeviceBits)
1005 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -07001006 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -07001007 , types::DEVICE_CONNECTION_RESULT_UNKNOWN
Andy Hungea840382020-05-05 21:50:17 -07001008 , /* connection_time_ms */ 0.f
1009 , /* connection_count */ 1
1010 );
Andy Hunga629bd12020-06-05 16:03:53 -07001011 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -07001012 mAudioAnalytics.mStatsdLog->log(
1013 android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -07001014 }
Andy Hungce9b6632020-04-28 20:15:17 -07001015}
1016
jiabin515eb092020-11-18 17:55:52 -08001017void AudioAnalytics::AAudioStreamInfo::endAAudioStream(
1018 const std::shared_ptr<const android::mediametrics::Item> &item, CallerPath path) const {
1019 const std::string& key = item->getKey();
1020
jiabin515eb092020-11-18 17:55:52 -08001021 std::string directionStr;
1022 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1023 key, AMEDIAMETRICS_PROP_DIRECTION, &directionStr);
1024 const auto direction = types::lookup<types::AAUDIO_DIRECTION, int32_t>(directionStr);
1025
1026 int32_t framesPerBurst = -1;
1027 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1028 key, AMEDIAMETRICS_PROP_BURSTFRAMES, &framesPerBurst);
1029
1030 int32_t bufferSizeInFrames = -1;
1031 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1032 key, AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, &bufferSizeInFrames);
1033
1034 int32_t bufferCapacityInFrames = -1;
1035 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1036 key, AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, &bufferCapacityInFrames);
1037
1038 int32_t channelCount = -1;
1039 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1040 key, AMEDIAMETRICS_PROP_CHANNELCOUNT, &channelCount);
jiabinfbf20302021-07-28 22:15:01 +00001041 if (channelCount == -1) {
1042 // Try to get channel count from channel mask. From the legacy path,
1043 // only channel mask are logged.
1044 int32_t channelMask = 0;
1045 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1046 key, AMEDIAMETRICS_PROP_CHANNELMASK, &channelMask);
1047 if (channelMask != 0) {
1048 switch (direction) {
1049 case 1: // Output, keep sync with AudioTypes#getAAudioDirection()
1050 channelCount = audio_channel_count_from_out_mask(channelMask);
1051 break;
1052 case 2: // Input, keep sync with AudioTypes#getAAudioDirection()
1053 channelCount = audio_channel_count_from_in_mask(channelMask);
1054 break;
1055 default:
1056 ALOGW("Invalid direction %d", direction);
1057 }
1058 }
1059 }
jiabin515eb092020-11-18 17:55:52 -08001060
1061 int64_t totalFramesTransferred = -1;
jiabin97247ea2021-04-07 00:33:38 +00001062 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1063 key, AMEDIAMETRICS_PROP_FRAMESTRANSFERRED, &totalFramesTransferred);
jiabin515eb092020-11-18 17:55:52 -08001064
1065 std::string perfModeRequestedStr;
1066 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1067 key, AMEDIAMETRICS_PROP_PERFORMANCEMODE, &perfModeRequestedStr);
1068 const auto perfModeRequested =
1069 types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeRequestedStr);
1070
jiabin97247ea2021-04-07 00:33:38 +00001071 std::string perfModeActualStr;
1072 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1073 key, AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL, &perfModeActualStr);
1074 const auto perfModeActual =
1075 types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeActualStr);
jiabin515eb092020-11-18 17:55:52 -08001076
jiabinc8da9032021-04-28 20:42:36 +00001077 std::string sharingModeActualStr;
jiabin515eb092020-11-18 17:55:52 -08001078 mAudioAnalytics.mAnalyticsState->timeMachine().get(
jiabinc8da9032021-04-28 20:42:36 +00001079 key, AMEDIAMETRICS_PROP_SHARINGMODEACTUAL, &sharingModeActualStr);
1080 const auto sharingModeActual =
1081 types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeActualStr);
jiabin515eb092020-11-18 17:55:52 -08001082
1083 int32_t xrunCount = -1;
1084 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1085 key, AMEDIAMETRICS_PROP_UNDERRUN, &xrunCount);
1086
jiabin92c9a522021-02-12 22:37:42 +00001087 std::string serializedDeviceTypes;
jiabin515eb092020-11-18 17:55:52 -08001088 // TODO: only routed device id is logged, but no device type
1089
jiabin97247ea2021-04-07 00:33:38 +00001090 std::string formatAppStr;
1091 mAudioAnalytics.mAnalyticsState->timeMachine().get(
jiabinef348b82021-04-19 16:53:08 +00001092 key, AMEDIAMETRICS_PROP_ENCODINGCLIENT, &formatAppStr);
jiabin97247ea2021-04-07 00:33:38 +00001093 const auto formatApp = types::lookup<types::ENCODING, int32_t>(formatAppStr);
jiabin515eb092020-11-18 17:55:52 -08001094
1095 std::string formatDeviceStr;
1096 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1097 key, AMEDIAMETRICS_PROP_ENCODING, &formatDeviceStr);
1098 const auto formatDevice = types::lookup<types::ENCODING, int32_t>(formatDeviceStr);
1099
jiabin92c9a522021-02-12 22:37:42 +00001100 std::string logSessionId;
jiabin97247ea2021-04-07 00:33:38 +00001101 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1102 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
jiabin92c9a522021-02-12 22:37:42 +00001103
jiabinc4c331c2021-03-23 17:11:01 +00001104 int32_t sampleRate = 0;
1105 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1106 key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
1107
1108 std::string contentTypeStr;
1109 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1110 key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentTypeStr);
1111 const auto contentType = types::lookup<types::CONTENT_TYPE, int32_t>(contentTypeStr);
1112
jiabinc8da9032021-04-28 20:42:36 +00001113 std::string sharingModeRequestedStr;
1114 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1115 key, AMEDIAMETRICS_PROP_SHARINGMODE, &sharingModeRequestedStr);
1116 const auto sharingModeRequested =
1117 types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeRequestedStr);
1118
jiabin515eb092020-11-18 17:55:52 -08001119 LOG(LOG_LEVEL) << "key:" << key
jiabin515eb092020-11-18 17:55:52 -08001120 << " path:" << path
1121 << " direction:" << direction << "(" << directionStr << ")"
1122 << " frames_per_burst:" << framesPerBurst
1123 << " buffer_size:" << bufferSizeInFrames
1124 << " buffer_capacity:" << bufferCapacityInFrames
1125 << " channel_count:" << channelCount
1126 << " total_frames_transferred:" << totalFramesTransferred
1127 << " perf_mode_requested:" << perfModeRequested << "(" << perfModeRequestedStr << ")"
jiabin97247ea2021-04-07 00:33:38 +00001128 << " perf_mode_actual:" << perfModeActual << "(" << perfModeActualStr << ")"
jiabinc8da9032021-04-28 20:42:36 +00001129 << " sharing:" << sharingModeActual << "(" << sharingModeActualStr << ")"
jiabin515eb092020-11-18 17:55:52 -08001130 << " xrun_count:" << xrunCount
jiabin92c9a522021-02-12 22:37:42 +00001131 << " device_type:" << serializedDeviceTypes
jiabin97247ea2021-04-07 00:33:38 +00001132 << " format_app:" << formatApp << "(" << formatAppStr << ")"
jiabin92c9a522021-02-12 22:37:42 +00001133 << " format_device: " << formatDevice << "(" << formatDeviceStr << ")"
jiabinc4c331c2021-03-23 17:11:01 +00001134 << " log_session_id: " << logSessionId
1135 << " sample_rate: " << sampleRate
jiabinc8da9032021-04-28 20:42:36 +00001136 << " content_type: " << contentType << "(" << contentTypeStr << ")"
1137 << " sharing_requested:" << sharingModeRequested
1138 << "(" << sharingModeRequestedStr << ")";
jiabin515eb092020-11-18 17:55:52 -08001139
jiabin92c9a522021-02-12 22:37:42 +00001140 if (mAudioAnalytics.mDeliverStatistics) {
1141 android::util::BytesField bf_serialized(
1142 serializedDeviceTypes.c_str(), serializedDeviceTypes.size());
1143 const auto result = sendToStatsd(
1144 CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
jiabin92c9a522021-02-12 22:37:42 +00001145 , path
1146 , direction
1147 , framesPerBurst
1148 , bufferSizeInFrames
1149 , bufferCapacityInFrames
1150 , channelCount
1151 , totalFramesTransferred
1152 , perfModeRequested
1153 , perfModeActual
jiabinc8da9032021-04-28 20:42:36 +00001154 , sharingModeActual
jiabin92c9a522021-02-12 22:37:42 +00001155 , xrunCount
1156 , bf_serialized
1157 , formatApp
1158 , formatDevice
1159 , logSessionId.c_str()
jiabinc4c331c2021-03-23 17:11:01 +00001160 , sampleRate
1161 , contentType
jiabinc8da9032021-04-28 20:42:36 +00001162 , sharingModeRequested
jiabin92c9a522021-02-12 22:37:42 +00001163 );
1164 std::stringstream ss;
1165 ss << "result:" << result;
1166 const auto fieldsStr = printFields(AAudioStreamFields,
1167 CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
jiabin92c9a522021-02-12 22:37:42 +00001168 , path
1169 , direction
1170 , framesPerBurst
1171 , bufferSizeInFrames
1172 , bufferCapacityInFrames
1173 , channelCount
1174 , totalFramesTransferred
1175 , perfModeRequested
1176 , perfModeActual
jiabinc8da9032021-04-28 20:42:36 +00001177 , sharingModeActual
jiabin92c9a522021-02-12 22:37:42 +00001178 , xrunCount
1179 , serializedDeviceTypes.c_str()
1180 , formatApp
1181 , formatDevice
1182 , logSessionId.c_str()
jiabinc4c331c2021-03-23 17:11:01 +00001183 , sampleRate
1184 , contentType
jiabinc8da9032021-04-28 20:42:36 +00001185 , sharingModeRequested
jiabin92c9a522021-02-12 22:37:42 +00001186 );
1187 ss << " " << fieldsStr;
1188 std::string str = ss.str();
1189 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -07001190 mAudioAnalytics.mStatsdLog->log(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED, str);
jiabin92c9a522021-02-12 22:37:42 +00001191 }
jiabin515eb092020-11-18 17:55:52 -08001192}
1193
Andy Hung3ab1b322020-05-18 10:47:31 -07001194} // namespace android::mediametrics