blob: 78e2c8947ccf477bcf70c9367e29ff79bf989883 [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 Hungce9b6632020-04-28 20:15:17 -070024#include <audio_utils/clock.h> // clock conversions
Andy Hung1ea842e2020-05-18 10:47:31 -070025#include <cutils/properties.h>
Andy Hungce9b6632020-04-28 20:15:17 -070026#include <statslog.h> // statsd
Andy Hung06f3aba2019-12-03 16:36:42 -080027
Andy Hung1ea842e2020-05-18 10:47:31 -070028#include "AudioTypes.h" // string to int conversions
29#include "MediaMetricsService.h" // package info
30#include "StringUtils.h"
31
32#define PROP_AUDIO_ANALYTICS_CLOUD_ENABLED "persist.audio.analytics.cloud.enabled"
33
Andy Hunga629bd12020-06-05 16:03:53 -070034namespace android::mediametrics {
Andy Hung1ea842e2020-05-18 10:47:31 -070035
Andy Hunga629bd12020-06-05 16:03:53 -070036// Enable for testing of delivery to statsd. Caution if this is enabled, all protos MUST exist.
Andy Hunga0a5ad22020-06-12 09:30:34 -070037#define STATSD_ENABLE
Andy Hung1ea842e2020-05-18 10:47:31 -070038
Andy Hunga629bd12020-06-05 16:03:53 -070039#ifdef STATSD_ENABLE
40#define CONDITION(INT_VALUE) (INT_VALUE) // allow value
Andy Hung1ea842e2020-05-18 10:47:31 -070041#else
Andy Hunga629bd12020-06-05 16:03:53 -070042#define CONDITION(INT_VALUE) (int(0)) // mask value since the proto may not be defined yet.
Andy Hung1ea842e2020-05-18 10:47:31 -070043#endif
44
Andy Hunga629bd12020-06-05 16:03:53 -070045// Maximum length of a device name.
46static constexpr size_t STATSD_DEVICE_NAME_MAX_LENGTH = 32;
Andy Hung06f3aba2019-12-03 16:36:42 -080047
Andy Hunga629bd12020-06-05 16:03:53 -070048// Transmit Enums to statsd in integer or strings (this must match the atoms.proto)
49static constexpr bool STATSD_USE_INT_FOR_ENUM = false;
50
51// derive types based on integer or strings.
52using short_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int32_t, std::string>;
53using long_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int64_t, std::string>;
54
55// Convert std::string to char *
56template <typename T>
57auto ENUM_EXTRACT(const T& x) {
58 if constexpr (std::is_same_v<std::decay_t<T>, std::string>) {
59 return x.c_str();
60 } else {
61 return x;
62 }
63}
64
65static constexpr const auto LOG_LEVEL = android::base::VERBOSE;
66
67/*
68 * For logging purposes, we list all of the MediaMetrics atom fields,
69 * which can then be associated with consecutive arguments to the statsd write.
70 */
71
72static constexpr const char * const AudioRecordDeviceUsageFields[] = {
73 "mediametrics_audiorecorddeviceusage_reported", // proto number
74 "devices",
75 "device_names",
76 "device_time_nanos",
77 "encoding",
78 "frame_count",
79 "interval_count",
80 "sample_rate",
81 "flags",
82 "package_name",
83 "selected_device_id",
84 "caller",
85 "source",
86};
87
88static constexpr const char * const AudioThreadDeviceUsageFields[] = {
89 "mediametrics_audiothreaddeviceusage_reported",
90 "devices",
91 "device_names",
92 "device_time_nanos",
93 "encoding",
94 "frame_count",
95 "interval_count",
96 "sample_rate",
97 "flags",
98 "xruns",
99 "type",
100};
101
102static constexpr const char * const AudioTrackDeviceUsageFields[] = {
103 "mediametrics_audiotrackdeviceusage_reported",
104 "devices",
105 "device_names",
106 "device_time_nanos",
107 "encoding",
108 "frame_count",
109 "interval_count",
110 "sample_rate",
111 "flags",
112 "xruns",
113 "package_name",
114 "device_latency_millis",
115 "device_startup_millis",
116 "device_volume",
117 "selected_device_id",
118 "stream_type",
119 "usage",
120 "content_type",
121 "caller",
122 "traits",
123};
124
125static constexpr const char * const AudioDeviceConnectionFields[] = {
126 "mediametrics_audiodeviceconnection_reported",
127 "input_devices",
128 "output_devices",
129 "device_names",
130 "result",
131 "time_to_connect_millis",
132 "connection_count",
133};
134
135/**
136 * sendToStatsd is a helper method that sends the arguments to statsd
137 * and returns a pair { result, summary_string }.
138 */
139template <size_t N, typename ...Types>
140std::pair<int, std::string> sendToStatsd(const char * const (& fields)[N], Types ... args)
141{
142 int result = 0;
143 std::stringstream ss;
144
145#ifdef STATSD_ENABLE
146 result = android::util::stats_write(args...);
147 ss << "result:" << result;
148#endif
149 ss << " { ";
150 stringutils::fieldPrint(ss, fields, args...);
151 ss << "}";
152 return { result, ss.str() };
153}
Andy Hung06f3aba2019-12-03 16:36:42 -0800154
155AudioAnalytics::AudioAnalytics()
Andy Hung1ea842e2020-05-18 10:47:31 -0700156 : mDeliverStatistics(property_get_bool(PROP_AUDIO_ANALYTICS_CLOUD_ENABLED, true))
Andy Hung06f3aba2019-12-03 16:36:42 -0800157{
Andy Hunga629bd12020-06-05 16:03:53 -0700158 SetMinimumLogSeverity(android::base::DEBUG); // for LOG().
Andy Hung06f3aba2019-12-03 16:36:42 -0800159 ALOGD("%s", __func__);
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800160
161 // Add action to save AnalyticsState if audioserver is restarted.
162 // This triggers on an item of "audio.flinger"
163 // with a property "event" set to "AudioFlinger" (the constructor).
164 mActions.addAction(
Andy Hungea186fa2020-01-09 18:13:15 -0800165 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
166 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR),
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800167 std::make_shared<AnalyticsActions::Function>(
Andy Hungea186fa2020-01-09 18:13:15 -0800168 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
169 ALOGW("(key=%s) Audioflinger constructor event detected", item->getKey().c_str());
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800170 mPreviousAnalyticsState.set(std::make_shared<AnalyticsState>(
171 *mAnalyticsState.get()));
172 // Note: get returns shared_ptr temp, whose lifetime is extended
173 // to end of full expression.
174 mAnalyticsState->clear(); // TODO: filter the analytics state.
Andy Hungea186fa2020-01-09 18:13:15 -0800175 // Perhaps report this.
176 }));
177
Andy Hungea840382020-05-05 21:50:17 -0700178 // Handle device use record statistics
Andy Hungea186fa2020-01-09 18:13:15 -0800179 mActions.addAction(
Andy Hungea840382020-05-05 21:50:17 -0700180 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
181 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
Andy Hungea186fa2020-01-09 18:13:15 -0800182 std::make_shared<AnalyticsActions::Function>(
183 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
Andy Hungea840382020-05-05 21:50:17 -0700184 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::RECORD);
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800185 }));
Andy Hungce9b6632020-04-28 20:15:17 -0700186
187 // Handle device use thread statistics
188 mActions.addAction(
189 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
190 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
191 std::make_shared<AnalyticsActions::Function>(
192 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
Andy Hungea840382020-05-05 21:50:17 -0700193 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::THREAD);
Andy Hungce9b6632020-04-28 20:15:17 -0700194 }));
195
196 // Handle device use track statistics
197 mActions.addAction(
198 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
199 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
200 std::make_shared<AnalyticsActions::Function>(
201 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
Andy Hungea840382020-05-05 21:50:17 -0700202 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::TRACK);
Andy Hungce9b6632020-04-28 20:15:17 -0700203 }));
204
Andy Hungea840382020-05-05 21:50:17 -0700205
206 // Handle device connection statistics
Andy Hungce9b6632020-04-28 20:15:17 -0700207
208 // We track connections (not disconnections) for the time to connect.
209 // TODO: consider BT requests in their A2dp service
210 // AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
211 // AudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
212 // AudioDeviceBroker.postA2dpActiveDeviceChange
213 mActions.addAction(
214 "audio.device.a2dp.state",
Andy Hungea840382020-05-05 21:50:17 -0700215 "connected",
Andy Hungce9b6632020-04-28 20:15:17 -0700216 std::make_shared<AnalyticsActions::Function>(
217 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
218 mDeviceConnection.a2dpConnected(item);
219 }));
220 // If audio is active, we expect to see a createAudioPatch after the device is connected.
221 mActions.addAction(
222 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
223 std::string("createAudioPatch"),
224 std::make_shared<AnalyticsActions::Function>(
225 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
226 mDeviceConnection.createPatch(item);
227 }));
Joey Poomarin52989982020-03-05 17:40:49 +0800228
Andy Hungea840382020-05-05 21:50:17 -0700229 // Called from BT service
230 mActions.addAction(
231 AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE
232 "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent"
233 "." AMEDIAMETRICS_PROP_STATE,
234 "connected",
235 std::make_shared<AnalyticsActions::Function>(
236 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
237 mDeviceConnection.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(item);
238 }));
239
Joey Poomarin52989982020-03-05 17:40:49 +0800240 // Handle power usage
241 mActions.addAction(
242 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
243 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
244 std::make_shared<AnalyticsActions::Function>(
245 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
246 mAudioPowerUsage.checkTrackRecord(item, true /* isTrack */);
247 }));
248
249 mActions.addAction(
250 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
251 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
252 std::make_shared<AnalyticsActions::Function>(
253 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
254 mAudioPowerUsage.checkTrackRecord(item, false /* isTrack */);
255 }));
256
257 mActions.addAction(
258 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
259 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE),
260 std::make_shared<AnalyticsActions::Function>(
261 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
262 // ALOGD("(key=%s) Audioflinger setMode", item->getKey().c_str());
263 mAudioPowerUsage.checkMode(item);
264 }));
265
266 mActions.addAction(
267 AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
268 std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME),
269 std::make_shared<AnalyticsActions::Function>(
270 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
271 // ALOGD("(key=%s) Audioflinger setVoiceVolume", item->getKey().c_str());
272 mAudioPowerUsage.checkVoiceVolume(item);
273 }));
274
275 mActions.addAction(
276 AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
277 std::string("createAudioPatch"),
278 std::make_shared<AnalyticsActions::Function>(
279 [this](const std::shared_ptr<const android::mediametrics::Item> &item){
280 mAudioPowerUsage.checkCreatePatch(item);
281 }));
Andy Hung06f3aba2019-12-03 16:36:42 -0800282}
283
284AudioAnalytics::~AudioAnalytics()
285{
286 ALOGD("%s", __func__);
Andy Hungce9b6632020-04-28 20:15:17 -0700287 mTimedAction.quit(); // ensure no deferred access during destructor.
Andy Hung06f3aba2019-12-03 16:36:42 -0800288}
289
290status_t AudioAnalytics::submit(
Ray Essickf27e9872019-12-07 06:28:46 -0800291 const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted)
Andy Hung06f3aba2019-12-03 16:36:42 -0800292{
Andy Hungea186fa2020-01-09 18:13:15 -0800293 if (!startsWith(item->getKey(), AMEDIAMETRICS_KEY_PREFIX_AUDIO)) return BAD_VALUE;
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800294 status_t status = mAnalyticsState->submit(item, isTrusted);
295 if (status != NO_ERROR) return status; // may not be permitted.
296
297 // Only if the item was successfully submitted (permission)
298 // do we check triggered actions.
299 checkActions(item);
300 return NO_ERROR;
Andy Hung06f3aba2019-12-03 16:36:42 -0800301}
302
Andy Hung709b91e2020-04-04 14:23:36 -0700303std::pair<std::string, int32_t> AudioAnalytics::dump(
304 int32_t lines, int64_t sinceNs, const char *prefix) const
Andy Hung06f3aba2019-12-03 16:36:42 -0800305{
306 std::stringstream ss;
307 int32_t ll = lines;
308
309 if (ll > 0) {
Andy Hung709b91e2020-04-04 14:23:36 -0700310 auto [s, l] = mAnalyticsState->dump(ll, sinceNs, prefix);
Andy Hungb744faf2020-04-09 13:09:26 -0700311 ss << s;
Andy Hung06f3aba2019-12-03 16:36:42 -0800312 ll -= l;
313 }
314 if (ll > 0) {
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800315 ss << "Prior audioserver state:\n";
Andy Hung06f3aba2019-12-03 16:36:42 -0800316 --ll;
317 }
318 if (ll > 0) {
Andy Hung709b91e2020-04-04 14:23:36 -0700319 auto [s, l] = mPreviousAnalyticsState->dump(ll, sinceNs, prefix);
Andy Hungb744faf2020-04-09 13:09:26 -0700320 ss << s;
Andy Hung06f3aba2019-12-03 16:36:42 -0800321 ll -= l;
322 }
Joey Poomarin52989982020-03-05 17:40:49 +0800323
Andy Hunga629bd12020-06-05 16:03:53 -0700324 if (ll > 0) {
325 // Print the statsd atoms we sent out.
326 const std::string statsd = mStatsdLog.dumpToString(" " /* prefix */, ll - 1);
327 const size_t n = std::count(statsd.begin(), statsd.end(), '\n') + 1; // we control this.
328 if ((size_t)ll >= n) {
329 if (n == 1) {
330 ss << "Statsd atoms: empty or truncated\n";
331 } else {
332 ss << "Statsd atoms:\n" << statsd;
333 }
334 ll -= n;
335 }
336 }
337
Joey Poomarin52989982020-03-05 17:40:49 +0800338 if (ll > 0 && prefix == nullptr) {
339 auto [s, l] = mAudioPowerUsage.dump(ll);
340 ss << s;
341 ll -= l;
342 }
Andy Hunga629bd12020-06-05 16:03:53 -0700343
Andy Hung06f3aba2019-12-03 16:36:42 -0800344 return { ss.str(), lines - ll };
345}
346
Andy Hung0f7ad8c2020-01-03 13:24:34 -0800347void AudioAnalytics::checkActions(const std::shared_ptr<const mediametrics::Item>& item)
348{
349 auto actions = mActions.getActionsForItem(item); // internally locked.
350 // Execute actions with no lock held.
351 for (const auto& action : actions) {
352 (*action)(item);
353 }
354}
355
Andy Hungea186fa2020-01-09 18:13:15 -0800356// HELPER METHODS
357
358std::string AudioAnalytics::getThreadFromTrack(const std::string& track) const
359{
360 int32_t threadId_int32{};
361 if (mAnalyticsState->timeMachine().get(
362 track, AMEDIAMETRICS_PROP_THREADID, &threadId_int32) != NO_ERROR) {
363 return {};
364 }
365 return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(threadId_int32);
366}
367
Andy Hungce9b6632020-04-28 20:15:17 -0700368// DeviceUse helper class.
369void AudioAnalytics::DeviceUse::endAudioIntervalGroup(
Andy Hungea840382020-05-05 21:50:17 -0700370 const std::shared_ptr<const android::mediametrics::Item> &item, ItemType itemType) const {
Andy Hungce9b6632020-04-28 20:15:17 -0700371 const std::string& key = item->getKey();
372 const std::string id = key.substr(
Andy Hungea840382020-05-05 21:50:17 -0700373 (itemType == THREAD ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD)
374 : itemType == TRACK ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
375 : sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD))
Andy Hungce9b6632020-04-28 20:15:17 -0700376 - 1);
377 // deliver statistics
378 int64_t deviceTimeNs = 0;
379 mAudioAnalytics.mAnalyticsState->timeMachine().get(
380 key, AMEDIAMETRICS_PROP_DEVICETIMENS, &deviceTimeNs);
381 std::string encoding;
382 mAudioAnalytics.mAnalyticsState->timeMachine().get(
383 key, AMEDIAMETRICS_PROP_ENCODING, &encoding);
384 int32_t frameCount = 0;
385 mAudioAnalytics.mAnalyticsState->timeMachine().get(
386 key, AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount);
Andy Hung1ea842e2020-05-18 10:47:31 -0700387 std::string inputDevicePairs;
Andy Hungea840382020-05-05 21:50:17 -0700388 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hung1ea842e2020-05-18 10:47:31 -0700389 key, AMEDIAMETRICS_PROP_INPUTDEVICES, &inputDevicePairs);
Andy Hungce9b6632020-04-28 20:15:17 -0700390 int32_t intervalCount = 0;
391 mAudioAnalytics.mAnalyticsState->timeMachine().get(
392 key, AMEDIAMETRICS_PROP_INTERVALCOUNT, &intervalCount);
Andy Hung1ea842e2020-05-18 10:47:31 -0700393 std::string outputDevicePairs;
Andy Hungce9b6632020-04-28 20:15:17 -0700394 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hung1ea842e2020-05-18 10:47:31 -0700395 key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevicePairs);
Andy Hungce9b6632020-04-28 20:15:17 -0700396 int32_t sampleRate = 0;
397 mAudioAnalytics.mAnalyticsState->timeMachine().get(
398 key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
Andy Hungea840382020-05-05 21:50:17 -0700399 std::string flags;
Andy Hungce9b6632020-04-28 20:15:17 -0700400 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hungea840382020-05-05 21:50:17 -0700401 key, AMEDIAMETRICS_PROP_FLAGS, &flags);
Andy Hung1ea842e2020-05-18 10:47:31 -0700402
Andy Hungea840382020-05-05 21:50:17 -0700403 // We may have several devices.
Andy Hung1ea842e2020-05-18 10:47:31 -0700404 // Accumulate the bit flags for input and output devices.
405 std::stringstream oss;
406 long_enum_type_t outputDeviceBits{};
407 { // compute outputDevices
408 const auto devaddrvec = stringutils::getDeviceAddressPairs(outputDevicePairs);
Andy Hungea840382020-05-05 21:50:17 -0700409 for (const auto& [device, addr] : devaddrvec) {
Andy Hung1ea842e2020-05-18 10:47:31 -0700410 if (oss.tellp() > 0) oss << "|"; // delimit devices with '|'.
411 oss << device;
412 outputDeviceBits += types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(device);
Andy Hungea840382020-05-05 21:50:17 -0700413 }
414 }
Andy Hung1ea842e2020-05-18 10:47:31 -0700415 const std::string outputDevices = oss.str();
416
417 std::stringstream iss;
418 long_enum_type_t inputDeviceBits{};
419 { // compute inputDevices
420 const auto devaddrvec = stringutils::getDeviceAddressPairs(inputDevicePairs);
421 for (const auto& [device, addr] : devaddrvec) {
422 if (iss.tellp() > 0) iss << "|"; // delimit devices with '|'.
423 iss << device;
424 inputDeviceBits += types::lookup<types::INPUT_DEVICE, long_enum_type_t>(device);
425 }
426 }
427 const std::string inputDevices = iss.str();
Andy Hungce9b6632020-04-28 20:15:17 -0700428
429 // Get connected device name if from bluetooth.
430 bool isBluetooth = false;
Andy Hunga629bd12020-06-05 16:03:53 -0700431
432 std::string inputDeviceNames; // not filled currently.
433 std::string outputDeviceNames;
Andy Hungce9b6632020-04-28 20:15:17 -0700434 if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos) {
435 isBluetooth = true;
436 mAudioAnalytics.mAnalyticsState->timeMachine().get(
Andy Hunga629bd12020-06-05 16:03:53 -0700437 "audio.device.bt_a2dp", AMEDIAMETRICS_PROP_NAME, &outputDeviceNames);
Andy Hung1ea842e2020-05-18 10:47:31 -0700438 // Remove | if present
Andy Hunga629bd12020-06-05 16:03:53 -0700439 stringutils::replace(outputDeviceNames, "|", '?');
440 if (outputDeviceNames.size() > STATSD_DEVICE_NAME_MAX_LENGTH) {
441 outputDeviceNames.resize(STATSD_DEVICE_NAME_MAX_LENGTH); // truncate
442 }
Andy Hungce9b6632020-04-28 20:15:17 -0700443 }
444
Andy Hungea840382020-05-05 21:50:17 -0700445 switch (itemType) {
446 case RECORD: {
447 std::string callerName;
Andy Hunga629bd12020-06-05 16:03:53 -0700448 const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
449 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
Andy Hungce9b6632020-04-28 20:15:17 -0700450
Andy Hungea840382020-05-05 21:50:17 -0700451 std::string packageName;
452 int64_t versionCode = 0;
453 int32_t uid = -1;
454 mAudioAnalytics.mAnalyticsState->timeMachine().get(
455 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
456 if (uid != -1) {
457 std::tie(packageName, versionCode) =
458 MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
459 }
460
461 int32_t selectedDeviceId = 0;
462 mAudioAnalytics.mAnalyticsState->timeMachine().get(
463 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
464 std::string source;
465 mAudioAnalytics.mAnalyticsState->timeMachine().get(
466 key, AMEDIAMETRICS_PROP_SOURCE, &source);
467
Andy Hung1ea842e2020-05-18 10:47:31 -0700468 const auto callerNameForStats =
469 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
470 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
471 const auto flagsForStats = types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags);
472 const auto sourceForStats = types::lookup<types::SOURCE_TYPE, short_enum_type_t>(source);
Andy Hungea840382020-05-05 21:50:17 -0700473
Andy Hunga629bd12020-06-05 16:03:53 -0700474 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700475 << " id:" << id
476 << " inputDevices:" << inputDevices << "(" << inputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700477 << ") inputDeviceNames:" << inputDeviceNames
Andy Hung1ea842e2020-05-18 10:47:31 -0700478 << " deviceTimeNs:" << deviceTimeNs
479 << " encoding:" << encoding << "(" << encodingForStats
480 << ") frameCount:" << frameCount
481 << " intervalCount:" << intervalCount
482 << " sampleRate:" << sampleRate
483 << " flags:" << flags << "(" << flagsForStats
484 << ") packageName:" << packageName
485 << " selectedDeviceId:" << selectedDeviceId
486 << " callerName:" << callerName << "(" << callerNameForStats
487 << ") source:" << source << "(" << sourceForStats << ")";
Andy Hunga629bd12020-06-05 16:03:53 -0700488 if (clientCalled // only log if client app called AudioRecord.
489 && mAudioAnalytics.mDeliverStatistics) {
490 const auto [ result, str ] = sendToStatsd(AudioRecordDeviceUsageFields,
491 CONDITION(android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700492 , ENUM_EXTRACT(inputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700493 , inputDeviceNames.c_str()
Andy Hungea840382020-05-05 21:50:17 -0700494 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700495 , ENUM_EXTRACT(encodingForStats)
Andy Hungea840382020-05-05 21:50:17 -0700496 , frameCount
497 , intervalCount
498 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700499 , ENUM_EXTRACT(flagsForStats)
Andy Hungea840382020-05-05 21:50:17 -0700500
501 , packageName.c_str()
502 , selectedDeviceId
Andy Hung1ea842e2020-05-18 10:47:31 -0700503 , ENUM_EXTRACT(callerNameForStats)
504 , ENUM_EXTRACT(sourceForStats)
Andy Hungea840382020-05-05 21:50:17 -0700505 );
Andy Hunga629bd12020-06-05 16:03:53 -0700506 ALOGV("%s: statsd %s", __func__, str.c_str());
507 mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
Andy Hungea840382020-05-05 21:50:17 -0700508 }
Andy Hungea840382020-05-05 21:50:17 -0700509 } break;
510 case THREAD: {
511 std::string type;
512 mAudioAnalytics.mAnalyticsState->timeMachine().get(
513 key, AMEDIAMETRICS_PROP_TYPE, &type);
514 int32_t underrun = 0; // zero for record types
515 mAudioAnalytics.mAnalyticsState->timeMachine().get(
516 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
Andy Hung1ea842e2020-05-18 10:47:31 -0700517
518 const bool isInput = types::isInputThreadType(type);
519 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
520 const auto flagsForStats =
521 (isInput ? types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags)
522 : types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags));
523 const auto typeForStats = types::lookup<types::THREAD_TYPE, short_enum_type_t>(type);
524
Andy Hunga629bd12020-06-05 16:03:53 -0700525 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700526 << " id:" << id
527 << " inputDevices:" << inputDevices << "(" << inputDeviceBits
528 << ") outputDevices:" << outputDevices << "(" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700529 << ") inputDeviceNames:" << inputDeviceNames
530 << " outputDeviceNames:" << outputDeviceNames
Andy Hung1ea842e2020-05-18 10:47:31 -0700531 << " deviceTimeNs:" << deviceTimeNs
532 << " encoding:" << encoding << "(" << encodingForStats
533 << ") frameCount:" << frameCount
534 << " intervalCount:" << intervalCount
535 << " sampleRate:" << sampleRate
536 << " underrun:" << underrun
537 << " flags:" << flags << "(" << flagsForStats
538 << ") type:" << type << "(" << typeForStats
539 << ")";
Andy Hungea840382020-05-05 21:50:17 -0700540 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -0700541 const auto [ result, str ] = sendToStatsd(AudioThreadDeviceUsageFields,
542 CONDITION(android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
543 , isInput ? ENUM_EXTRACT(inputDeviceBits) : ENUM_EXTRACT(outputDeviceBits)
544 , isInput ? inputDeviceNames.c_str() : outputDeviceNames.c_str()
Andy Hungea840382020-05-05 21:50:17 -0700545 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700546 , ENUM_EXTRACT(encodingForStats)
Andy Hungea840382020-05-05 21:50:17 -0700547 , frameCount
548 , intervalCount
549 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700550 , ENUM_EXTRACT(flagsForStats)
Andy Hungea840382020-05-05 21:50:17 -0700551 , underrun
Andy Hung1ea842e2020-05-18 10:47:31 -0700552 , ENUM_EXTRACT(typeForStats)
Andy Hungea840382020-05-05 21:50:17 -0700553 );
Andy Hunga629bd12020-06-05 16:03:53 -0700554 ALOGV("%s: statsd %s", __func__, str.c_str());
555 mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
Andy Hungea840382020-05-05 21:50:17 -0700556 }
Andy Hungea840382020-05-05 21:50:17 -0700557 } break;
558 case TRACK: {
Andy Hungce9b6632020-04-28 20:15:17 -0700559 std::string callerName;
Andy Hunga629bd12020-06-05 16:03:53 -0700560 const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
561 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
562
Andy Hungce9b6632020-04-28 20:15:17 -0700563 std::string contentType;
564 mAudioAnalytics.mAnalyticsState->timeMachine().get(
565 key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentType);
566 double deviceLatencyMs = 0.;
567 mAudioAnalytics.mAnalyticsState->timeMachine().get(
568 key, AMEDIAMETRICS_PROP_DEVICELATENCYMS, &deviceLatencyMs);
569 double deviceStartupMs = 0.;
570 mAudioAnalytics.mAnalyticsState->timeMachine().get(
571 key, AMEDIAMETRICS_PROP_DEVICESTARTUPMS, &deviceStartupMs);
572 double deviceVolume = 0.;
573 mAudioAnalytics.mAnalyticsState->timeMachine().get(
574 key, AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume);
575 std::string packageName;
576 int64_t versionCode = 0;
577 int32_t uid = -1;
578 mAudioAnalytics.mAnalyticsState->timeMachine().get(
579 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
580 if (uid != -1) {
581 std::tie(packageName, versionCode) =
582 MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
583 }
584 double playbackPitch = 0.;
585 mAudioAnalytics.mAnalyticsState->timeMachine().get(
586 key, AMEDIAMETRICS_PROP_PLAYBACK_PITCH, &playbackPitch);
587 double playbackSpeed = 0.;
588 mAudioAnalytics.mAnalyticsState->timeMachine().get(
589 key, AMEDIAMETRICS_PROP_PLAYBACK_SPEED, &playbackSpeed);
590 int32_t selectedDeviceId = 0;
591 mAudioAnalytics.mAnalyticsState->timeMachine().get(
592 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
Andy Hungea840382020-05-05 21:50:17 -0700593 std::string streamType;
594 mAudioAnalytics.mAnalyticsState->timeMachine().get(
595 key, AMEDIAMETRICS_PROP_STREAMTYPE, &streamType);
Andy Hunga629bd12020-06-05 16:03:53 -0700596 std::string traits;
597 mAudioAnalytics.mAnalyticsState->timeMachine().get(
598 key, AMEDIAMETRICS_PROP_TRAITS, &traits);
Andy Hungea840382020-05-05 21:50:17 -0700599 int32_t underrun = 0;
600 mAudioAnalytics.mAnalyticsState->timeMachine().get(
601 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
Andy Hungce9b6632020-04-28 20:15:17 -0700602 std::string usage;
603 mAudioAnalytics.mAnalyticsState->timeMachine().get(
604 key, AMEDIAMETRICS_PROP_USAGE, &usage);
605
Andy Hung1ea842e2020-05-18 10:47:31 -0700606 const auto callerNameForStats =
607 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
608 const auto contentTypeForStats =
609 types::lookup<types::CONTENT_TYPE, short_enum_type_t>(contentType);
610 const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
611 const auto flagsForStats = types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags);
612 const auto streamTypeForStats =
613 types::lookup<types::STREAM_TYPE, short_enum_type_t>(streamType);
Andy Hunga629bd12020-06-05 16:03:53 -0700614 const auto traitsForStats =
615 types::lookup<types::TRACK_TRAITS, short_enum_type_t>(traits);
Andy Hung1ea842e2020-05-18 10:47:31 -0700616 const auto usageForStats = types::lookup<types::USAGE, short_enum_type_t>(usage);
617
Andy Hunga629bd12020-06-05 16:03:53 -0700618 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700619 << " id:" << id
620 << " outputDevices:" << outputDevices << "(" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700621 << ") outputDeviceNames:" << outputDeviceNames
Andy Hung1ea842e2020-05-18 10:47:31 -0700622 << " deviceTimeNs:" << deviceTimeNs
623 << " encoding:" << encoding << "(" << encodingForStats
624 << ") frameCount:" << frameCount
625 << " intervalCount:" << intervalCount
626 << " sampleRate:" << sampleRate
627 << " underrun:" << underrun
628 << " flags:" << flags << "(" << flagsForStats
629 << ") callerName:" << callerName << "(" << callerNameForStats
630 << ") contentType:" << contentType << "(" << contentTypeForStats
631 << ") deviceLatencyMs:" << deviceLatencyMs
632 << " deviceStartupMs:" << deviceStartupMs
633 << " deviceVolume:" << deviceVolume
634 << " packageName:" << packageName
635 << " playbackPitch:" << playbackPitch
636 << " playbackSpeed:" << playbackSpeed
637 << " selectedDeviceId:" << selectedDeviceId
638 << " streamType:" << streamType << "(" << streamTypeForStats
Andy Hunga629bd12020-06-05 16:03:53 -0700639 << ") traits:" << traits << "(" << traitsForStats
Andy Hung1ea842e2020-05-18 10:47:31 -0700640 << ") usage:" << usage << "(" << usageForStats
641 << ")";
Andy Hunga629bd12020-06-05 16:03:53 -0700642 if (clientCalled // only log if client app called AudioTracks
643 && mAudioAnalytics.mDeliverStatistics) {
644 const auto [ result, str ] = sendToStatsd(AudioTrackDeviceUsageFields,
645 CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700646 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700647 , outputDeviceNames.c_str()
Andy Hungce9b6632020-04-28 20:15:17 -0700648 , deviceTimeNs
Andy Hung1ea842e2020-05-18 10:47:31 -0700649 , ENUM_EXTRACT(encodingForStats)
Andy Hungce9b6632020-04-28 20:15:17 -0700650 , frameCount
651 , intervalCount
652 , sampleRate
Andy Hung1ea842e2020-05-18 10:47:31 -0700653 , ENUM_EXTRACT(flagsForStats)
Andy Hungce9b6632020-04-28 20:15:17 -0700654 , underrun
Andy Hungce9b6632020-04-28 20:15:17 -0700655 , packageName.c_str()
656 , (float)deviceLatencyMs
657 , (float)deviceStartupMs
658 , (float)deviceVolume
659 , selectedDeviceId
Andy Hung1ea842e2020-05-18 10:47:31 -0700660 , ENUM_EXTRACT(streamTypeForStats)
661 , ENUM_EXTRACT(usageForStats)
662 , ENUM_EXTRACT(contentTypeForStats)
663 , ENUM_EXTRACT(callerNameForStats)
Andy Hunga629bd12020-06-05 16:03:53 -0700664 , ENUM_EXTRACT(traitsForStats)
Andy Hungce9b6632020-04-28 20:15:17 -0700665 );
Andy Hunga629bd12020-06-05 16:03:53 -0700666 ALOGV("%s: statsd %s", __func__, str.c_str());
667 mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
Andy Hungce9b6632020-04-28 20:15:17 -0700668 }
Andy Hungea840382020-05-05 21:50:17 -0700669 } break;
Andy Hungce9b6632020-04-28 20:15:17 -0700670 }
671
672 // Report this as needed.
673 if (isBluetooth) {
674 // report this for Bluetooth
675 }
676}
677
678// DeviceConnection helper class.
679void AudioAnalytics::DeviceConnection::a2dpConnected(
680 const std::shared_ptr<const android::mediametrics::Item> &item) {
681 const std::string& key = item->getKey();
Andy Hungea840382020-05-05 21:50:17 -0700682 const int64_t atNs = item->getTimestamp();
Andy Hungce9b6632020-04-28 20:15:17 -0700683 {
684 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -0700685 mA2dpConnectionServiceNs = atNs;
686 ++mA2dpConnectionServices;
687
688 if (mA2dpConnectionRequestNs == 0) {
689 mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
690 }
691 // This sets the time we were connected. Now we look for the delta in the future.
Andy Hungce9b6632020-04-28 20:15:17 -0700692 }
693 std::string name;
694 item->get(AMEDIAMETRICS_PROP_NAME, &name);
Andy Hungea840382020-05-05 21:50:17 -0700695 ALOGD("(key=%s) a2dp connected device:%s atNs:%lld",
696 key.c_str(), name.c_str(), (long long)atNs);
Andy Hungce9b6632020-04-28 20:15:17 -0700697}
698
699void AudioAnalytics::DeviceConnection::createPatch(
700 const std::shared_ptr<const android::mediametrics::Item> &item) {
701 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -0700702 if (mA2dpConnectionServiceNs == 0) return; // patch unrelated to us.
Andy Hungce9b6632020-04-28 20:15:17 -0700703 const std::string& key = item->getKey();
704 std::string outputDevices;
705 item->get(AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices);
Andy Hungea840382020-05-05 21:50:17 -0700706 if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH_A2DP") != std::string::npos) {
Andy Hungce9b6632020-04-28 20:15:17 -0700707 // TODO compare address
Andy Hung1ea842e2020-05-18 10:47:31 -0700708 int64_t timeDiffNs = item->getTimestamp();
Andy Hungea840382020-05-05 21:50:17 -0700709 if (mA2dpConnectionRequestNs == 0) {
710 ALOGD("%s: A2DP create patch didn't see a connection request", __func__);
Andy Hung1ea842e2020-05-18 10:47:31 -0700711 timeDiffNs -= mA2dpConnectionServiceNs;
Andy Hungea840382020-05-05 21:50:17 -0700712 } else {
Andy Hung1ea842e2020-05-18 10:47:31 -0700713 timeDiffNs -= mA2dpConnectionRequestNs;
Andy Hungea840382020-05-05 21:50:17 -0700714 }
Andy Hung1ea842e2020-05-18 10:47:31 -0700715
Andy Hungea840382020-05-05 21:50:17 -0700716 mA2dpConnectionRequestNs = 0;
717 mA2dpConnectionServiceNs = 0;
718 ++mA2dpConnectionSuccesses;
719
Andy Hung1ea842e2020-05-18 10:47:31 -0700720 const auto connectionTimeMs = float(timeDiffNs * 1e-6);
721
722 const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
723 "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
724
Andy Hunga629bd12020-06-05 16:03:53 -0700725 LOG(LOG_LEVEL) << "key:" << key
Andy Hung1ea842e2020-05-18 10:47:31 -0700726 << " A2DP SUCCESS"
727 << " outputDevices:" << outputDeviceBits
Andy Hunga629bd12020-06-05 16:03:53 -0700728 << " deviceName:" << mA2dpDeviceName
Andy Hung1ea842e2020-05-18 10:47:31 -0700729 << " connectionTimeMs:" << connectionTimeMs;
Andy Hungea840382020-05-05 21:50:17 -0700730 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hung1ea842e2020-05-18 10:47:31 -0700731 const long_enum_type_t inputDeviceBits{};
Andy Hunga629bd12020-06-05 16:03:53 -0700732
733 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
734 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700735 , ENUM_EXTRACT(inputDeviceBits)
736 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700737 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -0700738 , types::DEVICE_CONNECTION_RESULT_SUCCESS
739 , connectionTimeMs
Andy Hungea840382020-05-05 21:50:17 -0700740 , /* connection_count */ 1
741 );
Andy Hunga629bd12020-06-05 16:03:53 -0700742 ALOGV("%s: statsd %s", __func__, str.c_str());
743 mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
Andy Hungea840382020-05-05 21:50:17 -0700744 }
Andy Hungce9b6632020-04-28 20:15:17 -0700745 }
746}
747
Andy Hungea840382020-05-05 21:50:17 -0700748// Called through AudioManager when the BT service wants to enable
749void AudioAnalytics::DeviceConnection::postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
750 const std::shared_ptr<const android::mediametrics::Item> &item) {
751 const int64_t atNs = item->getTimestamp();
752 const std::string& key = item->getKey();
753 std::string state;
754 item->get(AMEDIAMETRICS_PROP_STATE, &state);
755 if (state != "connected") return;
Andy Hunga629bd12020-06-05 16:03:53 -0700756
757 std::string name;
758 item->get(AMEDIAMETRICS_PROP_NAME, &name);
Andy Hungea840382020-05-05 21:50:17 -0700759 {
760 std::lock_guard l(mLock);
761 mA2dpConnectionRequestNs = atNs;
762 ++mA2dpConnectionRequests;
Andy Hunga629bd12020-06-05 16:03:53 -0700763 mA2dpDeviceName = name;
Andy Hungea840382020-05-05 21:50:17 -0700764 }
Andy Hunga629bd12020-06-05 16:03:53 -0700765 ALOGD("(key=%s) a2dp connection name:%s request atNs:%lld",
766 key.c_str(), name.c_str(), (long long)atNs);
Andy Hungea840382020-05-05 21:50:17 -0700767 // TODO: attempt to cancel a timed event, rather than let it expire.
768 mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
769}
770
Andy Hungce9b6632020-04-28 20:15:17 -0700771void AudioAnalytics::DeviceConnection::expire() {
772 std::lock_guard l(mLock);
Andy Hungea840382020-05-05 21:50:17 -0700773 if (mA2dpConnectionRequestNs == 0) return; // ignore (this was an internal connection).
Andy Hung1ea842e2020-05-18 10:47:31 -0700774
Andy Hung1ea842e2020-05-18 10:47:31 -0700775 const long_enum_type_t inputDeviceBits{};
Andy Hung1ea842e2020-05-18 10:47:31 -0700776 const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
777 "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
778
Andy Hungea840382020-05-05 21:50:17 -0700779 if (mA2dpConnectionServiceNs == 0) {
Andy Hungea840382020-05-05 21:50:17 -0700780 ++mA2dpConnectionJavaServiceCancels; // service did not connect to A2DP
Andy Hungce9b6632020-04-28 20:15:17 -0700781
Andy Hunga629bd12020-06-05 16:03:53 -0700782 LOG(LOG_LEVEL) << "A2DP CANCEL"
783 << " outputDevices:" << outputDeviceBits
784 << " deviceName:" << mA2dpDeviceName;
Andy Hungea840382020-05-05 21:50:17 -0700785 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -0700786 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
787 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700788 , ENUM_EXTRACT(inputDeviceBits)
789 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700790 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -0700791 , types::DEVICE_CONNECTION_RESULT_JAVA_SERVICE_CANCEL
Andy Hungea840382020-05-05 21:50:17 -0700792 , /* connection_time_ms */ 0.f
793 , /* connection_count */ 1
794 );
Andy Hunga629bd12020-06-05 16:03:53 -0700795 ALOGV("%s: statsd %s", __func__, str.c_str());
796 mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
Andy Hungea840382020-05-05 21:50:17 -0700797 }
Andy Hungea840382020-05-05 21:50:17 -0700798 return;
799 }
800
801 // AudioFlinger didn't play - an expiration may occur because there is no audio playing.
802 // Should we check elsewhere?
Andy Hungce9b6632020-04-28 20:15:17 -0700803 // TODO: disambiguate this case.
Andy Hungea840382020-05-05 21:50:17 -0700804 mA2dpConnectionRequestNs = 0;
805 mA2dpConnectionServiceNs = 0;
806 ++mA2dpConnectionUnknowns; // connection result unknown
Andy Hung1ea842e2020-05-18 10:47:31 -0700807
Andy Hunga629bd12020-06-05 16:03:53 -0700808 LOG(LOG_LEVEL) << "A2DP UNKNOWN"
809 << " outputDevices:" << outputDeviceBits
810 << " deviceName:" << mA2dpDeviceName;
Andy Hungea840382020-05-05 21:50:17 -0700811 if (mAudioAnalytics.mDeliverStatistics) {
Andy Hunga629bd12020-06-05 16:03:53 -0700812 const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
813 CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
Andy Hung1ea842e2020-05-18 10:47:31 -0700814 , ENUM_EXTRACT(inputDeviceBits)
815 , ENUM_EXTRACT(outputDeviceBits)
Andy Hunga629bd12020-06-05 16:03:53 -0700816 , mA2dpDeviceName.c_str()
Andy Hung1ea842e2020-05-18 10:47:31 -0700817 , types::DEVICE_CONNECTION_RESULT_UNKNOWN
Andy Hungea840382020-05-05 21:50:17 -0700818 , /* connection_time_ms */ 0.f
819 , /* connection_count */ 1
820 );
Andy Hunga629bd12020-06-05 16:03:53 -0700821 ALOGV("%s: statsd %s", __func__, str.c_str());
822 mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
Andy Hungea840382020-05-05 21:50:17 -0700823 }
Andy Hungce9b6632020-04-28 20:15:17 -0700824}
825
Andy Hung3ab1b322020-05-18 10:47:31 -0700826} // namespace android::mediametrics