blob: 21768f842ec97b7fff0b6f05699e17093d6a287d [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 Hungb64ea8e2021-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 Hungb64ea8e2021-12-07 21:50:04 -080068// The status variable contains status_t codes which are used by
69// the core audio framework.
70//
71// We also consider AAudio status codes as they are non-overlapping with status_t
72// and compiler checked here.
73//
74// Caution: As AAUDIO_ERROR codes have a unique range (AAUDIO_ERROR_BASE = -900),
75// overlap with status_t should not present an issue.
76//
77// See: system/core/libutils/include/utils/Errors.h
78// frameworks/av/media/libaaudio/include/aaudio/AAudio.h
79//
80// Compare with mediametrics::statusToStatusString
81//
82inline constexpr const char* extendedStatusToStatusString(status_t status) {
83 switch (status) {
84 case BAD_VALUE: // status_t
85 case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
86 case AAUDIO_ERROR_INVALID_FORMAT:
87 case AAUDIO_ERROR_INVALID_RATE:
88 case AAUDIO_ERROR_NULL:
89 case AAUDIO_ERROR_OUT_OF_RANGE:
90 return AMEDIAMETRICS_PROP_STATUS_VALUE_ARGUMENT;
91 case DEAD_OBJECT: // status_t
92 case FAILED_TRANSACTION: // status_t
93 case AAUDIO_ERROR_DISCONNECTED:
94 case AAUDIO_ERROR_INVALID_HANDLE:
95 case AAUDIO_ERROR_NO_SERVICE:
96 return AMEDIAMETRICS_PROP_STATUS_VALUE_IO;
97 case NO_MEMORY: // status_t
98 case AAUDIO_ERROR_NO_FREE_HANDLES:
99 case AAUDIO_ERROR_NO_MEMORY:
100 return AMEDIAMETRICS_PROP_STATUS_VALUE_MEMORY;
101 case PERMISSION_DENIED: // status_t
102 return AMEDIAMETRICS_PROP_STATUS_VALUE_SECURITY;
103 case INVALID_OPERATION: // status_t
104 case NO_INIT: // status_t
105 case AAUDIO_ERROR_INVALID_STATE:
106 case AAUDIO_ERROR_UNAVAILABLE:
107 case AAUDIO_ERROR_UNIMPLEMENTED:
108 return AMEDIAMETRICS_PROP_STATUS_VALUE_STATE;
109 case WOULD_BLOCK: // status_t
110 case AAUDIO_ERROR_TIMEOUT:
111 case AAUDIO_ERROR_WOULD_BLOCK:
112 return AMEDIAMETRICS_PROP_STATUS_VALUE_TIMEOUT;
113 default:
114 if (status >= 0) return AMEDIAMETRICS_PROP_STATUS_VALUE_OK; // non-negative values "OK"
115 [[fallthrough]]; // negative values are error.
116 case UNKNOWN_ERROR: // status_t
117 return AMEDIAMETRICS_PROP_STATUS_VALUE_UNKNOWN;
118 }
119}
120
Andy Hunga629bd12020-06-05 16:03:53 -0700121static constexpr const auto LOG_LEVEL = android::base::VERBOSE;
122
Andy Hungb18f5062020-06-18 23:10:08 -0700123static constexpr int PREVIOUS_STATE_EXPIRE_SEC = 60 * 60; // 1 hour.
124
Andy Hung3deef2b2020-07-17 12:58:54 -0700125static constexpr const char * SUPPRESSED = "SUPPRESSED";
126
Andy Hunga629bd12020-06-05 16:03:53 -0700127/*
128 * For logging purposes, we list all of the MediaMetrics atom fields,
129 * which can then be associated with consecutive arguments to the statsd write.
130 */
131
132static constexpr const char * const AudioRecordDeviceUsageFields[] = {
133 "mediametrics_audiorecorddeviceusage_reported", // proto number
134 "devices",
135 "device_names",
136 "device_time_nanos",
137 "encoding",
138 "frame_count",
139 "interval_count",
140 "sample_rate",
141 "flags",
142 "package_name",
143 "selected_device_id",
144 "caller",
145 "source",
Andy Hungcbcfaa22021-02-23 13:54:49 -0800146 "log_session_id",
Andy Hunga629bd12020-06-05 16:03:53 -0700147};
148
149static constexpr const char * const AudioThreadDeviceUsageFields[] = {
150 "mediametrics_audiothreaddeviceusage_reported",
151 "devices",
152 "device_names",
153 "device_time_nanos",
154 "encoding",
155 "frame_count",
156 "interval_count",
157 "sample_rate",
158 "flags",
159 "xruns",
160 "type",
161};
162
163static constexpr const char * const AudioTrackDeviceUsageFields[] = {
164 "mediametrics_audiotrackdeviceusage_reported",
165 "devices",
166 "device_names",
167 "device_time_nanos",
168 "encoding",
169 "frame_count",
170 "interval_count",
171 "sample_rate",
172 "flags",
173 "xruns",
174 "package_name",
175 "device_latency_millis",
176 "device_startup_millis",
177 "device_volume",
178 "selected_device_id",
179 "stream_type",
180 "usage",
181 "content_type",
182 "caller",
183 "traits",
Andy Hungcbcfaa22021-02-23 13:54:49 -0800184 "log_session_id",
Andy Hunga629bd12020-06-05 16:03:53 -0700185};
186
187static constexpr const char * const AudioDeviceConnectionFields[] = {
188 "mediametrics_audiodeviceconnection_reported",
189 "input_devices",
190 "output_devices",
191 "device_names",
192 "result",
193 "time_to_connect_millis",
194 "connection_count",
195};
196
jiabin92c9a522021-02-12 22:37:42 +0000197static constexpr const char * const AAudioStreamFields[] {
198 "mediametrics_aaudiostream_reported",
jiabin92c9a522021-02-12 22:37:42 +0000199 "path",
200 "direction",
201 "frames_per_burst",
202 "buffer_size",
203 "buffer_capacity",
204 "channel_count",
205 "total_frames_transferred",
206 "perf_mode_requested",
207 "perf_mode_actual",
208 "sharing",
209 "xrun_count",
210 "device_type",
211 "format_app",
212 "format_device",
213 "log_session_id",
jiabinc4c331c2021-03-23 17:11:01 +0000214 "sample_rate",
215 "content_type",
jiabinc8da9032021-04-28 20:42:36 +0000216 "sharing_requested",
jiabin92c9a522021-02-12 22:37:42 +0000217};
218
219/**
220 * printFields is a helper method that prints the fields and corresponding values
221 * in a human readable style.
222 */
223template <size_t N, typename ...Types>
224std::string printFields(const char * const (& fields)[N], Types ... args)
225{
226 std::stringstream ss;
227 ss << " { ";
228 stringutils::fieldPrint(ss, fields, args...);
229 ss << "}";
230 return ss.str();
231}
232
233/**
234 * sendToStatsd is a helper method that sends the arguments to statsd
235 */
236template <typename ...Types>
237int sendToStatsd(Types ... args)
238{
239 int result = 0;
240
241#ifdef STATSD_ENABLE
242 result = android::util::stats_write(args...);
243#endif
244 return result;
245}
jiabin515eb092020-11-18 17:55:52 -0800246
Andy Hunga629bd12020-06-05 16:03:53 -0700247/**
248 * sendToStatsd is a helper method that sends the arguments to statsd
249 * and returns a pair { result, summary_string }.
250 */
251template <size_t N, typename ...Types>
252std::pair<int, std::string> sendToStatsd(const char * const (& fields)[N], Types ... args)
253{
254 int result = 0;
255 std::stringstream ss;
256
257#ifdef STATSD_ENABLE
258 result = android::util::stats_write(args...);
259 ss << "result:" << result;
260#endif
261 ss << " { ";
262 stringutils::fieldPrint(ss, fields, args...);
263 ss << "}";
264 return { result, ss.str() };
265}
Andy Hung06f3aba2019-12-03 16:36:42 -0800266
Andy Hung5be90c82021-03-30 14:30:20 -0700267AudioAnalytics::AudioAnalytics(const std::shared_ptr<StatsdLog>& statsdLog)
Andy Hung1ea842e2020-05-18 10:47:31 -0700268 : mDeliverStatistics(property_get_bool(PROP_AUDIO_ANALYTICS_CLOUD_ENABLED, true))
Andy Hung5be90c82021-03-30 14:30:20 -0700269 , mStatsdLog(statsdLog)
270 , mAudioPowerUsage(this, statsdLog)
Andy Hung06f3aba2019-12-03 16:36:42 -0800271{
Andy Hunga629bd12020-06-05 16:03:53 -0700272 SetMinimumLogSeverity(android::base::DEBUG); // for LOG().
Andy Hung06f3aba2019-12-03 16:36:42 -0800273 ALOGD("%s", __func__);
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800274
275 // Add action to save AnalyticsState if audioserver is restarted.
276 // This triggers on an item of "audio.flinger"
277 // with a property "event" set to "AudioFlinger" (the constructor).
278 mActions.addAction(
Andy Hungea186fa2020-01-09 18:13:15 -0800279 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
280 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR),
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800281 std::make_shared<AnalyticsActions::Function>(
Andy Hungea186fa2020-01-09 18:13:15 -0800282 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
283 ALOGW("(key=%s) Audioflinger constructor event detected", item->getKey().c_str());
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800284 mPreviousAnalyticsState.set(std::make_shared<AnalyticsState>(
285 *mAnalyticsState.get()));
286 // Note: get returns shared_ptr temp, whose lifetime is extended
287 // to end of full expression.
288 mAnalyticsState->clear(); // TODO: filter the analytics state.
Andy Hungea186fa2020-01-09 18:13:15 -0800289 // Perhaps report this.
Andy Hungb18f5062020-06-18 23:10:08 -0700290
291 // Set up a timer to expire the previous audio state to save space.
292 // Use the transaction log size as a cookie to see if it is the
293 // same as before. A benign race is possible where a state is cleared early.
294 const size_t size = mPreviousAnalyticsState->transactionLog().size();
295 mTimedAction.postIn(
296 std::chrono::seconds(PREVIOUS_STATE_EXPIRE_SEC), [this, size](){
297 if (mPreviousAnalyticsState->transactionLog().size() == size) {
298 ALOGD("expiring previous audio state after %d seconds.",
299 PREVIOUS_STATE_EXPIRE_SEC);
300 mPreviousAnalyticsState->clear(); // removes data from the state.
301 }
302 });
Andy Hungea186fa2020-01-09 18:13:15 -0800303 }));
304
jiabin97247ea2021-04-07 00:33:38 +0000305 // Handle legacy aaudio playback stream statistics
jiabin515eb092020-11-18 17:55:52 -0800306 mActions.addAction(
307 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." 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
jiabin97247ea2021-04-07 00:33:38 +0000314 // Handle legacy aaudio capture stream statistics
315 mActions.addAction(
316 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." 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
jiabin515eb092020-11-18 17:55:52 -0800323 // Handle mmap aaudio stream statistics
324 mActions.addAction(
325 AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*." 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_MMAP);
330 }));
331
Andy Hungea840382020-05-05 21:50:17 -0700332 // Handle device use record statistics
Andy Hungea186fa2020-01-09 18:13:15 -0800333 mActions.addAction(
Andy Hungea840382020-05-05 21:50:17 -0700334 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
335 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
Andy Hungea186fa2020-01-09 18:13:15 -0800336 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::RECORD);
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800339 }));
Andy Hungce9b6632020-04-28 20:15:17 -0700340
341 // Handle device use thread statistics
342 mActions.addAction(
343 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." 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::THREAD);
Andy Hungce9b6632020-04-28 20:15:17 -0700348 }));
349
350 // Handle device use track statistics
351 mActions.addAction(
352 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." 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::TRACK);
Andy Hungce9b6632020-04-28 20:15:17 -0700357 }));
358
Andy Hungea840382020-05-05 21:50:17 -0700359
360 // Handle device connection statistics
Andy Hungce9b6632020-04-28 20:15:17 -0700361
362 // We track connections (not disconnections) for the time to connect.
363 // TODO: consider BT requests in their A2dp service
364 // AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
365 // AudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
366 // AudioDeviceBroker.postA2dpActiveDeviceChange
367 mActions.addAction(
368 "audio.device.a2dp.state",
Andy Hungea840382020-05-05 21:50:17 -0700369 "connected",
Andy Hungce9b6632020-04-28 20:15:17 -0700370 std::make_shared<AnalyticsActions::Function>(
371 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
372 mDeviceConnection.a2dpConnected(item);
373 }));
374 // If audio is active, we expect to see a createAudioPatch after the device is connected.
375 mActions.addAction(
376 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
377 std::string("createAudioPatch"),
378 std::make_shared<AnalyticsActions::Function>(
379 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
380 mDeviceConnection.createPatch(item);
381 }));
Joey Poomarin52989982020-03-05 17:40:49 +0800382
Andy Hungea840382020-05-05 21:50:17 -0700383 // Called from BT service
384 mActions.addAction(
385 AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE
386 "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent"
387 "." AMEDIAMETRICS_PROP_STATE,
388 "connected",
389 std::make_shared<AnalyticsActions::Function>(
390 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
391 mDeviceConnection.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(item);
392 }));
393
Joey Poomarin52989982020-03-05 17:40:49 +0800394 // Handle power usage
395 mActions.addAction(
396 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
397 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
398 std::make_shared<AnalyticsActions::Function>(
399 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
400 mAudioPowerUsage.checkTrackRecord(item, true /* isTrack */);
401 }));
402
403 mActions.addAction(
404 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
405 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
406 std::make_shared<AnalyticsActions::Function>(
407 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
408 mAudioPowerUsage.checkTrackRecord(item, false /* isTrack */);
409 }));
410
411 mActions.addAction(
412 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
413 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE),
414 std::make_shared<AnalyticsActions::Function>(
415 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
416 // ALOGD("(key=%s) Audioflinger setMode", item->getKey().c_str());
417 mAudioPowerUsage.checkMode(item);
418 }));
419
420 mActions.addAction(
421 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
422 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME),
423 std::make_shared<AnalyticsActions::Function>(
424 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
425 // ALOGD("(key=%s) Audioflinger setVoiceVolume", item->getKey().c_str());
426 mAudioPowerUsage.checkVoiceVolume(item);
427 }));
428
429 mActions.addAction(
430 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
431 std::string("createAudioPatch"),
432 std::make_shared<AnalyticsActions::Function>(
433 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
434 mAudioPowerUsage.checkCreatePatch(item);
435 }));
Andy Hung06f3aba2019-12-03 16:36:42 -0800436}
437
438AudioAnalytics::~AudioAnalytics()
439{
440 ALOGD("%s", __func__);
Andy Hungce9b6632020-04-28 20:15:17 -0700441 mTimedAction.quit(); // ensure no deferred access during destructor.
Andy Hung06f3aba2019-12-03 16:36:42 -0800442}
443
444status_t AudioAnalytics::submit(
Ray Essickf27e9872019-12-07 06:28:46 -0800445 const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted)
Andy Hung06f3aba2019-12-03 16:36:42 -0800446{
Andy Hungea186fa2020-01-09 18:13:15 -0800447 if (!startsWith(item->getKey(), AMEDIAMETRICS_KEY_PREFIX_AUDIO)) return BAD_VALUE;
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800448 status_t status = mAnalyticsState->submit(item, isTrusted);
Andy Hungb64ea8e2021-12-07 21:50:04 -0800449
450 // Status is selectively authenticated.
451 processStatus(item);
452
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800453 if (status != NO_ERROR) return status; // may not be permitted.
454
455 // Only if the item was successfully submitted (permission)
456 // do we check triggered actions.
Andy Hungb64ea8e2021-12-07 21:50:04 -0800457 processActions(item);
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800458 return NO_ERROR;
Andy Hung06f3aba2019-12-03 16:36:42 -0800459}
460
Andy Hung709b91e2020-04-04 14:23:36 -0700461std::pair<std::string, int32_t> AudioAnalytics::dump(
462 int32_t lines, int64_t sinceNs, const char *prefix) const
Andy Hung06f3aba2019-12-03 16:36:42 -0800463{
464 std::stringstream ss;
465 int32_t ll = lines;
466
467 if (ll > 0) {
Andy Hung709b91e2020-04-04 14:23:36 -0700468 auto [s, l] = mAnalyticsState->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 }
472 if (ll > 0) {
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800473 ss << "Prior audioserver state:\n";
Andy Hung06f3aba2019-12-03 16:36:42 -0800474 --ll;
475 }
476 if (ll > 0) {
Andy Hung709b91e2020-04-04 14:23:36 -0700477 auto [s, l] = mPreviousAnalyticsState->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 }
Joey Poomarin52989982020-03-05 17:40:49 +0800481
482 if (ll > 0 && prefix == nullptr) {
483 auto [s, l] = mAudioPowerUsage.dump(ll);
484 ss << s;
485 ll -= l;
486 }
Andy Hunga629bd12020-06-05 16:03:53 -0700487
Andy Hung06f3aba2019-12-03 16:36:42 -0800488 return { ss.str(), lines - ll };
489}
490
Andy Hungb64ea8e2021-12-07 21:50:04 -0800491void AudioAnalytics::processActions(const std::shared_ptr<const mediametrics::Item>& item)
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800492{
493 auto actions = mActions.getActionsForItem(item); // internally locked.
494 // Execute actions with no lock held.
495 for (const auto& action : actions) {
496 (*action)(item);
497 }
498}
499
Andy Hungb64ea8e2021-12-07 21:50:04 -0800500void AudioAnalytics::processStatus(const std::shared_ptr<const mediametrics::Item>& item)
501{
502 int32_t status;
503 if (!item->get(AMEDIAMETRICS_PROP_STATUS, &status)) return;
504
505 // Any record with a status will automatically be added to a heat map.
506 // Standard information.
507 const auto key = item->getKey();
508 const auto uid = item->getUid();
509
510 // from audio.track.10 -> prefix = audio.track, suffix = 10
511 // from audio.track.error -> prefix = audio.track, suffix = error
512 const auto [prefixKey, suffixKey] = stringutils::splitPrefixKey(key);
513
514 std::string message;
515 item->get(AMEDIAMETRICS_PROP_STATUSMESSAGE, &message); // optional
516
517 int32_t subCode = 0; // not used
518 (void)item->get(AMEDIAMETRICS_PROP_STATUSSUBCODE, &subCode); // optional
519
520 std::string eventStr; // optional
521 item->get(AMEDIAMETRICS_PROP_EVENT, &eventStr);
522
523 const std::string statusString = extendedStatusToStatusString(status);
524
525 // Add to the heat map - we automatically track every item's status to see
526 // the types of errors and the frequency of errors.
527 mHeatMap.add(prefixKey, suffixKey, eventStr, statusString, uid, message, subCode);
528}
529
Andy Hungea186fa2020-01-09 18:13:15 -0800530// HELPER METHODS
531
532std::string AudioAnalytics::getThreadFromTrack(const std::string& track) const
533{
534 int32_t threadId_int32{};
535 if (mAnalyticsState->timeMachine().get(
536 track, AMEDIAMETRICS_PROP_THREADID, &threadId_int32) != NO_ERROR) {
537 return {};
538 }
539 return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(threadId_int32);
540}
541
Andy Hungce9b6632020-04-28 20:15:17 -0700542// DeviceUse helper class.
543void AudioAnalytics::DeviceUse::endAudioIntervalGroup(
Andy Hungea840382020-05-05 21:50:17 -0700544 const std::shared_ptr<const android::mediametrics::Item> &item, ItemType itemType) const {
Andy Hungce9b6632020-04-28 20:15:17 -0700545 const std::string& key = item->getKey();
546 const std::string id = key.substr(
Andy Hungea840382020-05-05 21:50:17 -0700547 (itemType == THREAD ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD)
548 : itemType == TRACK ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
549 : sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD))
Andy Hungce9b6632020-04-28 20:15:17 -0700550 - 1);
551 // deliver statistics
552 int64_t deviceTimeNs = 0;
553 mAudioAnalytics.mAnalyticsState->timeMachine().get(
554 key, AMEDIAMETRICS_PROP_DEVICETIMENS, &deviceTimeNs);
555 std::string encoding;
556 mAudioAnalytics.mAnalyticsState->timeMachine().get(
557 key, AMEDIAMETRICS_PROP_ENCODING, &encoding);
558 int32_t frameCount = 0;
559 mAudioAnalytics.mAnalyticsState->timeMachine().get(
560 key, AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount);
Andy Hung1ea842e2020-05-18 10:47:31 -0700561 std::string inputDevicePairs;
Andy Hungea840382020-05-05 21:50:17 -0700562 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hung1ea842e2020-05-18 10:47:31 -0700563 key, AMEDIAMETRICS_PROP_INPUTDEVICES, &inputDevicePairs);
Andy Hungce9b6632020-04-28 20:15:17 -0700564 int32_t intervalCount = 0;
565 mAudioAnalytics.mAnalyticsState->timeMachine().get(
566 key, AMEDIAMETRICS_PROP_INTERVALCOUNT, &intervalCount);
Andy Hung1ea842e2020-05-18 10:47:31 -0700567 std::string outputDevicePairs;
Andy Hungce9b6632020-04-28 20:15:17 -0700568 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hung1ea842e2020-05-18 10:47:31 -0700569 key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevicePairs);
Andy Hungce9b6632020-04-28 20:15:17 -0700570 int32_t sampleRate = 0;
571 mAudioAnalytics.mAnalyticsState->timeMachine().get(
572 key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
Andy Hungea840382020-05-05 21:50:17 -0700573 std::string flags;
Andy Hungce9b6632020-04-28 20:15:17 -0700574 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hungea840382020-05-05 21:50:17 -0700575 key, AMEDIAMETRICS_PROP_FLAGS, &flags);
Andy Hung1ea842e2020-05-18 10:47:31 -0700576
Andy Hungea840382020-05-05 21:50:17 -0700577 // We may have several devices.
Andy Hung1ea842e2020-05-18 10:47:31 -0700578 // Accumulate the bit flags for input and output devices.
579 std::stringstream oss;
580 long_enum_type_t outputDeviceBits{};
581 { // compute outputDevices
582 const auto devaddrvec = stringutils::getDeviceAddressPairs(outputDevicePairs);
Andy Hungea840382020-05-05 21:50:17 -0700583 for (const auto& [device, addr] : devaddrvec) {
Andy Hung1ea842e2020-05-18 10:47:31 -0700584 if (oss.tellp() > 0) oss << "|"; // delimit devices with '|'.
585 oss << device;
586 outputDeviceBits += types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(device);
Andy Hungea840382020-05-05 21:50:17 -0700587 }
588 }
Andy Hung1ea842e2020-05-18 10:47:31 -0700589 const std::string outputDevices = oss.str();
590
591 std::stringstream iss;
592 long_enum_type_t inputDeviceBits{};
593 { // compute inputDevices
594 const auto devaddrvec = stringutils::getDeviceAddressPairs(inputDevicePairs);
595 for (const auto& [device, addr] : devaddrvec) {
596 if (iss.tellp() > 0) iss << "|"; // delimit devices with '|'.
597 iss << device;
598 inputDeviceBits += types::lookup<types::INPUT_DEVICE, long_enum_type_t>(device);
599 }
600 }
601 const std::string inputDevices = iss.str();
Andy Hungce9b6632020-04-28 20:15:17 -0700602
603 // Get connected device name if from bluetooth.
604 bool isBluetooth = false;
Andy Hunga629bd12020-06-05 16:03:53 -0700605
606 std::string inputDeviceNames; // not filled currently.
607 std::string outputDeviceNames;
Andy Hungce9b6632020-04-28 20:15:17 -0700608 if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos) {
609 isBluetooth = true;
Andy Hung3deef2b2020-07-17 12:58:54 -0700610 outputDeviceNames = SUPPRESSED;
611#if 0 // TODO(b/161554630) sanitize name
Andy Hungce9b6632020-04-28 20:15:17 -0700612 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hunga629bd12020-06-05 16:03:53 -0700613 "audio.device.bt_a2dp", AMEDIAMETRICS_PROP_NAME, &outputDeviceNames);
Andy Hung1ea842e2020-05-18 10:47:31 -0700614 // Remove | if present
Andy Hunga629bd12020-06-05 16:03:53 -0700615 stringutils::replace(outputDeviceNames, "|", '?');
616 if (outputDeviceNames.size() > STATSD_DEVICE_NAME_MAX_LENGTH) {
617 outputDeviceNames.resize(STATSD_DEVICE_NAME_MAX_LENGTH); // truncate
618 }
Andy Hung3deef2b2020-07-17 12:58:54 -0700619#endif
Andy Hungce9b6632020-04-28 20:15:17 -0700620 }
621
Andy Hungea840382020-05-05 21:50:17 -0700622 switch (itemType) {
623 case RECORD: {
624 std::string callerName;
Andy Hunga629bd12020-06-05 16:03:53 -0700625 const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
626 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
Andy Hungce9b6632020-04-28 20:15:17 -0700627
Andy Hungea840382020-05-05 21:50:17 -0700628 std::string packageName;
629 int64_t versionCode = 0;
630 int32_t uid = -1;
631 mAudioAnalytics.mAnalyticsState->timeMachine().get(
632 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
633 if (uid != -1) {
634 std::tie(packageName, versionCode) =
635 MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
636 }
637
638 int32_t selectedDeviceId = 0;
639 mAudioAnalytics.mAnalyticsState->timeMachine().get(
640 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
641 std::string source;
642 mAudioAnalytics.mAnalyticsState->timeMachine().get(
643 key, AMEDIAMETRICS_PROP_SOURCE, &source);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800644 // Android S
645 std::string logSessionId;
646 mAudioAnalytics.mAnalyticsState->timeMachine().get(
647 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
Andy Hungea840382020-05-05 21:50:17 -0700648
Andy Hung1ea842e2020-05-18 10:47:31 -0700649 const auto callerNameForStats =
650 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
651 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
652 const auto flagsForStats = types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags);
653 const auto sourceForStats = types::lookup<types::SOURCE_TYPE, short_enum_type_t>(source);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800654 // Android S
Andy Hungc9b6f8b2021-07-08 10:17:55 -0700655 const auto logSessionIdForStats = ValidateId::get()->validateId(logSessionId);
Andy Hungea840382020-05-05 21:50:17 -0700656
Andy Hunga629bd12020-06-05 16:03:53 -0700657 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700658 << " id:" << id
659 << " inputDevices:" << inputDevices << "(" << inputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700660 << ") inputDeviceNames:" << inputDeviceNames
Andy Hung1ea842e2020-05-18 10:47:31 -0700661 << " deviceTimeNs:" << deviceTimeNs
662 << " encoding:" << encoding << "(" << encodingForStats
663 << ") frameCount:" << frameCount
664 << " intervalCount:" << intervalCount
665 << " sampleRate:" << sampleRate
666 << " flags:" << flags << "(" << flagsForStats
667 << ") packageName:" << packageName
668 << " selectedDeviceId:" << selectedDeviceId
669 << " callerName:" << callerName << "(" << callerNameForStats
Andy Hungcbcfaa22021-02-23 13:54:49 -0800670 << ") source:" << source << "(" << sourceForStats
671 << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats
672 << ")";
Andy Hunga629bd12020-06-05 16:03:53 -0700673 if (clientCalled // only log if client app called AudioRecord.
674 && mAudioAnalytics.mDeliverStatistics) {
675 const auto [ result, str ] = sendToStatsd(AudioRecordDeviceUsageFields,
676 CONDITION(android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700677 , ENUM_EXTRACT(inputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700678 , inputDeviceNames.c_str()
Andy Hungea840382020-05-05 21:50:17 -0700679 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700680 , ENUM_EXTRACT(encodingForStats)
Andy Hungea840382020-05-05 21:50:17 -0700681 , frameCount
682 , intervalCount
683 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700684 , ENUM_EXTRACT(flagsForStats)
Andy Hungea840382020-05-05 21:50:17 -0700685
686 , packageName.c_str()
687 , selectedDeviceId
Andy Hung1ea842e2020-05-18 10:47:31 -0700688 , ENUM_EXTRACT(callerNameForStats)
689 , ENUM_EXTRACT(sourceForStats)
Andy Hungcbcfaa22021-02-23 13:54:49 -0800690 , logSessionIdForStats.c_str()
Andy Hungea840382020-05-05 21:50:17 -0700691 );
Andy Hunga629bd12020-06-05 16:03:53 -0700692 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700693 mAudioAnalytics.mStatsdLog->log(
694 android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -0700695 }
Andy Hungea840382020-05-05 21:50:17 -0700696 } break;
697 case THREAD: {
698 std::string type;
699 mAudioAnalytics.mAnalyticsState->timeMachine().get(
700 key, AMEDIAMETRICS_PROP_TYPE, &type);
701 int32_t underrun = 0; // zero for record types
702 mAudioAnalytics.mAnalyticsState->timeMachine().get(
703 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
Andy Hung1ea842e2020-05-18 10:47:31 -0700704
705 const bool isInput = types::isInputThreadType(type);
706 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
707 const auto flagsForStats =
708 (isInput ? types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags)
709 : types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags));
710 const auto typeForStats = types::lookup<types::THREAD_TYPE, short_enum_type_t>(type);
711
Andy Hunga629bd12020-06-05 16:03:53 -0700712 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700713 << " id:" << id
714 << " inputDevices:" << inputDevices << "(" << inputDeviceBits
715 << ") outputDevices:" << outputDevices << "(" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700716 << ") inputDeviceNames:" << inputDeviceNames
717 << " outputDeviceNames:" << outputDeviceNames
Andy Hung1ea842e2020-05-18 10:47:31 -0700718 << " deviceTimeNs:" << deviceTimeNs
719 << " encoding:" << encoding << "(" << encodingForStats
720 << ") frameCount:" << frameCount
721 << " intervalCount:" << intervalCount
722 << " sampleRate:" << sampleRate
723 << " underrun:" << underrun
724 << " flags:" << flags << "(" << flagsForStats
725 << ") type:" << type << "(" << typeForStats
726 << ")";
Andy Hungea840382020-05-05 21:50:17 -0700727 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -0700728 const auto [ result, str ] = sendToStatsd(AudioThreadDeviceUsageFields,
729 CONDITION(android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
730 , isInput ? ENUM_EXTRACT(inputDeviceBits) : ENUM_EXTRACT(outputDeviceBits)
731 , isInput ? inputDeviceNames.c_str() : outputDeviceNames.c_str()
Andy Hungea840382020-05-05 21:50:17 -0700732 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700733 , ENUM_EXTRACT(encodingForStats)
Andy Hungea840382020-05-05 21:50:17 -0700734 , frameCount
735 , intervalCount
736 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700737 , ENUM_EXTRACT(flagsForStats)
Andy Hungea840382020-05-05 21:50:17 -0700738 , underrun
Andy Hung1ea842e2020-05-18 10:47:31 -0700739 , ENUM_EXTRACT(typeForStats)
Andy Hungea840382020-05-05 21:50:17 -0700740 );
Andy Hunga629bd12020-06-05 16:03:53 -0700741 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700742 mAudioAnalytics.mStatsdLog->log(
743 android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -0700744 }
Andy Hungea840382020-05-05 21:50:17 -0700745 } break;
746 case TRACK: {
Andy Hungce9b6632020-04-28 20:15:17 -0700747 std::string callerName;
Andy Hunga629bd12020-06-05 16:03:53 -0700748 const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
749 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
750
Andy Hungce9b6632020-04-28 20:15:17 -0700751 std::string contentType;
752 mAudioAnalytics.mAnalyticsState->timeMachine().get(
753 key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentType);
754 double deviceLatencyMs = 0.;
755 mAudioAnalytics.mAnalyticsState->timeMachine().get(
756 key, AMEDIAMETRICS_PROP_DEVICELATENCYMS, &deviceLatencyMs);
757 double deviceStartupMs = 0.;
758 mAudioAnalytics.mAnalyticsState->timeMachine().get(
759 key, AMEDIAMETRICS_PROP_DEVICESTARTUPMS, &deviceStartupMs);
760 double deviceVolume = 0.;
761 mAudioAnalytics.mAnalyticsState->timeMachine().get(
762 key, AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume);
763 std::string packageName;
764 int64_t versionCode = 0;
765 int32_t uid = -1;
766 mAudioAnalytics.mAnalyticsState->timeMachine().get(
767 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
768 if (uid != -1) {
769 std::tie(packageName, versionCode) =
770 MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
771 }
772 double playbackPitch = 0.;
773 mAudioAnalytics.mAnalyticsState->timeMachine().get(
774 key, AMEDIAMETRICS_PROP_PLAYBACK_PITCH, &playbackPitch);
775 double playbackSpeed = 0.;
776 mAudioAnalytics.mAnalyticsState->timeMachine().get(
777 key, AMEDIAMETRICS_PROP_PLAYBACK_SPEED, &playbackSpeed);
778 int32_t selectedDeviceId = 0;
779 mAudioAnalytics.mAnalyticsState->timeMachine().get(
780 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
Andy Hungea840382020-05-05 21:50:17 -0700781 std::string streamType;
782 mAudioAnalytics.mAnalyticsState->timeMachine().get(
783 key, AMEDIAMETRICS_PROP_STREAMTYPE, &streamType);
Andy Hunga629bd12020-06-05 16:03:53 -0700784 std::string traits;
785 mAudioAnalytics.mAnalyticsState->timeMachine().get(
786 key, AMEDIAMETRICS_PROP_TRAITS, &traits);
Andy Hungea840382020-05-05 21:50:17 -0700787 int32_t underrun = 0;
788 mAudioAnalytics.mAnalyticsState->timeMachine().get(
789 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
Andy Hungce9b6632020-04-28 20:15:17 -0700790 std::string usage;
791 mAudioAnalytics.mAnalyticsState->timeMachine().get(
792 key, AMEDIAMETRICS_PROP_USAGE, &usage);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800793 // Android S
794 std::string logSessionId;
795 mAudioAnalytics.mAnalyticsState->timeMachine().get(
796 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
Andy Hungce9b6632020-04-28 20:15:17 -0700797
Andy Hung1ea842e2020-05-18 10:47:31 -0700798 const auto callerNameForStats =
799 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
800 const auto contentTypeForStats =
801 types::lookup<types::CONTENT_TYPE, short_enum_type_t>(contentType);
802 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
803 const auto flagsForStats = types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags);
804 const auto streamTypeForStats =
805 types::lookup<types::STREAM_TYPE, short_enum_type_t>(streamType);
Andy Hunga629bd12020-06-05 16:03:53 -0700806 const auto traitsForStats =
807 types::lookup<types::TRACK_TRAITS, short_enum_type_t>(traits);
Andy Hung1ea842e2020-05-18 10:47:31 -0700808 const auto usageForStats = types::lookup<types::USAGE, short_enum_type_t>(usage);
Andy Hungcbcfaa22021-02-23 13:54:49 -0800809 // Android S
Andy Hungc9b6f8b2021-07-08 10:17:55 -0700810 const auto logSessionIdForStats = ValidateId::get()->validateId(logSessionId);
Andy Hung1ea842e2020-05-18 10:47:31 -0700811
Andy Hunga629bd12020-06-05 16:03:53 -0700812 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700813 << " id:" << id
814 << " outputDevices:" << outputDevices << "(" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700815 << ") outputDeviceNames:" << outputDeviceNames
Andy Hung1ea842e2020-05-18 10:47:31 -0700816 << " deviceTimeNs:" << deviceTimeNs
817 << " encoding:" << encoding << "(" << encodingForStats
818 << ") frameCount:" << frameCount
819 << " intervalCount:" << intervalCount
820 << " sampleRate:" << sampleRate
821 << " underrun:" << underrun
822 << " flags:" << flags << "(" << flagsForStats
823 << ") callerName:" << callerName << "(" << callerNameForStats
824 << ") contentType:" << contentType << "(" << contentTypeForStats
825 << ") deviceLatencyMs:" << deviceLatencyMs
826 << " deviceStartupMs:" << deviceStartupMs
827 << " deviceVolume:" << deviceVolume
828 << " packageName:" << packageName
829 << " playbackPitch:" << playbackPitch
830 << " playbackSpeed:" << playbackSpeed
831 << " selectedDeviceId:" << selectedDeviceId
832 << " streamType:" << streamType << "(" << streamTypeForStats
Andy Hunga629bd12020-06-05 16:03:53 -0700833 << ") traits:" << traits << "(" << traitsForStats
Andy Hung1ea842e2020-05-18 10:47:31 -0700834 << ") usage:" << usage << "(" << usageForStats
Andy Hungcbcfaa22021-02-23 13:54:49 -0800835 << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats
Andy Hung1ea842e2020-05-18 10:47:31 -0700836 << ")";
Andy Hunga629bd12020-06-05 16:03:53 -0700837 if (clientCalled // only log if client app called AudioTracks
838 && mAudioAnalytics.mDeliverStatistics) {
839 const auto [ result, str ] = sendToStatsd(AudioTrackDeviceUsageFields,
840 CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700841 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700842 , outputDeviceNames.c_str()
Andy Hungce9b6632020-04-28 20:15:17 -0700843 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700844 , ENUM_EXTRACT(encodingForStats)
Andy Hungce9b6632020-04-28 20:15:17 -0700845 , frameCount
846 , intervalCount
847 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700848 , ENUM_EXTRACT(flagsForStats)
Andy Hungce9b6632020-04-28 20:15:17 -0700849 , underrun
Andy Hungce9b6632020-04-28 20:15:17 -0700850 , packageName.c_str()
851 , (float)deviceLatencyMs
852 , (float)deviceStartupMs
853 , (float)deviceVolume
854 , selectedDeviceId
Andy Hung1ea842e2020-05-18 10:47:31 -0700855 , ENUM_EXTRACT(streamTypeForStats)
856 , ENUM_EXTRACT(usageForStats)
857 , ENUM_EXTRACT(contentTypeForStats)
858 , ENUM_EXTRACT(callerNameForStats)
Andy Hunga629bd12020-06-05 16:03:53 -0700859 , ENUM_EXTRACT(traitsForStats)
Andy Hungcbcfaa22021-02-23 13:54:49 -0800860 , logSessionIdForStats.c_str()
Andy Hungce9b6632020-04-28 20:15:17 -0700861 );
Andy Hunga629bd12020-06-05 16:03:53 -0700862 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700863 mAudioAnalytics.mStatsdLog->log(
864 android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED, str);
Andy Hungce9b6632020-04-28 20:15:17 -0700865 }
Andy Hungea840382020-05-05 21:50:17 -0700866 } break;
Andy Hungce9b6632020-04-28 20:15:17 -0700867 }
868
869 // Report this as needed.
870 if (isBluetooth) {
871 // report this for Bluetooth
872 }
873}
874
875// DeviceConnection helper class.
876void AudioAnalytics::DeviceConnection::a2dpConnected(
877 const std::shared_ptr<const android::mediametrics::Item> &item) {
878 const std::string& key = item->getKey();
Andy Hungea840382020-05-05 21:50:17 -0700879 const int64_t atNs = item->getTimestamp();
Andy Hungce9b6632020-04-28 20:15:17 -0700880 {
881 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -0700882 mA2dpConnectionServiceNs = atNs;
883 ++mA2dpConnectionServices;
884
885 if (mA2dpConnectionRequestNs == 0) {
886 mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
887 }
888 // This sets the time we were connected. Now we look for the delta in the future.
Andy Hungce9b6632020-04-28 20:15:17 -0700889 }
890 std::string name;
891 item->get(AMEDIAMETRICS_PROP_NAME, &name);
Andy Hungea840382020-05-05 21:50:17 -0700892 ALOGD("(key=%s) a2dp connected device:%s atNs:%lld",
893 key.c_str(), name.c_str(), (long long)atNs);
Andy Hungce9b6632020-04-28 20:15:17 -0700894}
895
896void AudioAnalytics::DeviceConnection::createPatch(
897 const std::shared_ptr<const android::mediametrics::Item> &item) {
898 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -0700899 if (mA2dpConnectionServiceNs == 0) return; // patch unrelated to us.
Andy Hungce9b6632020-04-28 20:15:17 -0700900 const std::string& key = item->getKey();
901 std::string outputDevices;
902 item->get(AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices);
Andy Hungea840382020-05-05 21:50:17 -0700903 if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH_A2DP") != std::string::npos) {
Andy Hungce9b6632020-04-28 20:15:17 -0700904 // TODO compare address
Andy Hung1ea842e2020-05-18 10:47:31 -0700905 int64_t timeDiffNs = item->getTimestamp();
Andy Hungea840382020-05-05 21:50:17 -0700906 if (mA2dpConnectionRequestNs == 0) {
907 ALOGD("%s: A2DP create patch didn't see a connection request", __func__);
Andy Hung1ea842e2020-05-18 10:47:31 -0700908 timeDiffNs -= mA2dpConnectionServiceNs;
Andy Hungea840382020-05-05 21:50:17 -0700909 } else {
Andy Hung1ea842e2020-05-18 10:47:31 -0700910 timeDiffNs -= mA2dpConnectionRequestNs;
Andy Hungea840382020-05-05 21:50:17 -0700911 }
Andy Hung1ea842e2020-05-18 10:47:31 -0700912
Andy Hungea840382020-05-05 21:50:17 -0700913 mA2dpConnectionRequestNs = 0;
914 mA2dpConnectionServiceNs = 0;
915 ++mA2dpConnectionSuccesses;
916
Andy Hungc14ee142021-03-10 16:39:02 -0800917 const auto connectionTimeMs = float((double)timeDiffNs * 1e-6);
Andy Hung1ea842e2020-05-18 10:47:31 -0700918
919 const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
920 "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
921
Andy Hunga629bd12020-06-05 16:03:53 -0700922 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700923 << " A2DP SUCCESS"
924 << " outputDevices:" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700925 << " deviceName:" << mA2dpDeviceName
Andy Hung1ea842e2020-05-18 10:47:31 -0700926 << " connectionTimeMs:" << connectionTimeMs;
Andy Hungea840382020-05-05 21:50:17 -0700927 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hung1ea842e2020-05-18 10:47:31 -0700928 const long_enum_type_t inputDeviceBits{};
Andy Hunga629bd12020-06-05 16:03:53 -0700929
930 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
931 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700932 , ENUM_EXTRACT(inputDeviceBits)
933 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700934 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -0700935 , types::DEVICE_CONNECTION_RESULT_SUCCESS
936 , connectionTimeMs
Andy Hungea840382020-05-05 21:50:17 -0700937 , /* connection_count */ 1
938 );
Andy Hunga629bd12020-06-05 16:03:53 -0700939 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700940 mAudioAnalytics.mStatsdLog->log(
941 android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -0700942 }
Andy Hungce9b6632020-04-28 20:15:17 -0700943 }
944}
945
Andy Hungea840382020-05-05 21:50:17 -0700946// Called through AudioManager when the BT service wants to enable
947void AudioAnalytics::DeviceConnection::postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
948 const std::shared_ptr<const android::mediametrics::Item> &item) {
949 const int64_t atNs = item->getTimestamp();
950 const std::string& key = item->getKey();
951 std::string state;
952 item->get(AMEDIAMETRICS_PROP_STATE, &state);
953 if (state != "connected") return;
Andy Hunga629bd12020-06-05 16:03:53 -0700954
955 std::string name;
956 item->get(AMEDIAMETRICS_PROP_NAME, &name);
Andy Hungea840382020-05-05 21:50:17 -0700957 {
958 std::lock_guard l(mLock);
959 mA2dpConnectionRequestNs = atNs;
960 ++mA2dpConnectionRequests;
Andy Hung3deef2b2020-07-17 12:58:54 -0700961 mA2dpDeviceName = SUPPRESSED; // TODO(b/161554630) sanitize name
Andy Hungea840382020-05-05 21:50:17 -0700962 }
Andy Hunga629bd12020-06-05 16:03:53 -0700963 ALOGD("(key=%s) a2dp connection name:%s request atNs:%lld",
964 key.c_str(), name.c_str(), (long long)atNs);
Andy Hungea840382020-05-05 21:50:17 -0700965 // TODO: attempt to cancel a timed event, rather than let it expire.
966 mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
967}
968
Andy Hungce9b6632020-04-28 20:15:17 -0700969void AudioAnalytics::DeviceConnection::expire() {
970 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -0700971 if (mA2dpConnectionRequestNs == 0) return; // ignore (this was an internal connection).
Andy Hung1ea842e2020-05-18 10:47:31 -0700972
Andy Hung1ea842e2020-05-18 10:47:31 -0700973 const long_enum_type_t inputDeviceBits{};
Andy Hung1ea842e2020-05-18 10:47:31 -0700974 const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
975 "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
976
Andy Hungea840382020-05-05 21:50:17 -0700977 if (mA2dpConnectionServiceNs == 0) {
Andy Hungea840382020-05-05 21:50:17 -0700978 ++mA2dpConnectionJavaServiceCancels; // service did not connect to A2DP
Andy Hungce9b6632020-04-28 20:15:17 -0700979
Andy Hunga629bd12020-06-05 16:03:53 -0700980 LOG(LOG_LEVEL) << "A2DP CANCEL"
981 << " outputDevices:" << outputDeviceBits
982 << " deviceName:" << mA2dpDeviceName;
Andy Hungea840382020-05-05 21:50:17 -0700983 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -0700984 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
985 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700986 , ENUM_EXTRACT(inputDeviceBits)
987 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700988 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -0700989 , types::DEVICE_CONNECTION_RESULT_JAVA_SERVICE_CANCEL
Andy Hungea840382020-05-05 21:50:17 -0700990 , /* connection_time_ms */ 0.f
991 , /* connection_count */ 1
992 );
Andy Hunga629bd12020-06-05 16:03:53 -0700993 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -0700994 mAudioAnalytics.mStatsdLog->log(
995 android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -0700996 }
Andy Hungea840382020-05-05 21:50:17 -0700997 return;
998 }
999
1000 // AudioFlinger didn't play - an expiration may occur because there is no audio playing.
1001 // Should we check elsewhere?
Andy Hungce9b6632020-04-28 20:15:17 -07001002 // TODO: disambiguate this case.
Andy Hungea840382020-05-05 21:50:17 -07001003 mA2dpConnectionRequestNs = 0;
1004 mA2dpConnectionServiceNs = 0;
1005 ++mA2dpConnectionUnknowns; // connection result unknown
Andy Hung1ea842e2020-05-18 10:47:31 -07001006
Andy Hunga629bd12020-06-05 16:03:53 -07001007 LOG(LOG_LEVEL) << "A2DP UNKNOWN"
1008 << " outputDevices:" << outputDeviceBits
1009 << " deviceName:" << mA2dpDeviceName;
Andy Hungea840382020-05-05 21:50:17 -07001010 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -07001011 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
1012 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -07001013 , ENUM_EXTRACT(inputDeviceBits)
1014 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -07001015 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -07001016 , types::DEVICE_CONNECTION_RESULT_UNKNOWN
Andy Hungea840382020-05-05 21:50:17 -07001017 , /* connection_time_ms */ 0.f
1018 , /* connection_count */ 1
1019 );
Andy Hunga629bd12020-06-05 16:03:53 -07001020 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -07001021 mAudioAnalytics.mStatsdLog->log(
1022 android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
Andy Hungea840382020-05-05 21:50:17 -07001023 }
Andy Hungce9b6632020-04-28 20:15:17 -07001024}
1025
jiabin515eb092020-11-18 17:55:52 -08001026void AudioAnalytics::AAudioStreamInfo::endAAudioStream(
1027 const std::shared_ptr<const android::mediametrics::Item> &item, CallerPath path) const {
1028 const std::string& key = item->getKey();
1029
jiabin515eb092020-11-18 17:55:52 -08001030 std::string directionStr;
1031 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1032 key, AMEDIAMETRICS_PROP_DIRECTION, &directionStr);
1033 const auto direction = types::lookup<types::AAUDIO_DIRECTION, int32_t>(directionStr);
1034
1035 int32_t framesPerBurst = -1;
1036 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1037 key, AMEDIAMETRICS_PROP_BURSTFRAMES, &framesPerBurst);
1038
1039 int32_t bufferSizeInFrames = -1;
1040 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1041 key, AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, &bufferSizeInFrames);
1042
1043 int32_t bufferCapacityInFrames = -1;
1044 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1045 key, AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, &bufferCapacityInFrames);
1046
1047 int32_t channelCount = -1;
1048 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1049 key, AMEDIAMETRICS_PROP_CHANNELCOUNT, &channelCount);
jiabinfbf20302021-07-28 22:15:01 +00001050 if (channelCount == -1) {
1051 // Try to get channel count from channel mask. From the legacy path,
1052 // only channel mask are logged.
1053 int32_t channelMask = 0;
1054 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1055 key, AMEDIAMETRICS_PROP_CHANNELMASK, &channelMask);
1056 if (channelMask != 0) {
1057 switch (direction) {
1058 case 1: // Output, keep sync with AudioTypes#getAAudioDirection()
1059 channelCount = audio_channel_count_from_out_mask(channelMask);
1060 break;
1061 case 2: // Input, keep sync with AudioTypes#getAAudioDirection()
1062 channelCount = audio_channel_count_from_in_mask(channelMask);
1063 break;
1064 default:
1065 ALOGW("Invalid direction %d", direction);
1066 }
1067 }
1068 }
jiabin515eb092020-11-18 17:55:52 -08001069
1070 int64_t totalFramesTransferred = -1;
jiabin97247ea2021-04-07 00:33:38 +00001071 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1072 key, AMEDIAMETRICS_PROP_FRAMESTRANSFERRED, &totalFramesTransferred);
jiabin515eb092020-11-18 17:55:52 -08001073
1074 std::string perfModeRequestedStr;
1075 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1076 key, AMEDIAMETRICS_PROP_PERFORMANCEMODE, &perfModeRequestedStr);
1077 const auto perfModeRequested =
1078 types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeRequestedStr);
1079
jiabin97247ea2021-04-07 00:33:38 +00001080 std::string perfModeActualStr;
1081 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1082 key, AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL, &perfModeActualStr);
1083 const auto perfModeActual =
1084 types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeActualStr);
jiabin515eb092020-11-18 17:55:52 -08001085
jiabinc8da9032021-04-28 20:42:36 +00001086 std::string sharingModeActualStr;
jiabin515eb092020-11-18 17:55:52 -08001087 mAudioAnalytics.mAnalyticsState->timeMachine().get(
jiabinc8da9032021-04-28 20:42:36 +00001088 key, AMEDIAMETRICS_PROP_SHARINGMODEACTUAL, &sharingModeActualStr);
1089 const auto sharingModeActual =
1090 types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeActualStr);
jiabin515eb092020-11-18 17:55:52 -08001091
1092 int32_t xrunCount = -1;
1093 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1094 key, AMEDIAMETRICS_PROP_UNDERRUN, &xrunCount);
1095
jiabin92c9a522021-02-12 22:37:42 +00001096 std::string serializedDeviceTypes;
jiabin515eb092020-11-18 17:55:52 -08001097 // TODO: only routed device id is logged, but no device type
1098
jiabin97247ea2021-04-07 00:33:38 +00001099 std::string formatAppStr;
1100 mAudioAnalytics.mAnalyticsState->timeMachine().get(
jiabinef348b82021-04-19 16:53:08 +00001101 key, AMEDIAMETRICS_PROP_ENCODINGCLIENT, &formatAppStr);
jiabin97247ea2021-04-07 00:33:38 +00001102 const auto formatApp = types::lookup<types::ENCODING, int32_t>(formatAppStr);
jiabin515eb092020-11-18 17:55:52 -08001103
1104 std::string formatDeviceStr;
1105 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1106 key, AMEDIAMETRICS_PROP_ENCODING, &formatDeviceStr);
1107 const auto formatDevice = types::lookup<types::ENCODING, int32_t>(formatDeviceStr);
1108
jiabin92c9a522021-02-12 22:37:42 +00001109 std::string logSessionId;
jiabin97247ea2021-04-07 00:33:38 +00001110 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1111 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
jiabin92c9a522021-02-12 22:37:42 +00001112
jiabinc4c331c2021-03-23 17:11:01 +00001113 int32_t sampleRate = 0;
1114 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1115 key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
1116
1117 std::string contentTypeStr;
1118 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1119 key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentTypeStr);
1120 const auto contentType = types::lookup<types::CONTENT_TYPE, int32_t>(contentTypeStr);
1121
jiabinc8da9032021-04-28 20:42:36 +00001122 std::string sharingModeRequestedStr;
1123 mAudioAnalytics.mAnalyticsState->timeMachine().get(
1124 key, AMEDIAMETRICS_PROP_SHARINGMODE, &sharingModeRequestedStr);
1125 const auto sharingModeRequested =
1126 types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeRequestedStr);
1127
jiabin515eb092020-11-18 17:55:52 -08001128 LOG(LOG_LEVEL) << "key:" << key
jiabin515eb092020-11-18 17:55:52 -08001129 << " path:" << path
1130 << " direction:" << direction << "(" << directionStr << ")"
1131 << " frames_per_burst:" << framesPerBurst
1132 << " buffer_size:" << bufferSizeInFrames
1133 << " buffer_capacity:" << bufferCapacityInFrames
1134 << " channel_count:" << channelCount
1135 << " total_frames_transferred:" << totalFramesTransferred
1136 << " perf_mode_requested:" << perfModeRequested << "(" << perfModeRequestedStr << ")"
jiabin97247ea2021-04-07 00:33:38 +00001137 << " perf_mode_actual:" << perfModeActual << "(" << perfModeActualStr << ")"
jiabinc8da9032021-04-28 20:42:36 +00001138 << " sharing:" << sharingModeActual << "(" << sharingModeActualStr << ")"
jiabin515eb092020-11-18 17:55:52 -08001139 << " xrun_count:" << xrunCount
jiabin92c9a522021-02-12 22:37:42 +00001140 << " device_type:" << serializedDeviceTypes
jiabin97247ea2021-04-07 00:33:38 +00001141 << " format_app:" << formatApp << "(" << formatAppStr << ")"
jiabin92c9a522021-02-12 22:37:42 +00001142 << " format_device: " << formatDevice << "(" << formatDeviceStr << ")"
jiabinc4c331c2021-03-23 17:11:01 +00001143 << " log_session_id: " << logSessionId
1144 << " sample_rate: " << sampleRate
jiabinc8da9032021-04-28 20:42:36 +00001145 << " content_type: " << contentType << "(" << contentTypeStr << ")"
1146 << " sharing_requested:" << sharingModeRequested
1147 << "(" << sharingModeRequestedStr << ")";
jiabin515eb092020-11-18 17:55:52 -08001148
jiabin92c9a522021-02-12 22:37:42 +00001149 if (mAudioAnalytics.mDeliverStatistics) {
1150 android::util::BytesField bf_serialized(
1151 serializedDeviceTypes.c_str(), serializedDeviceTypes.size());
1152 const auto result = sendToStatsd(
1153 CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
jiabin92c9a522021-02-12 22:37:42 +00001154 , path
1155 , direction
1156 , framesPerBurst
1157 , bufferSizeInFrames
1158 , bufferCapacityInFrames
1159 , channelCount
1160 , totalFramesTransferred
1161 , perfModeRequested
1162 , perfModeActual
jiabinc8da9032021-04-28 20:42:36 +00001163 , sharingModeActual
jiabin92c9a522021-02-12 22:37:42 +00001164 , xrunCount
1165 , bf_serialized
1166 , formatApp
1167 , formatDevice
1168 , logSessionId.c_str()
jiabinc4c331c2021-03-23 17:11:01 +00001169 , sampleRate
1170 , contentType
jiabinc8da9032021-04-28 20:42:36 +00001171 , sharingModeRequested
jiabin92c9a522021-02-12 22:37:42 +00001172 );
1173 std::stringstream ss;
1174 ss << "result:" << result;
1175 const auto fieldsStr = printFields(AAudioStreamFields,
1176 CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
jiabin92c9a522021-02-12 22:37:42 +00001177 , path
1178 , direction
1179 , framesPerBurst
1180 , bufferSizeInFrames
1181 , bufferCapacityInFrames
1182 , channelCount
1183 , totalFramesTransferred
1184 , perfModeRequested
1185 , perfModeActual
jiabinc8da9032021-04-28 20:42:36 +00001186 , sharingModeActual
jiabin92c9a522021-02-12 22:37:42 +00001187 , xrunCount
1188 , serializedDeviceTypes.c_str()
1189 , formatApp
1190 , formatDevice
1191 , logSessionId.c_str()
jiabinc4c331c2021-03-23 17:11:01 +00001192 , sampleRate
1193 , contentType
jiabinc8da9032021-04-28 20:42:36 +00001194 , sharingModeRequested
jiabin92c9a522021-02-12 22:37:42 +00001195 );
1196 ss << " " << fieldsStr;
1197 std::string str = ss.str();
1198 ALOGV("%s: statsd %s", __func__, str.c_str());
Andy Hung5be90c82021-03-30 14:30:20 -07001199 mAudioAnalytics.mStatsdLog->log(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED, str);
jiabin92c9a522021-02-12 22:37:42 +00001200 }
jiabin515eb092020-11-18 17:55:52 -08001201}
1202
Andy Hung3ab1b322020-05-18 10:47:31 -07001203} // namespace android::mediametrics