xref: /aosp_15_r20/frameworks/av/services/mediametrics/AudioAnalytics.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "AudioAnalytics"
19*ec779b8eSAndroid Build Coastguard Worker #include <android-base/logging.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
21*ec779b8eSAndroid Build Coastguard Worker 
22*ec779b8eSAndroid Build Coastguard Worker #include "AudioAnalytics.h"
23*ec779b8eSAndroid Build Coastguard Worker 
24*ec779b8eSAndroid Build Coastguard Worker #include <aaudio/AAudio.h>        // error codes
25*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/clock.h>    // clock conversions
26*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <stats_media_metrics.h>             // statsd
28*ec779b8eSAndroid Build Coastguard Worker #include <system/audio.h>
29*ec779b8eSAndroid Build Coastguard Worker 
30*ec779b8eSAndroid Build Coastguard Worker #include "AudioTypes.h"           // string to int conversions
31*ec779b8eSAndroid Build Coastguard Worker #include "MediaMetricsService.h"  // package info
32*ec779b8eSAndroid Build Coastguard Worker #include "StringUtils.h"
33*ec779b8eSAndroid Build Coastguard Worker #include "ValidateId.h"
34*ec779b8eSAndroid Build Coastguard Worker 
35*ec779b8eSAndroid Build Coastguard Worker #define PROP_AUDIO_ANALYTICS_CLOUD_ENABLED "persist.audio.analytics.cloud.enabled"
36*ec779b8eSAndroid Build Coastguard Worker 
37*ec779b8eSAndroid Build Coastguard Worker namespace android::mediametrics {
38*ec779b8eSAndroid Build Coastguard Worker 
39*ec779b8eSAndroid Build Coastguard Worker // Enable for testing of delivery to statsd. Caution if this is enabled, all protos MUST exist.
40*ec779b8eSAndroid Build Coastguard Worker #define STATSD_ENABLE
41*ec779b8eSAndroid Build Coastguard Worker 
42*ec779b8eSAndroid Build Coastguard Worker #ifdef STATSD_ENABLE
43*ec779b8eSAndroid Build Coastguard Worker #define CONDITION(INT_VALUE) (INT_VALUE)  // allow value
44*ec779b8eSAndroid Build Coastguard Worker #else
45*ec779b8eSAndroid Build Coastguard Worker #define CONDITION(INT_VALUE) (int(0))     // mask value since the proto may not be defined yet.
46*ec779b8eSAndroid Build Coastguard Worker #endif
47*ec779b8eSAndroid Build Coastguard Worker 
48*ec779b8eSAndroid Build Coastguard Worker // Maximum length of a device name.
49*ec779b8eSAndroid Build Coastguard Worker // static constexpr size_t STATSD_DEVICE_NAME_MAX_LENGTH = 32; // unused since we suppress
50*ec779b8eSAndroid Build Coastguard Worker 
51*ec779b8eSAndroid Build Coastguard Worker // Transmit Enums to statsd in integer or strings  (this must match the atoms.proto)
52*ec779b8eSAndroid Build Coastguard Worker static constexpr bool STATSD_USE_INT_FOR_ENUM = false;
53*ec779b8eSAndroid Build Coastguard Worker 
54*ec779b8eSAndroid Build Coastguard Worker // derive types based on integer or strings.
55*ec779b8eSAndroid Build Coastguard Worker using short_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int32_t, std::string>;
56*ec779b8eSAndroid Build Coastguard Worker using long_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int64_t, std::string>;
57*ec779b8eSAndroid Build Coastguard Worker 
58*ec779b8eSAndroid Build Coastguard Worker // Convert std::string to char *
59*ec779b8eSAndroid Build Coastguard Worker template <typename T>
ENUM_EXTRACT(const T & x)60*ec779b8eSAndroid Build Coastguard Worker auto ENUM_EXTRACT(const T& x) {
61*ec779b8eSAndroid Build Coastguard Worker     if constexpr (std::is_same_v<std::decay_t<T>, std::string>) {
62*ec779b8eSAndroid Build Coastguard Worker         return x.c_str();
63*ec779b8eSAndroid Build Coastguard Worker     } else {
64*ec779b8eSAndroid Build Coastguard Worker         return x;
65*ec779b8eSAndroid Build Coastguard Worker     }
66*ec779b8eSAndroid Build Coastguard Worker }
67*ec779b8eSAndroid Build Coastguard Worker 
68*ec779b8eSAndroid Build Coastguard Worker // The status variable contains status_t codes which are used by
69*ec779b8eSAndroid Build Coastguard Worker // the core audio framework. We also consider AAudio status codes.
70*ec779b8eSAndroid Build Coastguard Worker //
71*ec779b8eSAndroid Build Coastguard Worker // Compare with mediametrics::statusToStatusString
72*ec779b8eSAndroid Build Coastguard Worker //
extendedStatusToStatusString(status_t status)73*ec779b8eSAndroid Build Coastguard Worker inline constexpr const char* extendedStatusToStatusString(status_t status) {
74*ec779b8eSAndroid Build Coastguard Worker     switch (status) {
75*ec779b8eSAndroid Build Coastguard Worker     case BAD_VALUE:           // status_t
76*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
77*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_INVALID_FORMAT:
78*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_INVALID_RATE:
79*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_NULL:
80*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_OUT_OF_RANGE:
81*ec779b8eSAndroid Build Coastguard Worker         return AMEDIAMETRICS_PROP_STATUS_VALUE_ARGUMENT;
82*ec779b8eSAndroid Build Coastguard Worker     case DEAD_OBJECT:         // status_t
83*ec779b8eSAndroid Build Coastguard Worker     case FAILED_TRANSACTION:  // status_t
84*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_DISCONNECTED:
85*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_INVALID_HANDLE:
86*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_NO_SERVICE:
87*ec779b8eSAndroid Build Coastguard Worker         return AMEDIAMETRICS_PROP_STATUS_VALUE_IO;
88*ec779b8eSAndroid Build Coastguard Worker     case NO_MEMORY:           // status_t
89*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_NO_FREE_HANDLES:
90*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_NO_MEMORY:
91*ec779b8eSAndroid Build Coastguard Worker         return AMEDIAMETRICS_PROP_STATUS_VALUE_MEMORY;
92*ec779b8eSAndroid Build Coastguard Worker     case PERMISSION_DENIED:   // status_t
93*ec779b8eSAndroid Build Coastguard Worker         return AMEDIAMETRICS_PROP_STATUS_VALUE_SECURITY;
94*ec779b8eSAndroid Build Coastguard Worker     case INVALID_OPERATION:   // status_t
95*ec779b8eSAndroid Build Coastguard Worker     case NO_INIT:             // status_t
96*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_INVALID_STATE:
97*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_UNAVAILABLE:
98*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_UNIMPLEMENTED:
99*ec779b8eSAndroid Build Coastguard Worker         return AMEDIAMETRICS_PROP_STATUS_VALUE_STATE;
100*ec779b8eSAndroid Build Coastguard Worker     case WOULD_BLOCK:         // status_t
101*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_TIMEOUT:
102*ec779b8eSAndroid Build Coastguard Worker     case AAUDIO_ERROR_WOULD_BLOCK:
103*ec779b8eSAndroid Build Coastguard Worker         return AMEDIAMETRICS_PROP_STATUS_VALUE_TIMEOUT;
104*ec779b8eSAndroid Build Coastguard Worker     default:
105*ec779b8eSAndroid Build Coastguard Worker         if (status >= 0) return AMEDIAMETRICS_PROP_STATUS_VALUE_OK; // non-negative values "OK"
106*ec779b8eSAndroid Build Coastguard Worker         [[fallthrough]];            // negative values are error.
107*ec779b8eSAndroid Build Coastguard Worker     case UNKNOWN_ERROR:       // status_t
108*ec779b8eSAndroid Build Coastguard Worker         return AMEDIAMETRICS_PROP_STATUS_VALUE_UNKNOWN;
109*ec779b8eSAndroid Build Coastguard Worker     }
110*ec779b8eSAndroid Build Coastguard Worker }
111*ec779b8eSAndroid Build Coastguard Worker 
112*ec779b8eSAndroid Build Coastguard Worker static constexpr const auto LOG_LEVEL = android::base::VERBOSE;
113*ec779b8eSAndroid Build Coastguard Worker 
114*ec779b8eSAndroid Build Coastguard Worker static constexpr int PREVIOUS_STATE_EXPIRE_SEC = 60 * 60; // 1 hour.
115*ec779b8eSAndroid Build Coastguard Worker 
116*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * SUPPRESSED = "SUPPRESSED";
117*ec779b8eSAndroid Build Coastguard Worker 
118*ec779b8eSAndroid Build Coastguard Worker /*
119*ec779b8eSAndroid Build Coastguard Worker  * For logging purposes, we list all of the MediaMetrics atom fields,
120*ec779b8eSAndroid Build Coastguard Worker  * which can then be associated with consecutive arguments to the statsd write.
121*ec779b8eSAndroid Build Coastguard Worker  */
122*ec779b8eSAndroid Build Coastguard Worker 
123*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * const AudioRecordDeviceUsageFields[] = {
124*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_audiorecorddeviceusage_reported", // proto number
125*ec779b8eSAndroid Build Coastguard Worker     "devices",
126*ec779b8eSAndroid Build Coastguard Worker     "device_names",
127*ec779b8eSAndroid Build Coastguard Worker     "device_time_nanos",
128*ec779b8eSAndroid Build Coastguard Worker     "encoding",
129*ec779b8eSAndroid Build Coastguard Worker     "frame_count",
130*ec779b8eSAndroid Build Coastguard Worker     "interval_count",
131*ec779b8eSAndroid Build Coastguard Worker     "sample_rate",
132*ec779b8eSAndroid Build Coastguard Worker     "flags",
133*ec779b8eSAndroid Build Coastguard Worker     "package_name",
134*ec779b8eSAndroid Build Coastguard Worker     "selected_device_id",
135*ec779b8eSAndroid Build Coastguard Worker     "caller",
136*ec779b8eSAndroid Build Coastguard Worker     "source",
137*ec779b8eSAndroid Build Coastguard Worker     "log_session_id",
138*ec779b8eSAndroid Build Coastguard Worker };
139*ec779b8eSAndroid Build Coastguard Worker 
140*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * const AudioThreadDeviceUsageFields[] = {
141*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_audiothreaddeviceusage_reported",
142*ec779b8eSAndroid Build Coastguard Worker     "devices",
143*ec779b8eSAndroid Build Coastguard Worker     "device_names",
144*ec779b8eSAndroid Build Coastguard Worker     "device_time_nanos",
145*ec779b8eSAndroid Build Coastguard Worker     "encoding",
146*ec779b8eSAndroid Build Coastguard Worker     "frame_count",
147*ec779b8eSAndroid Build Coastguard Worker     "interval_count",
148*ec779b8eSAndroid Build Coastguard Worker     "sample_rate",
149*ec779b8eSAndroid Build Coastguard Worker     "flags",
150*ec779b8eSAndroid Build Coastguard Worker     "xruns",
151*ec779b8eSAndroid Build Coastguard Worker     "type",
152*ec779b8eSAndroid Build Coastguard Worker };
153*ec779b8eSAndroid Build Coastguard Worker 
154*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * const AudioTrackDeviceUsageFields[] = {
155*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_audiotrackdeviceusage_reported",
156*ec779b8eSAndroid Build Coastguard Worker     "devices",
157*ec779b8eSAndroid Build Coastguard Worker     "device_names",
158*ec779b8eSAndroid Build Coastguard Worker     "device_time_nanos",
159*ec779b8eSAndroid Build Coastguard Worker     "encoding",
160*ec779b8eSAndroid Build Coastguard Worker     "frame_count",
161*ec779b8eSAndroid Build Coastguard Worker     "interval_count",
162*ec779b8eSAndroid Build Coastguard Worker     "sample_rate",
163*ec779b8eSAndroid Build Coastguard Worker     "flags",
164*ec779b8eSAndroid Build Coastguard Worker     "xruns",
165*ec779b8eSAndroid Build Coastguard Worker     "package_name",
166*ec779b8eSAndroid Build Coastguard Worker     "device_latency_millis",
167*ec779b8eSAndroid Build Coastguard Worker     "device_startup_millis",
168*ec779b8eSAndroid Build Coastguard Worker     "device_volume",
169*ec779b8eSAndroid Build Coastguard Worker     "selected_device_id",
170*ec779b8eSAndroid Build Coastguard Worker     "stream_type",
171*ec779b8eSAndroid Build Coastguard Worker     "usage",
172*ec779b8eSAndroid Build Coastguard Worker     "content_type",
173*ec779b8eSAndroid Build Coastguard Worker     "caller",
174*ec779b8eSAndroid Build Coastguard Worker     "traits",
175*ec779b8eSAndroid Build Coastguard Worker     "log_session_id",
176*ec779b8eSAndroid Build Coastguard Worker };
177*ec779b8eSAndroid Build Coastguard Worker 
178*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * const AudioRecordStatusFields[] {
179*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_audiorecordstatus_reported",
180*ec779b8eSAndroid Build Coastguard Worker     "status",
181*ec779b8eSAndroid Build Coastguard Worker     "debug_message",
182*ec779b8eSAndroid Build Coastguard Worker     "status_subcode",
183*ec779b8eSAndroid Build Coastguard Worker     "uid",
184*ec779b8eSAndroid Build Coastguard Worker     "event",
185*ec779b8eSAndroid Build Coastguard Worker     "input_flags",
186*ec779b8eSAndroid Build Coastguard Worker     "source",
187*ec779b8eSAndroid Build Coastguard Worker     "encoding",
188*ec779b8eSAndroid Build Coastguard Worker     "channel_mask",
189*ec779b8eSAndroid Build Coastguard Worker     "buffer_frame_count",
190*ec779b8eSAndroid Build Coastguard Worker     "sample_rate",
191*ec779b8eSAndroid Build Coastguard Worker };
192*ec779b8eSAndroid Build Coastguard Worker 
193*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * const AudioTrackStatusFields[] {
194*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_audiotrackstatus_reported",
195*ec779b8eSAndroid Build Coastguard Worker     "status",
196*ec779b8eSAndroid Build Coastguard Worker     "debug_message",
197*ec779b8eSAndroid Build Coastguard Worker     "status_subcode",
198*ec779b8eSAndroid Build Coastguard Worker     "uid",
199*ec779b8eSAndroid Build Coastguard Worker     "event",
200*ec779b8eSAndroid Build Coastguard Worker     "output_flags",
201*ec779b8eSAndroid Build Coastguard Worker     "content_type",
202*ec779b8eSAndroid Build Coastguard Worker     "usage",
203*ec779b8eSAndroid Build Coastguard Worker     "encoding",
204*ec779b8eSAndroid Build Coastguard Worker     "channel_mask",
205*ec779b8eSAndroid Build Coastguard Worker     "buffer_frame_count",
206*ec779b8eSAndroid Build Coastguard Worker     "sample_rate",
207*ec779b8eSAndroid Build Coastguard Worker     "speed",
208*ec779b8eSAndroid Build Coastguard Worker     "pitch",
209*ec779b8eSAndroid Build Coastguard Worker };
210*ec779b8eSAndroid Build Coastguard Worker 
211*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * const AudioDeviceConnectionFields[] = {
212*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_audiodeviceconnection_reported",
213*ec779b8eSAndroid Build Coastguard Worker     "input_devices",
214*ec779b8eSAndroid Build Coastguard Worker     "output_devices",
215*ec779b8eSAndroid Build Coastguard Worker     "device_names",
216*ec779b8eSAndroid Build Coastguard Worker     "result",
217*ec779b8eSAndroid Build Coastguard Worker     "time_to_connect_millis",
218*ec779b8eSAndroid Build Coastguard Worker     "connection_count",
219*ec779b8eSAndroid Build Coastguard Worker };
220*ec779b8eSAndroid Build Coastguard Worker 
221*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * const AAudioStreamFields[] {
222*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_aaudiostream_reported",
223*ec779b8eSAndroid Build Coastguard Worker     "path",
224*ec779b8eSAndroid Build Coastguard Worker     "direction",
225*ec779b8eSAndroid Build Coastguard Worker     "frames_per_burst",
226*ec779b8eSAndroid Build Coastguard Worker     "buffer_size",
227*ec779b8eSAndroid Build Coastguard Worker     "buffer_capacity",
228*ec779b8eSAndroid Build Coastguard Worker     "channel_count",
229*ec779b8eSAndroid Build Coastguard Worker     "total_frames_transferred",
230*ec779b8eSAndroid Build Coastguard Worker     "perf_mode_requested",
231*ec779b8eSAndroid Build Coastguard Worker     "perf_mode_actual",
232*ec779b8eSAndroid Build Coastguard Worker     "sharing",
233*ec779b8eSAndroid Build Coastguard Worker     "xrun_count",
234*ec779b8eSAndroid Build Coastguard Worker     "device_type",
235*ec779b8eSAndroid Build Coastguard Worker     "format_app",
236*ec779b8eSAndroid Build Coastguard Worker     "format_device",
237*ec779b8eSAndroid Build Coastguard Worker     "log_session_id",
238*ec779b8eSAndroid Build Coastguard Worker     "sample_rate",
239*ec779b8eSAndroid Build Coastguard Worker     "content_type",
240*ec779b8eSAndroid Build Coastguard Worker     "sharing_requested",
241*ec779b8eSAndroid Build Coastguard Worker     "format_hardware",
242*ec779b8eSAndroid Build Coastguard Worker     "channel_count_hardware",
243*ec779b8eSAndroid Build Coastguard Worker     "sample_rate_hardware",
244*ec779b8eSAndroid Build Coastguard Worker     "uid",
245*ec779b8eSAndroid Build Coastguard Worker     "sample_rate_client",
246*ec779b8eSAndroid Build Coastguard Worker };
247*ec779b8eSAndroid Build Coastguard Worker 
248*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * HeadTrackerDeviceEnabledFields[] {
249*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_headtrackerdeviceenabled_reported",
250*ec779b8eSAndroid Build Coastguard Worker     "type",
251*ec779b8eSAndroid Build Coastguard Worker     "event",
252*ec779b8eSAndroid Build Coastguard Worker     "enabled",
253*ec779b8eSAndroid Build Coastguard Worker };
254*ec779b8eSAndroid Build Coastguard Worker 
255*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * HeadTrackerDeviceSupportedFields[] {
256*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_headtrackerdevicesupported_reported",
257*ec779b8eSAndroid Build Coastguard Worker     "type",
258*ec779b8eSAndroid Build Coastguard Worker     "event",
259*ec779b8eSAndroid Build Coastguard Worker     "supported",
260*ec779b8eSAndroid Build Coastguard Worker };
261*ec779b8eSAndroid Build Coastguard Worker 
262*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * SpatializerCapabilitiesFields[] {
263*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_spatializer_reported",
264*ec779b8eSAndroid Build Coastguard Worker     "head_tracking_modes",
265*ec779b8eSAndroid Build Coastguard Worker     "spatializer_levels",
266*ec779b8eSAndroid Build Coastguard Worker     "spatializer_modes",
267*ec779b8eSAndroid Build Coastguard Worker     "channel_masks",
268*ec779b8eSAndroid Build Coastguard Worker };
269*ec779b8eSAndroid Build Coastguard Worker 
270*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * SpatializerDeviceEnabledFields[] {
271*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_spatializerdeviceenabled_reported",
272*ec779b8eSAndroid Build Coastguard Worker     "type",
273*ec779b8eSAndroid Build Coastguard Worker     "event",
274*ec779b8eSAndroid Build Coastguard Worker     "enabled",
275*ec779b8eSAndroid Build Coastguard Worker };
276*ec779b8eSAndroid Build Coastguard Worker 
277*ec779b8eSAndroid Build Coastguard Worker static constexpr const char * const MidiDeviceCloseFields[] {
278*ec779b8eSAndroid Build Coastguard Worker     "mediametrics_midi_device_close_reported",
279*ec779b8eSAndroid Build Coastguard Worker     "uid",
280*ec779b8eSAndroid Build Coastguard Worker     "midi_device_id",
281*ec779b8eSAndroid Build Coastguard Worker     "input_port_count",
282*ec779b8eSAndroid Build Coastguard Worker     "output_port_count",
283*ec779b8eSAndroid Build Coastguard Worker     "device_type",
284*ec779b8eSAndroid Build Coastguard Worker     "is_shared",
285*ec779b8eSAndroid Build Coastguard Worker     "supports_ump",
286*ec779b8eSAndroid Build Coastguard Worker     "using_alsa",
287*ec779b8eSAndroid Build Coastguard Worker     "duration_ns",
288*ec779b8eSAndroid Build Coastguard Worker     "opened_count",
289*ec779b8eSAndroid Build Coastguard Worker     "closed_count",
290*ec779b8eSAndroid Build Coastguard Worker     "device_disconnected",
291*ec779b8eSAndroid Build Coastguard Worker     "total_input_bytes",
292*ec779b8eSAndroid Build Coastguard Worker     "total_output_bytes",
293*ec779b8eSAndroid Build Coastguard Worker };
294*ec779b8eSAndroid Build Coastguard Worker 
295*ec779b8eSAndroid Build Coastguard Worker /**
296*ec779b8eSAndroid Build Coastguard Worker  * printFields is a helper method that prints the fields and corresponding values
297*ec779b8eSAndroid Build Coastguard Worker  * in a human readable style.
298*ec779b8eSAndroid Build Coastguard Worker  */
299*ec779b8eSAndroid Build Coastguard Worker template <size_t N, typename ...Types>
printFields(const char * const (& fields)[N],Types...args)300*ec779b8eSAndroid Build Coastguard Worker std::string printFields(const char * const (& fields)[N], Types ... args)
301*ec779b8eSAndroid Build Coastguard Worker {
302*ec779b8eSAndroid Build Coastguard Worker     std::stringstream ss;
303*ec779b8eSAndroid Build Coastguard Worker     ss << " { ";
304*ec779b8eSAndroid Build Coastguard Worker     stringutils::fieldPrint(ss, fields, args...);
305*ec779b8eSAndroid Build Coastguard Worker     ss << "}";
306*ec779b8eSAndroid Build Coastguard Worker     return ss.str();
307*ec779b8eSAndroid Build Coastguard Worker }
308*ec779b8eSAndroid Build Coastguard Worker 
309*ec779b8eSAndroid Build Coastguard Worker /**
310*ec779b8eSAndroid Build Coastguard Worker  * sendToStatsd is a helper method that sends the arguments to statsd
311*ec779b8eSAndroid Build Coastguard Worker  */
312*ec779b8eSAndroid Build Coastguard Worker template <typename ...Types>
sendToStatsd(Types...args)313*ec779b8eSAndroid Build Coastguard Worker int sendToStatsd(Types ... args)
314*ec779b8eSAndroid Build Coastguard Worker {
315*ec779b8eSAndroid Build Coastguard Worker     int result = 0;
316*ec779b8eSAndroid Build Coastguard Worker 
317*ec779b8eSAndroid Build Coastguard Worker #ifdef STATSD_ENABLE
318*ec779b8eSAndroid Build Coastguard Worker     result = stats::media_metrics::stats_write(args...);
319*ec779b8eSAndroid Build Coastguard Worker #endif
320*ec779b8eSAndroid Build Coastguard Worker     return result;
321*ec779b8eSAndroid Build Coastguard Worker }
322*ec779b8eSAndroid Build Coastguard Worker 
323*ec779b8eSAndroid Build Coastguard Worker /**
324*ec779b8eSAndroid Build Coastguard Worker  * sendToStatsd is a helper method that sends the arguments to statsd
325*ec779b8eSAndroid Build Coastguard Worker  * and returns a pair { result, summary_string }.
326*ec779b8eSAndroid Build Coastguard Worker  */
327*ec779b8eSAndroid Build Coastguard Worker template <size_t N, typename ...Types>
sendToStatsd(const char * const (& fields)[N],Types...args)328*ec779b8eSAndroid Build Coastguard Worker std::pair<int, std::string> sendToStatsd(const char * const (& fields)[N], Types ... args)
329*ec779b8eSAndroid Build Coastguard Worker {
330*ec779b8eSAndroid Build Coastguard Worker     int result = 0;
331*ec779b8eSAndroid Build Coastguard Worker     std::stringstream ss;
332*ec779b8eSAndroid Build Coastguard Worker 
333*ec779b8eSAndroid Build Coastguard Worker #ifdef STATSD_ENABLE
334*ec779b8eSAndroid Build Coastguard Worker     result = stats::media_metrics::stats_write(args...);
335*ec779b8eSAndroid Build Coastguard Worker     ss << "result:" << result;
336*ec779b8eSAndroid Build Coastguard Worker #endif
337*ec779b8eSAndroid Build Coastguard Worker     ss << " { ";
338*ec779b8eSAndroid Build Coastguard Worker     stringutils::fieldPrint(ss, fields, args...);
339*ec779b8eSAndroid Build Coastguard Worker     ss << "}";
340*ec779b8eSAndroid Build Coastguard Worker     return { result, ss.str() };
341*ec779b8eSAndroid Build Coastguard Worker }
342*ec779b8eSAndroid Build Coastguard Worker 
AudioAnalytics(const std::shared_ptr<StatsdLog> & statsdLog)343*ec779b8eSAndroid Build Coastguard Worker AudioAnalytics::AudioAnalytics(const std::shared_ptr<StatsdLog>& statsdLog)
344*ec779b8eSAndroid Build Coastguard Worker     : mDeliverStatistics(property_get_bool(PROP_AUDIO_ANALYTICS_CLOUD_ENABLED, true))
345*ec779b8eSAndroid Build Coastguard Worker     , mStatsdLog(statsdLog)
346*ec779b8eSAndroid Build Coastguard Worker     , mAudioPowerUsage(this, statsdLog)
347*ec779b8eSAndroid Build Coastguard Worker {
348*ec779b8eSAndroid Build Coastguard Worker     SetMinimumLogSeverity(android::base::DEBUG); // for LOG().
349*ec779b8eSAndroid Build Coastguard Worker     ALOGD("%s", __func__);
350*ec779b8eSAndroid Build Coastguard Worker 
351*ec779b8eSAndroid Build Coastguard Worker     // Add action to save AnalyticsState if audioserver is restarted.
352*ec779b8eSAndroid Build Coastguard Worker     // This triggers on AudioFlinger or AudioPolicy ctors and onFirstRef,
353*ec779b8eSAndroid Build Coastguard Worker     // as well as TimeCheck events.
354*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
355*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
356*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR),
357*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
358*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
359*ec779b8eSAndroid Build Coastguard Worker                 mHealth.onAudioServerStart(Health::Module::AUDIOFLINGER, item);
360*ec779b8eSAndroid Build Coastguard Worker             }));
361*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
362*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_AUDIO_POLICY "." AMEDIAMETRICS_PROP_EVENT,
363*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR),
364*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
365*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
366*ec779b8eSAndroid Build Coastguard Worker                 mHealth.onAudioServerStart(Health::Module::AUDIOPOLICY, item);
367*ec779b8eSAndroid Build Coastguard Worker             }));
368*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
369*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
370*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_TIMEOUT),
371*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
372*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
373*ec779b8eSAndroid Build Coastguard Worker                 mHealth.onAudioServerTimeout(Health::Module::AUDIOFLINGER, item);
374*ec779b8eSAndroid Build Coastguard Worker             }));
375*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
376*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_AUDIO_POLICY "." AMEDIAMETRICS_PROP_EVENT,
377*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_TIMEOUT),
378*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
379*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
380*ec779b8eSAndroid Build Coastguard Worker                 mHealth.onAudioServerTimeout(Health::Module::AUDIOPOLICY, item);
381*ec779b8eSAndroid Build Coastguard Worker             }));
382*ec779b8eSAndroid Build Coastguard Worker 
383*ec779b8eSAndroid Build Coastguard Worker     // Handle legacy aaudio playback stream statistics
384*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
385*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
386*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
387*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
388*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
389*ec779b8eSAndroid Build Coastguard Worker                 mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
390*ec779b8eSAndroid Build Coastguard Worker             }));
391*ec779b8eSAndroid Build Coastguard Worker 
392*ec779b8eSAndroid Build Coastguard Worker     // Handle legacy aaudio capture stream statistics
393*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
394*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
395*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
396*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
397*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
398*ec779b8eSAndroid Build Coastguard Worker                 mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
399*ec779b8eSAndroid Build Coastguard Worker             }));
400*ec779b8eSAndroid Build Coastguard Worker 
401*ec779b8eSAndroid Build Coastguard Worker     // Handle mmap aaudio stream statistics
402*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
403*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*." AMEDIAMETRICS_PROP_EVENT,
404*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
405*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
406*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
407*ec779b8eSAndroid Build Coastguard Worker                 mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_MMAP);
408*ec779b8eSAndroid Build Coastguard Worker             }));
409*ec779b8eSAndroid Build Coastguard Worker 
410*ec779b8eSAndroid Build Coastguard Worker     // Handle device use record statistics
411*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
412*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
413*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
414*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
415*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
416*ec779b8eSAndroid Build Coastguard Worker                 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::RECORD);
417*ec779b8eSAndroid Build Coastguard Worker             }));
418*ec779b8eSAndroid Build Coastguard Worker 
419*ec779b8eSAndroid Build Coastguard Worker     // Handle device use thread statistics
420*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
421*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
422*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
423*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
424*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
425*ec779b8eSAndroid Build Coastguard Worker                 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::THREAD);
426*ec779b8eSAndroid Build Coastguard Worker             }));
427*ec779b8eSAndroid Build Coastguard Worker 
428*ec779b8eSAndroid Build Coastguard Worker     // Handle device use track statistics
429*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
430*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
431*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
432*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
433*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
434*ec779b8eSAndroid Build Coastguard Worker                 mDeviceUse.endAudioIntervalGroup(item, DeviceUse::TRACK);
435*ec779b8eSAndroid Build Coastguard Worker             }));
436*ec779b8eSAndroid Build Coastguard Worker 
437*ec779b8eSAndroid Build Coastguard Worker 
438*ec779b8eSAndroid Build Coastguard Worker     // Handle device connection statistics
439*ec779b8eSAndroid Build Coastguard Worker 
440*ec779b8eSAndroid Build Coastguard Worker     // We track connections (not disconnections) for the time to connect.
441*ec779b8eSAndroid Build Coastguard Worker     // TODO: consider BT requests in their A2dp service
442*ec779b8eSAndroid Build Coastguard Worker     // AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
443*ec779b8eSAndroid Build Coastguard Worker     // AudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
444*ec779b8eSAndroid Build Coastguard Worker     // AudioDeviceBroker.postA2dpActiveDeviceChange
445*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
446*ec779b8eSAndroid Build Coastguard Worker         "audio.device.a2dp.state",
447*ec779b8eSAndroid Build Coastguard Worker         "connected",
448*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
449*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
450*ec779b8eSAndroid Build Coastguard Worker                 mDeviceConnection.a2dpConnected(item);
451*ec779b8eSAndroid Build Coastguard Worker             }));
452*ec779b8eSAndroid Build Coastguard Worker     // If audio is active, we expect to see a createAudioPatch after the device is connected.
453*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
454*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
455*ec779b8eSAndroid Build Coastguard Worker         std::string("createAudioPatch"),
456*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
457*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
458*ec779b8eSAndroid Build Coastguard Worker                 mDeviceConnection.createPatch(item);
459*ec779b8eSAndroid Build Coastguard Worker             }));
460*ec779b8eSAndroid Build Coastguard Worker 
461*ec779b8eSAndroid Build Coastguard Worker     // Called from BT service
462*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
463*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE
464*ec779b8eSAndroid Build Coastguard Worker         "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent"
465*ec779b8eSAndroid Build Coastguard Worker         "." AMEDIAMETRICS_PROP_STATE,
466*ec779b8eSAndroid Build Coastguard Worker         "connected",
467*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
468*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
469*ec779b8eSAndroid Build Coastguard Worker                 mDeviceConnection.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(item);
470*ec779b8eSAndroid Build Coastguard Worker             }));
471*ec779b8eSAndroid Build Coastguard Worker 
472*ec779b8eSAndroid Build Coastguard Worker     // Handle power usage
473*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
474*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
475*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
476*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
477*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
478*ec779b8eSAndroid Build Coastguard Worker                 mAudioPowerUsage.checkTrackRecord(item, true /* isTrack */);
479*ec779b8eSAndroid Build Coastguard Worker             }));
480*ec779b8eSAndroid Build Coastguard Worker 
481*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
482*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
483*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
484*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
485*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
486*ec779b8eSAndroid Build Coastguard Worker                 mAudioPowerUsage.checkTrackRecord(item, false /* isTrack */);
487*ec779b8eSAndroid Build Coastguard Worker             }));
488*ec779b8eSAndroid Build Coastguard Worker 
489*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
490*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
491*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE),
492*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
493*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
494*ec779b8eSAndroid Build Coastguard Worker                 // ALOGD("(key=%s) Audioflinger setMode", item->getKey().c_str());
495*ec779b8eSAndroid Build Coastguard Worker                 mAudioPowerUsage.checkMode(item);
496*ec779b8eSAndroid Build Coastguard Worker             }));
497*ec779b8eSAndroid Build Coastguard Worker 
498*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
499*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
500*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME),
501*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
502*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
503*ec779b8eSAndroid Build Coastguard Worker                 // ALOGD("(key=%s) Audioflinger setVoiceVolume", item->getKey().c_str());
504*ec779b8eSAndroid Build Coastguard Worker                 mAudioPowerUsage.checkVoiceVolume(item);
505*ec779b8eSAndroid Build Coastguard Worker             }));
506*ec779b8eSAndroid Build Coastguard Worker 
507*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
508*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
509*ec779b8eSAndroid Build Coastguard Worker         std::string("createAudioPatch"),
510*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
511*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
512*ec779b8eSAndroid Build Coastguard Worker                 mAudioPowerUsage.checkCreatePatch(item);
513*ec779b8eSAndroid Build Coastguard Worker             }));
514*ec779b8eSAndroid Build Coastguard Worker 
515*ec779b8eSAndroid Build Coastguard Worker     // Handle Spatializer - these keys are prefixed by "audio.spatializer."
516*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
517*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER "*." AMEDIAMETRICS_PROP_EVENT,
518*ec779b8eSAndroid Build Coastguard Worker         std::monostate{}, /* match any event */
519*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
520*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item){
521*ec779b8eSAndroid Build Coastguard Worker                 mSpatializer.onEvent(item);
522*ec779b8eSAndroid Build Coastguard Worker             }));
523*ec779b8eSAndroid Build Coastguard Worker 
524*ec779b8eSAndroid Build Coastguard Worker     // Handle MIDI
525*ec779b8eSAndroid Build Coastguard Worker     mActions.addAction(
526*ec779b8eSAndroid Build Coastguard Worker         AMEDIAMETRICS_KEY_AUDIO_MIDI "." AMEDIAMETRICS_PROP_EVENT,
527*ec779b8eSAndroid Build Coastguard Worker         std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_DEVICECLOSED),
528*ec779b8eSAndroid Build Coastguard Worker         std::make_shared<AnalyticsActions::Function>(
529*ec779b8eSAndroid Build Coastguard Worker             [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
530*ec779b8eSAndroid Build Coastguard Worker                 mMidiLogging.onEvent(item);
531*ec779b8eSAndroid Build Coastguard Worker             }));
532*ec779b8eSAndroid Build Coastguard Worker }
533*ec779b8eSAndroid Build Coastguard Worker 
~AudioAnalytics()534*ec779b8eSAndroid Build Coastguard Worker AudioAnalytics::~AudioAnalytics()
535*ec779b8eSAndroid Build Coastguard Worker {
536*ec779b8eSAndroid Build Coastguard Worker     ALOGD("%s", __func__);
537*ec779b8eSAndroid Build Coastguard Worker     mTimedAction.quit(); // ensure no deferred access during destructor.
538*ec779b8eSAndroid Build Coastguard Worker }
539*ec779b8eSAndroid Build Coastguard Worker 
submit(const std::shared_ptr<const mediametrics::Item> & item,bool isTrusted)540*ec779b8eSAndroid Build Coastguard Worker status_t AudioAnalytics::submit(
541*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted)
542*ec779b8eSAndroid Build Coastguard Worker {
543*ec779b8eSAndroid Build Coastguard Worker     if (!startsWith(item->getKey(), AMEDIAMETRICS_KEY_PREFIX_AUDIO)) return BAD_VALUE;
544*ec779b8eSAndroid Build Coastguard Worker     status_t status = mAnalyticsState->submit(item, isTrusted);
545*ec779b8eSAndroid Build Coastguard Worker 
546*ec779b8eSAndroid Build Coastguard Worker     // Status is selectively authenticated.
547*ec779b8eSAndroid Build Coastguard Worker     processStatus(item);
548*ec779b8eSAndroid Build Coastguard Worker 
549*ec779b8eSAndroid Build Coastguard Worker     if (status != NO_ERROR) return status;  // may not be permitted.
550*ec779b8eSAndroid Build Coastguard Worker 
551*ec779b8eSAndroid Build Coastguard Worker     // Only if the item was successfully submitted (permission)
552*ec779b8eSAndroid Build Coastguard Worker     // do we check triggered actions.
553*ec779b8eSAndroid Build Coastguard Worker     processActions(item);
554*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
555*ec779b8eSAndroid Build Coastguard Worker }
556*ec779b8eSAndroid Build Coastguard Worker 
dump(bool details,int32_t lines,int64_t sinceNs,const char * prefix) const557*ec779b8eSAndroid Build Coastguard Worker std::pair<std::string, int32_t> AudioAnalytics::dump(
558*ec779b8eSAndroid Build Coastguard Worker         bool details, int32_t lines, int64_t sinceNs, const char *prefix) const
559*ec779b8eSAndroid Build Coastguard Worker {
560*ec779b8eSAndroid Build Coastguard Worker     std::stringstream ss;
561*ec779b8eSAndroid Build Coastguard Worker     int32_t ll = lines;
562*ec779b8eSAndroid Build Coastguard Worker 
563*ec779b8eSAndroid Build Coastguard Worker     if (ll > 0) {
564*ec779b8eSAndroid Build Coastguard Worker         auto [s, l] = mAnalyticsState->dump(details, ll, sinceNs, prefix);
565*ec779b8eSAndroid Build Coastguard Worker         ss << s;
566*ec779b8eSAndroid Build Coastguard Worker         ll -= l;
567*ec779b8eSAndroid Build Coastguard Worker     }
568*ec779b8eSAndroid Build Coastguard Worker 
569*ec779b8eSAndroid Build Coastguard Worker     // use details to dump prior state.
570*ec779b8eSAndroid Build Coastguard Worker     if (details && ll > 0) {
571*ec779b8eSAndroid Build Coastguard Worker         ss << "Prior audioserver state:\n";
572*ec779b8eSAndroid Build Coastguard Worker         --ll;
573*ec779b8eSAndroid Build Coastguard Worker     }
574*ec779b8eSAndroid Build Coastguard Worker     if (details && ll > 0) {
575*ec779b8eSAndroid Build Coastguard Worker         auto [s, l] = mPreviousAnalyticsState->dump(details, ll, sinceNs, prefix);
576*ec779b8eSAndroid Build Coastguard Worker         ss << s;
577*ec779b8eSAndroid Build Coastguard Worker         ll -= l;
578*ec779b8eSAndroid Build Coastguard Worker     }
579*ec779b8eSAndroid Build Coastguard Worker 
580*ec779b8eSAndroid Build Coastguard Worker     if (ll > 0 && prefix == nullptr) {
581*ec779b8eSAndroid Build Coastguard Worker         auto [s, l] = mAudioPowerUsage.dump(ll);
582*ec779b8eSAndroid Build Coastguard Worker         ss << s;
583*ec779b8eSAndroid Build Coastguard Worker         ll -= l;
584*ec779b8eSAndroid Build Coastguard Worker     }
585*ec779b8eSAndroid Build Coastguard Worker 
586*ec779b8eSAndroid Build Coastguard Worker     return { ss.str(), lines - ll };
587*ec779b8eSAndroid Build Coastguard Worker }
588*ec779b8eSAndroid Build Coastguard Worker 
processActions(const std::shared_ptr<const mediametrics::Item> & item)589*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::processActions(const std::shared_ptr<const mediametrics::Item>& item)
590*ec779b8eSAndroid Build Coastguard Worker {
591*ec779b8eSAndroid Build Coastguard Worker     auto actions = mActions.getActionsForItem(item); // internally locked.
592*ec779b8eSAndroid Build Coastguard Worker     // Execute actions with no lock held.
593*ec779b8eSAndroid Build Coastguard Worker     for (const auto& action : actions) {
594*ec779b8eSAndroid Build Coastguard Worker         (*action)(item);
595*ec779b8eSAndroid Build Coastguard Worker     }
596*ec779b8eSAndroid Build Coastguard Worker }
597*ec779b8eSAndroid Build Coastguard Worker 
processStatus(const std::shared_ptr<const mediametrics::Item> & item)598*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::processStatus(const std::shared_ptr<const mediametrics::Item>& item)
599*ec779b8eSAndroid Build Coastguard Worker {
600*ec779b8eSAndroid Build Coastguard Worker     int32_t status;
601*ec779b8eSAndroid Build Coastguard Worker     if (!item->get(AMEDIAMETRICS_PROP_STATUS, &status)) return;
602*ec779b8eSAndroid Build Coastguard Worker 
603*ec779b8eSAndroid Build Coastguard Worker     // Any record with a status will automatically be added to a heat map.
604*ec779b8eSAndroid Build Coastguard Worker     // Standard information.
605*ec779b8eSAndroid Build Coastguard Worker     const auto key = item->getKey();
606*ec779b8eSAndroid Build Coastguard Worker     const auto uid = item->getUid();
607*ec779b8eSAndroid Build Coastguard Worker 
608*ec779b8eSAndroid Build Coastguard Worker     // from audio.track.10 ->  prefix = audio.track, suffix = 10
609*ec779b8eSAndroid Build Coastguard Worker     // from audio.track.error -> prefix = audio.track, suffix = error
610*ec779b8eSAndroid Build Coastguard Worker     const auto [prefixKey, suffixKey] = stringutils::splitPrefixKey(key);
611*ec779b8eSAndroid Build Coastguard Worker 
612*ec779b8eSAndroid Build Coastguard Worker     std::string message;
613*ec779b8eSAndroid Build Coastguard Worker     item->get(AMEDIAMETRICS_PROP_STATUSMESSAGE, &message); // optional
614*ec779b8eSAndroid Build Coastguard Worker 
615*ec779b8eSAndroid Build Coastguard Worker     int32_t subCode = 0; // not used
616*ec779b8eSAndroid Build Coastguard Worker     (void)item->get(AMEDIAMETRICS_PROP_STATUSSUBCODE, &subCode); // optional
617*ec779b8eSAndroid Build Coastguard Worker 
618*ec779b8eSAndroid Build Coastguard Worker     std::string eventStr; // optional
619*ec779b8eSAndroid Build Coastguard Worker     item->get(AMEDIAMETRICS_PROP_EVENT, &eventStr);
620*ec779b8eSAndroid Build Coastguard Worker 
621*ec779b8eSAndroid Build Coastguard Worker     const std::string statusString = extendedStatusToStatusString(status);
622*ec779b8eSAndroid Build Coastguard Worker 
623*ec779b8eSAndroid Build Coastguard Worker     // Add to the heat map - we automatically track every item's status to see
624*ec779b8eSAndroid Build Coastguard Worker     // the types of errors and the frequency of errors.
625*ec779b8eSAndroid Build Coastguard Worker     mHeatMap.add(prefixKey, suffixKey, eventStr, statusString, uid, message, subCode);
626*ec779b8eSAndroid Build Coastguard Worker 
627*ec779b8eSAndroid Build Coastguard Worker     // Certain keys/event pairs are sent to statsd.  If we get a match (true) we return early.
628*ec779b8eSAndroid Build Coastguard Worker     if (reportAudioRecordStatus(item, key, eventStr, statusString, uid, message, subCode)) return;
629*ec779b8eSAndroid Build Coastguard Worker     if (reportAudioTrackStatus(item, key, eventStr, statusString, uid, message, subCode)) return;
630*ec779b8eSAndroid Build Coastguard Worker }
631*ec779b8eSAndroid Build Coastguard Worker 
reportAudioRecordStatus(const std::shared_ptr<const mediametrics::Item> & item,const std::string & key,const std::string & eventStr,const std::string & statusString,uid_t uid,const std::string & message,int32_t subCode) const632*ec779b8eSAndroid Build Coastguard Worker bool AudioAnalytics::reportAudioRecordStatus(
633*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<const mediametrics::Item>& item,
634*ec779b8eSAndroid Build Coastguard Worker         const std::string& key, const std::string& eventStr,
635*ec779b8eSAndroid Build Coastguard Worker         const std::string& statusString, uid_t uid, const std::string& message,
636*ec779b8eSAndroid Build Coastguard Worker         int32_t subCode) const
637*ec779b8eSAndroid Build Coastguard Worker {
638*ec779b8eSAndroid Build Coastguard Worker     // Note that the prefixes often end with a '.' so we use startsWith.
639*ec779b8eSAndroid Build Coastguard Worker     if (!startsWith(key, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD)) return false;
640*ec779b8eSAndroid Build Coastguard Worker     if (eventStr == AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE) {
641*ec779b8eSAndroid Build Coastguard Worker         const int atom_status = types::lookup<types::STATUS, int32_t>(statusString);
642*ec779b8eSAndroid Build Coastguard Worker 
643*ec779b8eSAndroid Build Coastguard Worker         // currently we only send create status events.
644*ec779b8eSAndroid Build Coastguard Worker         const int32_t event = stats::media_metrics::
645*ec779b8eSAndroid Build Coastguard Worker                 MEDIAMETRICS_AUDIO_RECORD_STATUS_REPORTED__EVENT__AUDIO_RECORD_EVENT_CREATE;
646*ec779b8eSAndroid Build Coastguard Worker 
647*ec779b8eSAndroid Build Coastguard Worker         // The following fields should all be present in a create event.
648*ec779b8eSAndroid Build Coastguard Worker         std::string flagsStr;
649*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_ORIGINALFLAGS, &flagsStr),
650*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field", __func__,
651*ec779b8eSAndroid Build Coastguard Worker                 AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_ORIGINALFLAGS);
652*ec779b8eSAndroid Build Coastguard Worker         const auto flags = types::lookup<types::INPUT_FLAG, int32_t>(flagsStr);
653*ec779b8eSAndroid Build Coastguard Worker 
654*ec779b8eSAndroid Build Coastguard Worker         // AMEDIAMETRICS_PROP_SESSIONID omitted from atom
655*ec779b8eSAndroid Build Coastguard Worker 
656*ec779b8eSAndroid Build Coastguard Worker         std::string sourceStr;
657*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_SOURCE, &sourceStr),
658*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
659*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_SOURCE);
660*ec779b8eSAndroid Build Coastguard Worker         const int32_t source = types::lookup<types::SOURCE_TYPE, int32_t>(sourceStr);
661*ec779b8eSAndroid Build Coastguard Worker 
662*ec779b8eSAndroid Build Coastguard Worker         // AMEDIAMETRICS_PROP_SELECTEDDEVICEID omitted from atom
663*ec779b8eSAndroid Build Coastguard Worker 
664*ec779b8eSAndroid Build Coastguard Worker         std::string encodingStr;
665*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_ENCODING, &encodingStr),
666*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
667*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_ENCODING);
668*ec779b8eSAndroid Build Coastguard Worker         const auto encoding = types::lookup<types::ENCODING, int32_t>(encodingStr);
669*ec779b8eSAndroid Build Coastguard Worker 
670*ec779b8eSAndroid Build Coastguard Worker         int32_t channelMask = 0;
671*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_CHANNELMASK, &channelMask),
672*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
673*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_CHANNELMASK);
674*ec779b8eSAndroid Build Coastguard Worker         int32_t frameCount = 0;
675*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount),
676*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
677*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_FRAMECOUNT);
678*ec779b8eSAndroid Build Coastguard Worker         int32_t sampleRate = 0;
679*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate),
680*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
681*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_SAMPLERATE);
682*ec779b8eSAndroid Build Coastguard Worker 
683*ec779b8eSAndroid Build Coastguard Worker         const auto [ result, str ] = sendToStatsd(AudioRecordStatusFields,
684*ec779b8eSAndroid Build Coastguard Worker                 CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED)
685*ec779b8eSAndroid Build Coastguard Worker                 , atom_status
686*ec779b8eSAndroid Build Coastguard Worker                 , message.c_str()
687*ec779b8eSAndroid Build Coastguard Worker                 , subCode
688*ec779b8eSAndroid Build Coastguard Worker                 , uid
689*ec779b8eSAndroid Build Coastguard Worker                 , event
690*ec779b8eSAndroid Build Coastguard Worker                 , flags
691*ec779b8eSAndroid Build Coastguard Worker                 , source
692*ec779b8eSAndroid Build Coastguard Worker                 , encoding
693*ec779b8eSAndroid Build Coastguard Worker                 , (int64_t)channelMask
694*ec779b8eSAndroid Build Coastguard Worker                 , frameCount
695*ec779b8eSAndroid Build Coastguard Worker                 , sampleRate
696*ec779b8eSAndroid Build Coastguard Worker                 );
697*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: statsd %s", __func__, str.c_str());
698*ec779b8eSAndroid Build Coastguard Worker         mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED, str);
699*ec779b8eSAndroid Build Coastguard Worker         return true;
700*ec779b8eSAndroid Build Coastguard Worker     }
701*ec779b8eSAndroid Build Coastguard Worker     return false;
702*ec779b8eSAndroid Build Coastguard Worker }
703*ec779b8eSAndroid Build Coastguard Worker 
reportAudioTrackStatus(const std::shared_ptr<const mediametrics::Item> & item,const std::string & key,const std::string & eventStr,const std::string & statusString,uid_t uid,const std::string & message,int32_t subCode) const704*ec779b8eSAndroid Build Coastguard Worker bool AudioAnalytics::reportAudioTrackStatus(
705*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<const mediametrics::Item>& item,
706*ec779b8eSAndroid Build Coastguard Worker         const std::string& key, const std::string& eventStr,
707*ec779b8eSAndroid Build Coastguard Worker         const std::string& statusString, uid_t uid, const std::string& message,
708*ec779b8eSAndroid Build Coastguard Worker         int32_t subCode) const
709*ec779b8eSAndroid Build Coastguard Worker {
710*ec779b8eSAndroid Build Coastguard Worker     // Note that the prefixes often end with a '.' so we use startsWith.
711*ec779b8eSAndroid Build Coastguard Worker     if (!startsWith(key, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)) return false;
712*ec779b8eSAndroid Build Coastguard Worker     if (eventStr == AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE) {
713*ec779b8eSAndroid Build Coastguard Worker         const int atom_status = types::lookup<types::STATUS, int32_t>(statusString);
714*ec779b8eSAndroid Build Coastguard Worker 
715*ec779b8eSAndroid Build Coastguard Worker         // currently we only send create status events.
716*ec779b8eSAndroid Build Coastguard Worker         const int32_t event = stats::media_metrics::
717*ec779b8eSAndroid Build Coastguard Worker                 MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__EVENT__AUDIO_TRACK_EVENT_CREATE;
718*ec779b8eSAndroid Build Coastguard Worker 
719*ec779b8eSAndroid Build Coastguard Worker         // The following fields should all be present in a create event.
720*ec779b8eSAndroid Build Coastguard Worker         std::string flagsStr;
721*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_ORIGINALFLAGS, &flagsStr),
722*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
723*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_ORIGINALFLAGS);
724*ec779b8eSAndroid Build Coastguard Worker         const auto flags = types::lookup<types::OUTPUT_FLAG, int32_t>(flagsStr);
725*ec779b8eSAndroid Build Coastguard Worker 
726*ec779b8eSAndroid Build Coastguard Worker         // AMEDIAMETRICS_PROP_SESSIONID omitted from atom
727*ec779b8eSAndroid Build Coastguard Worker 
728*ec779b8eSAndroid Build Coastguard Worker         std::string contentTypeStr;
729*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_CONTENTTYPE, &contentTypeStr),
730*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
731*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_CONTENTTYPE);
732*ec779b8eSAndroid Build Coastguard Worker         const auto contentType = types::lookup<types::CONTENT_TYPE, int32_t>(contentTypeStr);
733*ec779b8eSAndroid Build Coastguard Worker 
734*ec779b8eSAndroid Build Coastguard Worker         std::string usageStr;
735*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_USAGE, &usageStr),
736*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
737*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_USAGE);
738*ec779b8eSAndroid Build Coastguard Worker         const auto usage = types::lookup<types::USAGE, int32_t>(usageStr);
739*ec779b8eSAndroid Build Coastguard Worker 
740*ec779b8eSAndroid Build Coastguard Worker         // AMEDIAMETRICS_PROP_SELECTEDDEVICEID omitted from atom
741*ec779b8eSAndroid Build Coastguard Worker 
742*ec779b8eSAndroid Build Coastguard Worker         std::string encodingStr;
743*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_ENCODING, &encodingStr),
744*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
745*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_ENCODING);
746*ec779b8eSAndroid Build Coastguard Worker         const auto encoding = types::lookup<types::ENCODING, int32_t>(encodingStr);
747*ec779b8eSAndroid Build Coastguard Worker 
748*ec779b8eSAndroid Build Coastguard Worker         int32_t channelMask = 0;
749*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_CHANNELMASK, &channelMask),
750*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
751*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_CHANNELMASK);
752*ec779b8eSAndroid Build Coastguard Worker         int32_t frameCount = 0;
753*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount),
754*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
755*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_FRAMECOUNT);
756*ec779b8eSAndroid Build Coastguard Worker         int32_t sampleRate = 0;
757*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate),
758*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
759*ec779b8eSAndroid Build Coastguard Worker                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_SAMPLERATE);
760*ec779b8eSAndroid Build Coastguard Worker         double speed = 0.f;  // default is 1.f
761*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_PLAYBACK_SPEED, &speed),
762*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
763*ec779b8eSAndroid Build Coastguard Worker                 __func__,
764*ec779b8eSAndroid Build Coastguard Worker                 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_PLAYBACK_SPEED);
765*ec779b8eSAndroid Build Coastguard Worker         double pitch = 0.f;  // default is 1.f
766*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(!item->get(AMEDIAMETRICS_PROP_PLAYBACK_PITCH, &pitch),
767*ec779b8eSAndroid Build Coastguard Worker                 "%s: %s missing %s field",
768*ec779b8eSAndroid Build Coastguard Worker                 __func__,
769*ec779b8eSAndroid Build Coastguard Worker                 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_PLAYBACK_PITCH);
770*ec779b8eSAndroid Build Coastguard Worker         const auto [ result, str ] = sendToStatsd(AudioTrackStatusFields,
771*ec779b8eSAndroid Build Coastguard Worker                 CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED)
772*ec779b8eSAndroid Build Coastguard Worker                 , atom_status
773*ec779b8eSAndroid Build Coastguard Worker                 , message.c_str()
774*ec779b8eSAndroid Build Coastguard Worker                 , subCode
775*ec779b8eSAndroid Build Coastguard Worker                 , uid
776*ec779b8eSAndroid Build Coastguard Worker                 , event
777*ec779b8eSAndroid Build Coastguard Worker                 , flags
778*ec779b8eSAndroid Build Coastguard Worker                 , contentType
779*ec779b8eSAndroid Build Coastguard Worker                 , usage
780*ec779b8eSAndroid Build Coastguard Worker                 , encoding
781*ec779b8eSAndroid Build Coastguard Worker                 , (int64_t)channelMask
782*ec779b8eSAndroid Build Coastguard Worker                 , frameCount
783*ec779b8eSAndroid Build Coastguard Worker                 , sampleRate
784*ec779b8eSAndroid Build Coastguard Worker                 , (float)speed
785*ec779b8eSAndroid Build Coastguard Worker                 , (float)pitch
786*ec779b8eSAndroid Build Coastguard Worker                 );
787*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: statsd %s", __func__, str.c_str());
788*ec779b8eSAndroid Build Coastguard Worker         mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED, str);
789*ec779b8eSAndroid Build Coastguard Worker         return true;
790*ec779b8eSAndroid Build Coastguard Worker     }
791*ec779b8eSAndroid Build Coastguard Worker     return false;
792*ec779b8eSAndroid Build Coastguard Worker }
793*ec779b8eSAndroid Build Coastguard Worker 
794*ec779b8eSAndroid Build Coastguard Worker // HELPER METHODS
795*ec779b8eSAndroid Build Coastguard Worker 
getThreadFromTrack(const std::string & track) const796*ec779b8eSAndroid Build Coastguard Worker std::string AudioAnalytics::getThreadFromTrack(const std::string& track) const
797*ec779b8eSAndroid Build Coastguard Worker {
798*ec779b8eSAndroid Build Coastguard Worker     int32_t threadId_int32{};
799*ec779b8eSAndroid Build Coastguard Worker     if (mAnalyticsState->timeMachine().get(
800*ec779b8eSAndroid Build Coastguard Worker             track, AMEDIAMETRICS_PROP_THREADID, &threadId_int32) != NO_ERROR) {
801*ec779b8eSAndroid Build Coastguard Worker         return {};
802*ec779b8eSAndroid Build Coastguard Worker     }
803*ec779b8eSAndroid Build Coastguard Worker     return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(threadId_int32);
804*ec779b8eSAndroid Build Coastguard Worker }
805*ec779b8eSAndroid Build Coastguard Worker 
806*ec779b8eSAndroid Build Coastguard Worker // DeviceUse helper class.
endAudioIntervalGroup(const std::shared_ptr<const android::mediametrics::Item> & item,ItemType itemType) const807*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::DeviceUse::endAudioIntervalGroup(
808*ec779b8eSAndroid Build Coastguard Worker        const std::shared_ptr<const android::mediametrics::Item> &item, ItemType itemType) const {
809*ec779b8eSAndroid Build Coastguard Worker     const std::string& key = item->getKey();
810*ec779b8eSAndroid Build Coastguard Worker     const std::string id = key.substr(
811*ec779b8eSAndroid Build Coastguard Worker             (itemType == THREAD ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD)
812*ec779b8eSAndroid Build Coastguard Worker             : itemType == TRACK ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
813*ec779b8eSAndroid Build Coastguard Worker             : sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD))
814*ec779b8eSAndroid Build Coastguard Worker              - 1);
815*ec779b8eSAndroid Build Coastguard Worker     // deliver statistics
816*ec779b8eSAndroid Build Coastguard Worker     int64_t deviceTimeNs = 0;
817*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
818*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_DEVICETIMENS, &deviceTimeNs);
819*ec779b8eSAndroid Build Coastguard Worker     std::string encoding;
820*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
821*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_ENCODING, &encoding);
822*ec779b8eSAndroid Build Coastguard Worker     int32_t frameCount = 0;
823*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
824*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount);
825*ec779b8eSAndroid Build Coastguard Worker     int32_t intervalCount = 0;
826*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
827*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_INTERVALCOUNT, &intervalCount);
828*ec779b8eSAndroid Build Coastguard Worker     int32_t sampleRate = 0;
829*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
830*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
831*ec779b8eSAndroid Build Coastguard Worker     std::string flags;
832*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
833*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_FLAGS, &flags);
834*ec779b8eSAndroid Build Coastguard Worker 
835*ec779b8eSAndroid Build Coastguard Worker     switch (itemType) {
836*ec779b8eSAndroid Build Coastguard Worker     case RECORD: {
837*ec779b8eSAndroid Build Coastguard Worker         std::string inputDevicePairs;
838*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
839*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_INPUTDEVICES, &inputDevicePairs);
840*ec779b8eSAndroid Build Coastguard Worker 
841*ec779b8eSAndroid Build Coastguard Worker         const auto [ inputDeviceStatsd, inputDevices ] =
842*ec779b8eSAndroid Build Coastguard Worker                 stringutils::parseInputDevicePairs(inputDevicePairs);
843*ec779b8eSAndroid Build Coastguard Worker         const std::string inputDeviceNames;  // not filled currently.
844*ec779b8eSAndroid Build Coastguard Worker 
845*ec779b8eSAndroid Build Coastguard Worker         std::string callerName;
846*ec779b8eSAndroid Build Coastguard Worker         const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
847*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
848*ec779b8eSAndroid Build Coastguard Worker 
849*ec779b8eSAndroid Build Coastguard Worker         std::string packageName;
850*ec779b8eSAndroid Build Coastguard Worker         int64_t versionCode = 0;
851*ec779b8eSAndroid Build Coastguard Worker         int32_t uid = -1;
852*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
853*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
854*ec779b8eSAndroid Build Coastguard Worker         if (uid != -1) {
855*ec779b8eSAndroid Build Coastguard Worker             std::tie(packageName, versionCode) =
856*ec779b8eSAndroid Build Coastguard Worker                     MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
857*ec779b8eSAndroid Build Coastguard Worker         }
858*ec779b8eSAndroid Build Coastguard Worker 
859*ec779b8eSAndroid Build Coastguard Worker         int32_t selectedDeviceId = 0;
860*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
861*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
862*ec779b8eSAndroid Build Coastguard Worker         std::string source;
863*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
864*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_SOURCE, &source);
865*ec779b8eSAndroid Build Coastguard Worker         // Android S
866*ec779b8eSAndroid Build Coastguard Worker         std::string logSessionId;
867*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
868*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
869*ec779b8eSAndroid Build Coastguard Worker 
870*ec779b8eSAndroid Build Coastguard Worker         const auto callerNameForStats =
871*ec779b8eSAndroid Build Coastguard Worker                 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
872*ec779b8eSAndroid Build Coastguard Worker         const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
873*ec779b8eSAndroid Build Coastguard Worker         const auto flagsForStats = types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags);
874*ec779b8eSAndroid Build Coastguard Worker         const auto sourceForStats = types::lookup<types::SOURCE_TYPE, short_enum_type_t>(source);
875*ec779b8eSAndroid Build Coastguard Worker         // Android S
876*ec779b8eSAndroid Build Coastguard Worker         const auto logSessionIdForStats = ValidateId::get()->validateId(logSessionId);
877*ec779b8eSAndroid Build Coastguard Worker 
878*ec779b8eSAndroid Build Coastguard Worker         LOG(LOG_LEVEL) << "key:" << key
879*ec779b8eSAndroid Build Coastguard Worker               << " id:" << id
880*ec779b8eSAndroid Build Coastguard Worker               << " inputDevices:" << inputDevices << "(" << inputDeviceStatsd
881*ec779b8eSAndroid Build Coastguard Worker               << ") inputDeviceNames:" << inputDeviceNames
882*ec779b8eSAndroid Build Coastguard Worker               << " deviceTimeNs:" << deviceTimeNs
883*ec779b8eSAndroid Build Coastguard Worker               << " encoding:" << encoding << "(" << encodingForStats
884*ec779b8eSAndroid Build Coastguard Worker               << ") frameCount:" << frameCount
885*ec779b8eSAndroid Build Coastguard Worker               << " intervalCount:" << intervalCount
886*ec779b8eSAndroid Build Coastguard Worker               << " sampleRate:" << sampleRate
887*ec779b8eSAndroid Build Coastguard Worker               << " flags:" << flags << "(" << flagsForStats
888*ec779b8eSAndroid Build Coastguard Worker               << ") packageName:" << packageName
889*ec779b8eSAndroid Build Coastguard Worker               << " selectedDeviceId:" << selectedDeviceId
890*ec779b8eSAndroid Build Coastguard Worker               << " callerName:" << callerName << "(" << callerNameForStats
891*ec779b8eSAndroid Build Coastguard Worker               << ") source:" << source << "(" << sourceForStats
892*ec779b8eSAndroid Build Coastguard Worker               << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats
893*ec779b8eSAndroid Build Coastguard Worker               << ")";
894*ec779b8eSAndroid Build Coastguard Worker         if (clientCalled  // only log if client app called AudioRecord.
895*ec779b8eSAndroid Build Coastguard Worker                 && mAudioAnalytics.mDeliverStatistics) {
896*ec779b8eSAndroid Build Coastguard Worker             const auto [ result, str ] = sendToStatsd(AudioRecordDeviceUsageFields,
897*ec779b8eSAndroid Build Coastguard Worker                     CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
898*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(inputDeviceStatsd)
899*ec779b8eSAndroid Build Coastguard Worker                     , inputDeviceNames.c_str()
900*ec779b8eSAndroid Build Coastguard Worker                     , deviceTimeNs
901*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(encodingForStats)
902*ec779b8eSAndroid Build Coastguard Worker                     , frameCount
903*ec779b8eSAndroid Build Coastguard Worker                     , intervalCount
904*ec779b8eSAndroid Build Coastguard Worker                     , sampleRate
905*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(flagsForStats)
906*ec779b8eSAndroid Build Coastguard Worker 
907*ec779b8eSAndroid Build Coastguard Worker                     , packageName.c_str()
908*ec779b8eSAndroid Build Coastguard Worker                     , selectedDeviceId
909*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(callerNameForStats)
910*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(sourceForStats)
911*ec779b8eSAndroid Build Coastguard Worker                     , logSessionIdForStats.c_str()
912*ec779b8eSAndroid Build Coastguard Worker                     );
913*ec779b8eSAndroid Build Coastguard Worker             ALOGV("%s: statsd %s", __func__, str.c_str());
914*ec779b8eSAndroid Build Coastguard Worker             mAudioAnalytics.mStatsdLog->log(
915*ec779b8eSAndroid Build Coastguard Worker                     stats::media_metrics::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED, str);
916*ec779b8eSAndroid Build Coastguard Worker         }
917*ec779b8eSAndroid Build Coastguard Worker     } break;
918*ec779b8eSAndroid Build Coastguard Worker     case THREAD: {
919*ec779b8eSAndroid Build Coastguard Worker         std::string type;
920*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
921*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_TYPE, &type);
922*ec779b8eSAndroid Build Coastguard Worker         int32_t underrun = 0; // zero for record types
923*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
924*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
925*ec779b8eSAndroid Build Coastguard Worker 
926*ec779b8eSAndroid Build Coastguard Worker         const bool isInput = types::isInputThreadType(type);
927*ec779b8eSAndroid Build Coastguard Worker 
928*ec779b8eSAndroid Build Coastguard Worker         // get device information
929*ec779b8eSAndroid Build Coastguard Worker         std::string devicePairs;
930*ec779b8eSAndroid Build Coastguard Worker         std::string deviceStatsd;
931*ec779b8eSAndroid Build Coastguard Worker         std::string devices;
932*ec779b8eSAndroid Build Coastguard Worker         std::string deviceNames;
933*ec779b8eSAndroid Build Coastguard Worker         if (isInput) {
934*ec779b8eSAndroid Build Coastguard Worker             // Note we get the "last" device which is the one associated with group.
935*ec779b8eSAndroid Build Coastguard Worker             item->get(AMEDIAMETRICS_PROP_PREFIX_LAST AMEDIAMETRICS_PROP_INPUTDEVICES,
936*ec779b8eSAndroid Build Coastguard Worker                     &devicePairs);
937*ec779b8eSAndroid Build Coastguard Worker             std::tie(deviceStatsd, devices) = stringutils::parseInputDevicePairs(devicePairs);
938*ec779b8eSAndroid Build Coastguard Worker         } else {
939*ec779b8eSAndroid Build Coastguard Worker             // Note we get the "last" device which is the one associated with group.
940*ec779b8eSAndroid Build Coastguard Worker             item->get(AMEDIAMETRICS_PROP_PREFIX_LAST AMEDIAMETRICS_PROP_OUTPUTDEVICES,
941*ec779b8eSAndroid Build Coastguard Worker                     &devicePairs);
942*ec779b8eSAndroid Build Coastguard Worker             std::tie(deviceStatsd, devices) = stringutils::parseOutputDevicePairs(devicePairs);
943*ec779b8eSAndroid Build Coastguard Worker             deviceNames = mAudioAnalytics.getDeviceNamesFromOutputDevices(devices);
944*ec779b8eSAndroid Build Coastguard Worker         }
945*ec779b8eSAndroid Build Coastguard Worker 
946*ec779b8eSAndroid Build Coastguard Worker         const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
947*ec779b8eSAndroid Build Coastguard Worker         const auto flagsForStats =
948*ec779b8eSAndroid Build Coastguard Worker                 (isInput ? types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags)
949*ec779b8eSAndroid Build Coastguard Worker                         : types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags));
950*ec779b8eSAndroid Build Coastguard Worker         const auto typeForStats = types::lookup<types::THREAD_TYPE, short_enum_type_t>(type);
951*ec779b8eSAndroid Build Coastguard Worker 
952*ec779b8eSAndroid Build Coastguard Worker          LOG(LOG_LEVEL) << "key:" << key
953*ec779b8eSAndroid Build Coastguard Worker               << " id:" << id
954*ec779b8eSAndroid Build Coastguard Worker               << " devices:" << devices << "(" << deviceStatsd
955*ec779b8eSAndroid Build Coastguard Worker               << ") deviceNames:" << deviceNames
956*ec779b8eSAndroid Build Coastguard Worker               << " deviceTimeNs:" << deviceTimeNs
957*ec779b8eSAndroid Build Coastguard Worker               << " encoding:" << encoding << "(" << encodingForStats
958*ec779b8eSAndroid Build Coastguard Worker               << ") frameCount:" << frameCount
959*ec779b8eSAndroid Build Coastguard Worker               << " intervalCount:" << intervalCount
960*ec779b8eSAndroid Build Coastguard Worker               << " sampleRate:" << sampleRate
961*ec779b8eSAndroid Build Coastguard Worker               << " underrun:" << underrun
962*ec779b8eSAndroid Build Coastguard Worker               << " flags:" << flags << "(" << flagsForStats
963*ec779b8eSAndroid Build Coastguard Worker               << ") type:" << type << "(" << typeForStats
964*ec779b8eSAndroid Build Coastguard Worker               << ")";
965*ec779b8eSAndroid Build Coastguard Worker         if (mAudioAnalytics.mDeliverStatistics) {
966*ec779b8eSAndroid Build Coastguard Worker             const auto [ result, str ] = sendToStatsd(AudioThreadDeviceUsageFields,
967*ec779b8eSAndroid Build Coastguard Worker                 CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
968*ec779b8eSAndroid Build Coastguard Worker                 , ENUM_EXTRACT(deviceStatsd)
969*ec779b8eSAndroid Build Coastguard Worker                 , deviceNames.c_str()
970*ec779b8eSAndroid Build Coastguard Worker                 , deviceTimeNs
971*ec779b8eSAndroid Build Coastguard Worker                 , ENUM_EXTRACT(encodingForStats)
972*ec779b8eSAndroid Build Coastguard Worker                 , frameCount
973*ec779b8eSAndroid Build Coastguard Worker                 , intervalCount
974*ec779b8eSAndroid Build Coastguard Worker                 , sampleRate
975*ec779b8eSAndroid Build Coastguard Worker                 , ENUM_EXTRACT(flagsForStats)
976*ec779b8eSAndroid Build Coastguard Worker                 , underrun
977*ec779b8eSAndroid Build Coastguard Worker                 , ENUM_EXTRACT(typeForStats)
978*ec779b8eSAndroid Build Coastguard Worker             );
979*ec779b8eSAndroid Build Coastguard Worker             ALOGV("%s: statsd %s", __func__, str.c_str());
980*ec779b8eSAndroid Build Coastguard Worker             mAudioAnalytics.mStatsdLog->log(
981*ec779b8eSAndroid Build Coastguard Worker                     stats::media_metrics::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED, str);
982*ec779b8eSAndroid Build Coastguard Worker         }
983*ec779b8eSAndroid Build Coastguard Worker     } break;
984*ec779b8eSAndroid Build Coastguard Worker     case TRACK: {
985*ec779b8eSAndroid Build Coastguard Worker         std::string outputDevicePairs;
986*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
987*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevicePairs);
988*ec779b8eSAndroid Build Coastguard Worker 
989*ec779b8eSAndroid Build Coastguard Worker         const auto [ outputDeviceStatsd, outputDevices ] =
990*ec779b8eSAndroid Build Coastguard Worker                 stringutils::parseOutputDevicePairs(outputDevicePairs);
991*ec779b8eSAndroid Build Coastguard Worker         const std::string outputDeviceNames =
992*ec779b8eSAndroid Build Coastguard Worker                 mAudioAnalytics.getDeviceNamesFromOutputDevices(outputDevices);
993*ec779b8eSAndroid Build Coastguard Worker 
994*ec779b8eSAndroid Build Coastguard Worker         std::string callerName;
995*ec779b8eSAndroid Build Coastguard Worker         const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
996*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
997*ec779b8eSAndroid Build Coastguard Worker 
998*ec779b8eSAndroid Build Coastguard Worker         std::string contentType;
999*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1000*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentType);
1001*ec779b8eSAndroid Build Coastguard Worker         double deviceLatencyMs = 0.;
1002*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1003*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_DEVICELATENCYMS, &deviceLatencyMs);
1004*ec779b8eSAndroid Build Coastguard Worker         double deviceStartupMs = 0.;
1005*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1006*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_DEVICESTARTUPMS, &deviceStartupMs);
1007*ec779b8eSAndroid Build Coastguard Worker         double deviceVolume = 0.;
1008*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1009*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume);
1010*ec779b8eSAndroid Build Coastguard Worker         std::string packageName;
1011*ec779b8eSAndroid Build Coastguard Worker         int64_t versionCode = 0;
1012*ec779b8eSAndroid Build Coastguard Worker         int32_t uid = -1;
1013*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1014*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
1015*ec779b8eSAndroid Build Coastguard Worker         if (uid != -1) {
1016*ec779b8eSAndroid Build Coastguard Worker             std::tie(packageName, versionCode) =
1017*ec779b8eSAndroid Build Coastguard Worker                     MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
1018*ec779b8eSAndroid Build Coastguard Worker         }
1019*ec779b8eSAndroid Build Coastguard Worker         double playbackPitch = 0.;
1020*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1021*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_PLAYBACK_PITCH, &playbackPitch);
1022*ec779b8eSAndroid Build Coastguard Worker         double playbackSpeed = 0.;
1023*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1024*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_PLAYBACK_SPEED, &playbackSpeed);
1025*ec779b8eSAndroid Build Coastguard Worker         int32_t selectedDeviceId = 0;
1026*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1027*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
1028*ec779b8eSAndroid Build Coastguard Worker         std::string streamType;
1029*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1030*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_STREAMTYPE, &streamType);
1031*ec779b8eSAndroid Build Coastguard Worker         std::string traits;
1032*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1033*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_TRAITS, &traits);
1034*ec779b8eSAndroid Build Coastguard Worker         int32_t underrun = 0;
1035*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1036*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
1037*ec779b8eSAndroid Build Coastguard Worker         std::string usage;
1038*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1039*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_USAGE, &usage);
1040*ec779b8eSAndroid Build Coastguard Worker         // Android S
1041*ec779b8eSAndroid Build Coastguard Worker         std::string logSessionId;
1042*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1043*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
1044*ec779b8eSAndroid Build Coastguard Worker 
1045*ec779b8eSAndroid Build Coastguard Worker         const auto callerNameForStats =
1046*ec779b8eSAndroid Build Coastguard Worker                 types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
1047*ec779b8eSAndroid Build Coastguard Worker         const auto contentTypeForStats =
1048*ec779b8eSAndroid Build Coastguard Worker                 types::lookup<types::CONTENT_TYPE, short_enum_type_t>(contentType);
1049*ec779b8eSAndroid Build Coastguard Worker         const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
1050*ec779b8eSAndroid Build Coastguard Worker         const auto flagsForStats = types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags);
1051*ec779b8eSAndroid Build Coastguard Worker         const auto streamTypeForStats =
1052*ec779b8eSAndroid Build Coastguard Worker                 types::lookup<types::STREAM_TYPE, short_enum_type_t>(streamType);
1053*ec779b8eSAndroid Build Coastguard Worker         const auto traitsForStats =
1054*ec779b8eSAndroid Build Coastguard Worker                  types::lookup<types::TRACK_TRAITS, short_enum_type_t>(traits);
1055*ec779b8eSAndroid Build Coastguard Worker         const auto usageForStats = types::lookup<types::USAGE, short_enum_type_t>(usage);
1056*ec779b8eSAndroid Build Coastguard Worker         // Android S
1057*ec779b8eSAndroid Build Coastguard Worker         const auto logSessionIdForStats = ValidateId::get()->validateId(logSessionId);
1058*ec779b8eSAndroid Build Coastguard Worker 
1059*ec779b8eSAndroid Build Coastguard Worker         LOG(LOG_LEVEL) << "key:" << key
1060*ec779b8eSAndroid Build Coastguard Worker               << " id:" << id
1061*ec779b8eSAndroid Build Coastguard Worker               << " outputDevices:" << outputDevices << "(" << outputDeviceStatsd
1062*ec779b8eSAndroid Build Coastguard Worker               << ") outputDeviceNames:" << outputDeviceNames
1063*ec779b8eSAndroid Build Coastguard Worker               << " deviceTimeNs:" << deviceTimeNs
1064*ec779b8eSAndroid Build Coastguard Worker               << " encoding:" << encoding << "(" << encodingForStats
1065*ec779b8eSAndroid Build Coastguard Worker               << ") frameCount:" << frameCount
1066*ec779b8eSAndroid Build Coastguard Worker               << " intervalCount:" << intervalCount
1067*ec779b8eSAndroid Build Coastguard Worker               << " sampleRate:" << sampleRate
1068*ec779b8eSAndroid Build Coastguard Worker               << " underrun:" << underrun
1069*ec779b8eSAndroid Build Coastguard Worker               << " flags:" << flags << "(" << flagsForStats
1070*ec779b8eSAndroid Build Coastguard Worker               << ") callerName:" << callerName << "(" << callerNameForStats
1071*ec779b8eSAndroid Build Coastguard Worker               << ") contentType:" << contentType << "(" << contentTypeForStats
1072*ec779b8eSAndroid Build Coastguard Worker               << ") deviceLatencyMs:" << deviceLatencyMs
1073*ec779b8eSAndroid Build Coastguard Worker               << " deviceStartupMs:" << deviceStartupMs
1074*ec779b8eSAndroid Build Coastguard Worker               << " deviceVolume:" << deviceVolume
1075*ec779b8eSAndroid Build Coastguard Worker               << " packageName:" << packageName
1076*ec779b8eSAndroid Build Coastguard Worker               << " playbackPitch:" << playbackPitch
1077*ec779b8eSAndroid Build Coastguard Worker               << " playbackSpeed:" << playbackSpeed
1078*ec779b8eSAndroid Build Coastguard Worker               << " selectedDeviceId:" << selectedDeviceId
1079*ec779b8eSAndroid Build Coastguard Worker               << " streamType:" << streamType << "(" << streamTypeForStats
1080*ec779b8eSAndroid Build Coastguard Worker               << ") traits:" << traits << "(" << traitsForStats
1081*ec779b8eSAndroid Build Coastguard Worker               << ") usage:" << usage << "(" << usageForStats
1082*ec779b8eSAndroid Build Coastguard Worker               << ") logSessionId:" << logSessionId << "(" << logSessionIdForStats
1083*ec779b8eSAndroid Build Coastguard Worker               << ")";
1084*ec779b8eSAndroid Build Coastguard Worker         if (clientCalled // only log if client app called AudioTracks
1085*ec779b8eSAndroid Build Coastguard Worker                 && mAudioAnalytics.mDeliverStatistics) {
1086*ec779b8eSAndroid Build Coastguard Worker             const auto [ result, str ] = sendToStatsd(AudioTrackDeviceUsageFields,
1087*ec779b8eSAndroid Build Coastguard Worker                     CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
1088*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(outputDeviceStatsd)
1089*ec779b8eSAndroid Build Coastguard Worker                     , outputDeviceNames.c_str()
1090*ec779b8eSAndroid Build Coastguard Worker                     , deviceTimeNs
1091*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(encodingForStats)
1092*ec779b8eSAndroid Build Coastguard Worker                     , frameCount
1093*ec779b8eSAndroid Build Coastguard Worker                     , intervalCount
1094*ec779b8eSAndroid Build Coastguard Worker                     , sampleRate
1095*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(flagsForStats)
1096*ec779b8eSAndroid Build Coastguard Worker                     , underrun
1097*ec779b8eSAndroid Build Coastguard Worker                     , packageName.c_str()
1098*ec779b8eSAndroid Build Coastguard Worker                     , (float)deviceLatencyMs
1099*ec779b8eSAndroid Build Coastguard Worker                     , (float)deviceStartupMs
1100*ec779b8eSAndroid Build Coastguard Worker                     , (float)deviceVolume
1101*ec779b8eSAndroid Build Coastguard Worker                     , selectedDeviceId
1102*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(streamTypeForStats)
1103*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(usageForStats)
1104*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(contentTypeForStats)
1105*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(callerNameForStats)
1106*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(traitsForStats)
1107*ec779b8eSAndroid Build Coastguard Worker                     , logSessionIdForStats.c_str()
1108*ec779b8eSAndroid Build Coastguard Worker                     );
1109*ec779b8eSAndroid Build Coastguard Worker             ALOGV("%s: statsd %s", __func__, str.c_str());
1110*ec779b8eSAndroid Build Coastguard Worker             mAudioAnalytics.mStatsdLog->log(
1111*ec779b8eSAndroid Build Coastguard Worker                     stats::media_metrics::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED, str);
1112*ec779b8eSAndroid Build Coastguard Worker         }
1113*ec779b8eSAndroid Build Coastguard Worker         } break;
1114*ec779b8eSAndroid Build Coastguard Worker     }
1115*ec779b8eSAndroid Build Coastguard Worker }
1116*ec779b8eSAndroid Build Coastguard Worker 
1117*ec779b8eSAndroid Build Coastguard Worker // DeviceConnection helper class.
a2dpConnected(const std::shared_ptr<const android::mediametrics::Item> & item)1118*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::DeviceConnection::a2dpConnected(
1119*ec779b8eSAndroid Build Coastguard Worker        const std::shared_ptr<const android::mediametrics::Item> &item) {
1120*ec779b8eSAndroid Build Coastguard Worker     const std::string& key = item->getKey();
1121*ec779b8eSAndroid Build Coastguard Worker     const int64_t atNs = item->getTimestamp();
1122*ec779b8eSAndroid Build Coastguard Worker     {
1123*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard l(mLock);
1124*ec779b8eSAndroid Build Coastguard Worker         mA2dpConnectionServiceNs = atNs;
1125*ec779b8eSAndroid Build Coastguard Worker         ++mA2dpConnectionServices;
1126*ec779b8eSAndroid Build Coastguard Worker 
1127*ec779b8eSAndroid Build Coastguard Worker         if (mA2dpConnectionRequestNs == 0) {
1128*ec779b8eSAndroid Build Coastguard Worker             mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
1129*ec779b8eSAndroid Build Coastguard Worker         }
1130*ec779b8eSAndroid Build Coastguard Worker         // This sets the time we were connected.  Now we look for the delta in the future.
1131*ec779b8eSAndroid Build Coastguard Worker     }
1132*ec779b8eSAndroid Build Coastguard Worker     std::string name;
1133*ec779b8eSAndroid Build Coastguard Worker     item->get(AMEDIAMETRICS_PROP_NAME, &name);
1134*ec779b8eSAndroid Build Coastguard Worker     ALOGD("(key=%s) a2dp connected device:%s atNs:%lld",
1135*ec779b8eSAndroid Build Coastguard Worker             key.c_str(), name.c_str(), (long long)atNs);
1136*ec779b8eSAndroid Build Coastguard Worker }
1137*ec779b8eSAndroid Build Coastguard Worker 
createPatch(const std::shared_ptr<const android::mediametrics::Item> & item)1138*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::DeviceConnection::createPatch(
1139*ec779b8eSAndroid Build Coastguard Worker        const std::shared_ptr<const android::mediametrics::Item> &item) {
1140*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard l(mLock);
1141*ec779b8eSAndroid Build Coastguard Worker     if (mA2dpConnectionServiceNs == 0) return; // patch unrelated to us.
1142*ec779b8eSAndroid Build Coastguard Worker     const std::string& key = item->getKey();
1143*ec779b8eSAndroid Build Coastguard Worker     std::string outputDevices;
1144*ec779b8eSAndroid Build Coastguard Worker     item->get(AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices);
1145*ec779b8eSAndroid Build Coastguard Worker     if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH_A2DP") != std::string::npos) {
1146*ec779b8eSAndroid Build Coastguard Worker         // TODO compare address
1147*ec779b8eSAndroid Build Coastguard Worker         int64_t timeDiffNs = item->getTimestamp();
1148*ec779b8eSAndroid Build Coastguard Worker         if (mA2dpConnectionRequestNs == 0) {
1149*ec779b8eSAndroid Build Coastguard Worker             ALOGD("%s: A2DP create patch didn't see a connection request", __func__);
1150*ec779b8eSAndroid Build Coastguard Worker             timeDiffNs -= mA2dpConnectionServiceNs;
1151*ec779b8eSAndroid Build Coastguard Worker         } else {
1152*ec779b8eSAndroid Build Coastguard Worker             timeDiffNs -= mA2dpConnectionRequestNs;
1153*ec779b8eSAndroid Build Coastguard Worker         }
1154*ec779b8eSAndroid Build Coastguard Worker 
1155*ec779b8eSAndroid Build Coastguard Worker         mA2dpConnectionRequestNs = 0;
1156*ec779b8eSAndroid Build Coastguard Worker         mA2dpConnectionServiceNs = 0;
1157*ec779b8eSAndroid Build Coastguard Worker         ++mA2dpConnectionSuccesses;
1158*ec779b8eSAndroid Build Coastguard Worker 
1159*ec779b8eSAndroid Build Coastguard Worker         const auto connectionTimeMs = float((double)timeDiffNs * 1e-6);
1160*ec779b8eSAndroid Build Coastguard Worker 
1161*ec779b8eSAndroid Build Coastguard Worker         const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
1162*ec779b8eSAndroid Build Coastguard Worker                 "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
1163*ec779b8eSAndroid Build Coastguard Worker 
1164*ec779b8eSAndroid Build Coastguard Worker         LOG(LOG_LEVEL) << "key:" << key
1165*ec779b8eSAndroid Build Coastguard Worker                 << " A2DP SUCCESS"
1166*ec779b8eSAndroid Build Coastguard Worker                 << " outputDevices:" << outputDeviceBits
1167*ec779b8eSAndroid Build Coastguard Worker                 << " deviceName:" << mA2dpDeviceName
1168*ec779b8eSAndroid Build Coastguard Worker                 << " connectionTimeMs:" <<  connectionTimeMs;
1169*ec779b8eSAndroid Build Coastguard Worker         if (mAudioAnalytics.mDeliverStatistics) {
1170*ec779b8eSAndroid Build Coastguard Worker             const long_enum_type_t inputDeviceBits{};
1171*ec779b8eSAndroid Build Coastguard Worker 
1172*ec779b8eSAndroid Build Coastguard Worker             const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
1173*ec779b8eSAndroid Build Coastguard Worker                     CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
1174*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(inputDeviceBits)
1175*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(outputDeviceBits)
1176*ec779b8eSAndroid Build Coastguard Worker                     , mA2dpDeviceName.c_str()
1177*ec779b8eSAndroid Build Coastguard Worker                     , types::DEVICE_CONNECTION_RESULT_SUCCESS
1178*ec779b8eSAndroid Build Coastguard Worker                     , connectionTimeMs
1179*ec779b8eSAndroid Build Coastguard Worker                     , /* connection_count */ 1
1180*ec779b8eSAndroid Build Coastguard Worker                     );
1181*ec779b8eSAndroid Build Coastguard Worker             ALOGV("%s: statsd %s", __func__, str.c_str());
1182*ec779b8eSAndroid Build Coastguard Worker             mAudioAnalytics.mStatsdLog->log(
1183*ec779b8eSAndroid Build Coastguard Worker                     stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
1184*ec779b8eSAndroid Build Coastguard Worker         }
1185*ec779b8eSAndroid Build Coastguard Worker     }
1186*ec779b8eSAndroid Build Coastguard Worker }
1187*ec779b8eSAndroid Build Coastguard Worker 
1188*ec779b8eSAndroid Build Coastguard Worker // Called through AudioManager when the BT service wants to enable
postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(const std::shared_ptr<const android::mediametrics::Item> & item)1189*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::DeviceConnection::postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
1190*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<const android::mediametrics::Item> &item) {
1191*ec779b8eSAndroid Build Coastguard Worker     const int64_t atNs = item->getTimestamp();
1192*ec779b8eSAndroid Build Coastguard Worker     const std::string& key = item->getKey();
1193*ec779b8eSAndroid Build Coastguard Worker     std::string state;
1194*ec779b8eSAndroid Build Coastguard Worker     item->get(AMEDIAMETRICS_PROP_STATE, &state);
1195*ec779b8eSAndroid Build Coastguard Worker     if (state != "connected") return;
1196*ec779b8eSAndroid Build Coastguard Worker 
1197*ec779b8eSAndroid Build Coastguard Worker     std::string name;
1198*ec779b8eSAndroid Build Coastguard Worker     item->get(AMEDIAMETRICS_PROP_NAME, &name);
1199*ec779b8eSAndroid Build Coastguard Worker     {
1200*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard l(mLock);
1201*ec779b8eSAndroid Build Coastguard Worker         mA2dpConnectionRequestNs = atNs;
1202*ec779b8eSAndroid Build Coastguard Worker         ++mA2dpConnectionRequests;
1203*ec779b8eSAndroid Build Coastguard Worker         mA2dpDeviceName = SUPPRESSED; // TODO(b/161554630) sanitize name
1204*ec779b8eSAndroid Build Coastguard Worker     }
1205*ec779b8eSAndroid Build Coastguard Worker     ALOGD("(key=%s) a2dp connection name:%s request atNs:%lld",
1206*ec779b8eSAndroid Build Coastguard Worker             key.c_str(), name.c_str(), (long long)atNs);
1207*ec779b8eSAndroid Build Coastguard Worker     // TODO: attempt to cancel a timed event, rather than let it expire.
1208*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
1209*ec779b8eSAndroid Build Coastguard Worker }
1210*ec779b8eSAndroid Build Coastguard Worker 
expire()1211*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::DeviceConnection::expire() {
1212*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard l(mLock);
1213*ec779b8eSAndroid Build Coastguard Worker     if (mA2dpConnectionRequestNs == 0) return; // ignore (this was an internal connection).
1214*ec779b8eSAndroid Build Coastguard Worker 
1215*ec779b8eSAndroid Build Coastguard Worker     const long_enum_type_t inputDeviceBits{};
1216*ec779b8eSAndroid Build Coastguard Worker     const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
1217*ec779b8eSAndroid Build Coastguard Worker             "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
1218*ec779b8eSAndroid Build Coastguard Worker 
1219*ec779b8eSAndroid Build Coastguard Worker     if (mA2dpConnectionServiceNs == 0) {
1220*ec779b8eSAndroid Build Coastguard Worker         ++mA2dpConnectionJavaServiceCancels;  // service did not connect to A2DP
1221*ec779b8eSAndroid Build Coastguard Worker 
1222*ec779b8eSAndroid Build Coastguard Worker         LOG(LOG_LEVEL) << "A2DP CANCEL"
1223*ec779b8eSAndroid Build Coastguard Worker                 << " outputDevices:" << outputDeviceBits
1224*ec779b8eSAndroid Build Coastguard Worker                 << " deviceName:" << mA2dpDeviceName;
1225*ec779b8eSAndroid Build Coastguard Worker         if (mAudioAnalytics.mDeliverStatistics) {
1226*ec779b8eSAndroid Build Coastguard Worker             const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
1227*ec779b8eSAndroid Build Coastguard Worker                     CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
1228*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(inputDeviceBits)
1229*ec779b8eSAndroid Build Coastguard Worker                     , ENUM_EXTRACT(outputDeviceBits)
1230*ec779b8eSAndroid Build Coastguard Worker                     , mA2dpDeviceName.c_str()
1231*ec779b8eSAndroid Build Coastguard Worker                     , types::DEVICE_CONNECTION_RESULT_JAVA_SERVICE_CANCEL
1232*ec779b8eSAndroid Build Coastguard Worker                     , /* connection_time_ms */ 0.f
1233*ec779b8eSAndroid Build Coastguard Worker                     , /* connection_count */ 1
1234*ec779b8eSAndroid Build Coastguard Worker                     );
1235*ec779b8eSAndroid Build Coastguard Worker             ALOGV("%s: statsd %s", __func__, str.c_str());
1236*ec779b8eSAndroid Build Coastguard Worker             mAudioAnalytics.mStatsdLog->log(
1237*ec779b8eSAndroid Build Coastguard Worker                     stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
1238*ec779b8eSAndroid Build Coastguard Worker         }
1239*ec779b8eSAndroid Build Coastguard Worker         return;
1240*ec779b8eSAndroid Build Coastguard Worker     }
1241*ec779b8eSAndroid Build Coastguard Worker 
1242*ec779b8eSAndroid Build Coastguard Worker     // AudioFlinger didn't play - an expiration may occur because there is no audio playing.
1243*ec779b8eSAndroid Build Coastguard Worker     // Should we check elsewhere?
1244*ec779b8eSAndroid Build Coastguard Worker     // TODO: disambiguate this case.
1245*ec779b8eSAndroid Build Coastguard Worker     mA2dpConnectionRequestNs = 0;
1246*ec779b8eSAndroid Build Coastguard Worker     mA2dpConnectionServiceNs = 0;
1247*ec779b8eSAndroid Build Coastguard Worker     ++mA2dpConnectionUnknowns;  // connection result unknown
1248*ec779b8eSAndroid Build Coastguard Worker 
1249*ec779b8eSAndroid Build Coastguard Worker     LOG(LOG_LEVEL) << "A2DP UNKNOWN"
1250*ec779b8eSAndroid Build Coastguard Worker             << " outputDevices:" << outputDeviceBits
1251*ec779b8eSAndroid Build Coastguard Worker             << " deviceName:" << mA2dpDeviceName;
1252*ec779b8eSAndroid Build Coastguard Worker     if (mAudioAnalytics.mDeliverStatistics) {
1253*ec779b8eSAndroid Build Coastguard Worker         const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
1254*ec779b8eSAndroid Build Coastguard Worker                 CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
1255*ec779b8eSAndroid Build Coastguard Worker                 , ENUM_EXTRACT(inputDeviceBits)
1256*ec779b8eSAndroid Build Coastguard Worker                 , ENUM_EXTRACT(outputDeviceBits)
1257*ec779b8eSAndroid Build Coastguard Worker                 , mA2dpDeviceName.c_str()
1258*ec779b8eSAndroid Build Coastguard Worker                 , types::DEVICE_CONNECTION_RESULT_UNKNOWN
1259*ec779b8eSAndroid Build Coastguard Worker                 , /* connection_time_ms */ 0.f
1260*ec779b8eSAndroid Build Coastguard Worker                 , /* connection_count */ 1
1261*ec779b8eSAndroid Build Coastguard Worker                 );
1262*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: statsd %s", __func__, str.c_str());
1263*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mStatsdLog->log(
1264*ec779b8eSAndroid Build Coastguard Worker                 stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
1265*ec779b8eSAndroid Build Coastguard Worker     }
1266*ec779b8eSAndroid Build Coastguard Worker }
1267*ec779b8eSAndroid Build Coastguard Worker 
endAAudioStream(const std::shared_ptr<const android::mediametrics::Item> & item,CallerPath path) const1268*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::AAudioStreamInfo::endAAudioStream(
1269*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<const android::mediametrics::Item> &item, CallerPath path) const {
1270*ec779b8eSAndroid Build Coastguard Worker     const std::string& key = item->getKey();
1271*ec779b8eSAndroid Build Coastguard Worker 
1272*ec779b8eSAndroid Build Coastguard Worker     std::string directionStr;
1273*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1274*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_DIRECTION, &directionStr);
1275*ec779b8eSAndroid Build Coastguard Worker     const auto direction = types::lookup<types::AAUDIO_DIRECTION, int32_t>(directionStr);
1276*ec779b8eSAndroid Build Coastguard Worker 
1277*ec779b8eSAndroid Build Coastguard Worker     int32_t framesPerBurst = -1;
1278*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1279*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_BURSTFRAMES, &framesPerBurst);
1280*ec779b8eSAndroid Build Coastguard Worker 
1281*ec779b8eSAndroid Build Coastguard Worker     int32_t bufferSizeInFrames = -1;
1282*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1283*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, &bufferSizeInFrames);
1284*ec779b8eSAndroid Build Coastguard Worker 
1285*ec779b8eSAndroid Build Coastguard Worker     int32_t bufferCapacityInFrames = -1;
1286*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1287*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, &bufferCapacityInFrames);
1288*ec779b8eSAndroid Build Coastguard Worker 
1289*ec779b8eSAndroid Build Coastguard Worker     int32_t channelCount = -1;
1290*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1291*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_CHANNELCOUNT, &channelCount);
1292*ec779b8eSAndroid Build Coastguard Worker     if (channelCount == -1) {
1293*ec779b8eSAndroid Build Coastguard Worker         // Try to get channel count from channel mask. From the legacy path,
1294*ec779b8eSAndroid Build Coastguard Worker         // only channel mask are logged.
1295*ec779b8eSAndroid Build Coastguard Worker         int32_t channelMask = 0;
1296*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1297*ec779b8eSAndroid Build Coastguard Worker                 key, AMEDIAMETRICS_PROP_CHANNELMASK, &channelMask);
1298*ec779b8eSAndroid Build Coastguard Worker         if (channelMask != 0) {
1299*ec779b8eSAndroid Build Coastguard Worker             switch (direction) {
1300*ec779b8eSAndroid Build Coastguard Worker                 case 1: // Output, keep sync with AudioTypes#getAAudioDirection()
1301*ec779b8eSAndroid Build Coastguard Worker                     channelCount = (int32_t)audio_channel_count_from_out_mask(channelMask);
1302*ec779b8eSAndroid Build Coastguard Worker                     break;
1303*ec779b8eSAndroid Build Coastguard Worker                 case 2: // Input, keep sync with AudioTypes#getAAudioDirection()
1304*ec779b8eSAndroid Build Coastguard Worker                     channelCount = (int32_t)audio_channel_count_from_in_mask(channelMask);
1305*ec779b8eSAndroid Build Coastguard Worker                     break;
1306*ec779b8eSAndroid Build Coastguard Worker                 default:
1307*ec779b8eSAndroid Build Coastguard Worker                     ALOGW("Invalid direction %d", direction);
1308*ec779b8eSAndroid Build Coastguard Worker             }
1309*ec779b8eSAndroid Build Coastguard Worker         }
1310*ec779b8eSAndroid Build Coastguard Worker     }
1311*ec779b8eSAndroid Build Coastguard Worker 
1312*ec779b8eSAndroid Build Coastguard Worker     int64_t totalFramesTransferred = -1;
1313*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1314*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_FRAMESTRANSFERRED, &totalFramesTransferred);
1315*ec779b8eSAndroid Build Coastguard Worker 
1316*ec779b8eSAndroid Build Coastguard Worker     std::string perfModeRequestedStr;
1317*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1318*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_PERFORMANCEMODE, &perfModeRequestedStr);
1319*ec779b8eSAndroid Build Coastguard Worker     const auto perfModeRequested =
1320*ec779b8eSAndroid Build Coastguard Worker             types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeRequestedStr);
1321*ec779b8eSAndroid Build Coastguard Worker 
1322*ec779b8eSAndroid Build Coastguard Worker     std::string perfModeActualStr;
1323*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1324*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL, &perfModeActualStr);
1325*ec779b8eSAndroid Build Coastguard Worker     const auto perfModeActual =
1326*ec779b8eSAndroid Build Coastguard Worker             types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeActualStr);
1327*ec779b8eSAndroid Build Coastguard Worker 
1328*ec779b8eSAndroid Build Coastguard Worker     std::string sharingModeActualStr;
1329*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1330*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_SHARINGMODEACTUAL, &sharingModeActualStr);
1331*ec779b8eSAndroid Build Coastguard Worker     const auto sharingModeActual =
1332*ec779b8eSAndroid Build Coastguard Worker             types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeActualStr);
1333*ec779b8eSAndroid Build Coastguard Worker 
1334*ec779b8eSAndroid Build Coastguard Worker     int32_t xrunCount = -1;
1335*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1336*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_UNDERRUN, &xrunCount);
1337*ec779b8eSAndroid Build Coastguard Worker 
1338*ec779b8eSAndroid Build Coastguard Worker     std::string serializedDeviceTypes;
1339*ec779b8eSAndroid Build Coastguard Worker     // TODO: only routed device id is logged, but no device type
1340*ec779b8eSAndroid Build Coastguard Worker 
1341*ec779b8eSAndroid Build Coastguard Worker     std::string formatAppStr;
1342*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1343*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_ENCODINGCLIENT, &formatAppStr);
1344*ec779b8eSAndroid Build Coastguard Worker     const auto formatApp = types::lookup<types::ENCODING, int32_t>(formatAppStr);
1345*ec779b8eSAndroid Build Coastguard Worker 
1346*ec779b8eSAndroid Build Coastguard Worker     std::string formatDeviceStr;
1347*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1348*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_ENCODING, &formatDeviceStr);
1349*ec779b8eSAndroid Build Coastguard Worker     const auto formatDevice = types::lookup<types::ENCODING, int32_t>(formatDeviceStr);
1350*ec779b8eSAndroid Build Coastguard Worker 
1351*ec779b8eSAndroid Build Coastguard Worker     std::string logSessionId;
1352*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1353*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
1354*ec779b8eSAndroid Build Coastguard Worker 
1355*ec779b8eSAndroid Build Coastguard Worker     int32_t sampleRate = 0;
1356*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1357*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
1358*ec779b8eSAndroid Build Coastguard Worker 
1359*ec779b8eSAndroid Build Coastguard Worker     std::string contentTypeStr;
1360*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1361*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentTypeStr);
1362*ec779b8eSAndroid Build Coastguard Worker     const auto contentType = types::lookup<types::CONTENT_TYPE, int32_t>(contentTypeStr);
1363*ec779b8eSAndroid Build Coastguard Worker 
1364*ec779b8eSAndroid Build Coastguard Worker     std::string sharingModeRequestedStr;
1365*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1366*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_SHARINGMODE, &sharingModeRequestedStr);
1367*ec779b8eSAndroid Build Coastguard Worker     const auto sharingModeRequested =
1368*ec779b8eSAndroid Build Coastguard Worker             types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeRequestedStr);
1369*ec779b8eSAndroid Build Coastguard Worker 
1370*ec779b8eSAndroid Build Coastguard Worker     std::string formatHardwareStr;
1371*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1372*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_ENCODINGHARDWARE, &formatHardwareStr);
1373*ec779b8eSAndroid Build Coastguard Worker     const auto formatHardware = types::lookup<types::ENCODING, int32_t>(formatHardwareStr);
1374*ec779b8eSAndroid Build Coastguard Worker 
1375*ec779b8eSAndroid Build Coastguard Worker     int32_t channelCountHardware = -1;
1376*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1377*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_CHANNELCOUNTHARDWARE, &channelCountHardware);
1378*ec779b8eSAndroid Build Coastguard Worker 
1379*ec779b8eSAndroid Build Coastguard Worker     int32_t sampleRateHardware = 0;
1380*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1381*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_SAMPLERATEHARDWARE, &sampleRateHardware);
1382*ec779b8eSAndroid Build Coastguard Worker 
1383*ec779b8eSAndroid Build Coastguard Worker     const auto uid = item->getUid();
1384*ec779b8eSAndroid Build Coastguard Worker 
1385*ec779b8eSAndroid Build Coastguard Worker     int32_t sampleRateClient = 0;
1386*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1387*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_SAMPLERATECLIENT, &sampleRateClient);
1388*ec779b8eSAndroid Build Coastguard Worker 
1389*ec779b8eSAndroid Build Coastguard Worker     LOG(LOG_LEVEL) << "key:" << key
1390*ec779b8eSAndroid Build Coastguard Worker             << " path:" << path
1391*ec779b8eSAndroid Build Coastguard Worker             << " direction:" << direction << "(" << directionStr << ")"
1392*ec779b8eSAndroid Build Coastguard Worker             << " frames_per_burst:" << framesPerBurst
1393*ec779b8eSAndroid Build Coastguard Worker             << " buffer_size:" << bufferSizeInFrames
1394*ec779b8eSAndroid Build Coastguard Worker             << " buffer_capacity:" << bufferCapacityInFrames
1395*ec779b8eSAndroid Build Coastguard Worker             << " channel_count:" << channelCount
1396*ec779b8eSAndroid Build Coastguard Worker             << " total_frames_transferred:" << totalFramesTransferred
1397*ec779b8eSAndroid Build Coastguard Worker             << " perf_mode_requested:" << perfModeRequested << "(" << perfModeRequestedStr << ")"
1398*ec779b8eSAndroid Build Coastguard Worker             << " perf_mode_actual:" << perfModeActual << "(" << perfModeActualStr << ")"
1399*ec779b8eSAndroid Build Coastguard Worker             << " sharing:" << sharingModeActual << "(" << sharingModeActualStr << ")"
1400*ec779b8eSAndroid Build Coastguard Worker             << " xrun_count:" << xrunCount
1401*ec779b8eSAndroid Build Coastguard Worker             << " device_type:" << serializedDeviceTypes
1402*ec779b8eSAndroid Build Coastguard Worker             << " format_app:" << formatApp << "(" << formatAppStr << ")"
1403*ec779b8eSAndroid Build Coastguard Worker             << " format_device: " << formatDevice << "(" << formatDeviceStr << ")"
1404*ec779b8eSAndroid Build Coastguard Worker             << " log_session_id: " << logSessionId
1405*ec779b8eSAndroid Build Coastguard Worker             << " sample_rate: " << sampleRate
1406*ec779b8eSAndroid Build Coastguard Worker             << " content_type: " << contentType << "(" << contentTypeStr << ")"
1407*ec779b8eSAndroid Build Coastguard Worker             << " sharing_requested:" << sharingModeRequested
1408*ec779b8eSAndroid Build Coastguard Worker                     << "(" << sharingModeRequestedStr << ")"
1409*ec779b8eSAndroid Build Coastguard Worker             << " format_hardware:" << formatHardware << "(" << formatHardwareStr << ")"
1410*ec779b8eSAndroid Build Coastguard Worker             << " channel_count_hardware:" << channelCountHardware
1411*ec779b8eSAndroid Build Coastguard Worker             << " sample_rate_hardware: " << sampleRateHardware
1412*ec779b8eSAndroid Build Coastguard Worker             << " uid: " << uid
1413*ec779b8eSAndroid Build Coastguard Worker             << " sample_rate_client: " << sampleRateClient;
1414*ec779b8eSAndroid Build Coastguard Worker 
1415*ec779b8eSAndroid Build Coastguard Worker     if (mAudioAnalytics.mDeliverStatistics) {
1416*ec779b8eSAndroid Build Coastguard Worker         const stats::media_metrics::BytesField bf_serialized(
1417*ec779b8eSAndroid Build Coastguard Worker             serializedDeviceTypes.c_str(), serializedDeviceTypes.size());
1418*ec779b8eSAndroid Build Coastguard Worker         const auto result = sendToStatsd(
1419*ec779b8eSAndroid Build Coastguard Worker                 CONDITION(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
1420*ec779b8eSAndroid Build Coastguard Worker                 , path
1421*ec779b8eSAndroid Build Coastguard Worker                 , direction
1422*ec779b8eSAndroid Build Coastguard Worker                 , framesPerBurst
1423*ec779b8eSAndroid Build Coastguard Worker                 , bufferSizeInFrames
1424*ec779b8eSAndroid Build Coastguard Worker                 , bufferCapacityInFrames
1425*ec779b8eSAndroid Build Coastguard Worker                 , channelCount
1426*ec779b8eSAndroid Build Coastguard Worker                 , totalFramesTransferred
1427*ec779b8eSAndroid Build Coastguard Worker                 , perfModeRequested
1428*ec779b8eSAndroid Build Coastguard Worker                 , perfModeActual
1429*ec779b8eSAndroid Build Coastguard Worker                 , sharingModeActual
1430*ec779b8eSAndroid Build Coastguard Worker                 , xrunCount
1431*ec779b8eSAndroid Build Coastguard Worker                 , bf_serialized
1432*ec779b8eSAndroid Build Coastguard Worker                 , formatApp
1433*ec779b8eSAndroid Build Coastguard Worker                 , formatDevice
1434*ec779b8eSAndroid Build Coastguard Worker                 , logSessionId.c_str()
1435*ec779b8eSAndroid Build Coastguard Worker                 , sampleRate
1436*ec779b8eSAndroid Build Coastguard Worker                 , contentType
1437*ec779b8eSAndroid Build Coastguard Worker                 , sharingModeRequested
1438*ec779b8eSAndroid Build Coastguard Worker                 , formatHardware
1439*ec779b8eSAndroid Build Coastguard Worker                 , channelCountHardware
1440*ec779b8eSAndroid Build Coastguard Worker                 , sampleRateHardware
1441*ec779b8eSAndroid Build Coastguard Worker                 , uid
1442*ec779b8eSAndroid Build Coastguard Worker                 , sampleRateClient
1443*ec779b8eSAndroid Build Coastguard Worker                 );
1444*ec779b8eSAndroid Build Coastguard Worker         std::stringstream ss;
1445*ec779b8eSAndroid Build Coastguard Worker         ss << "result:" << result;
1446*ec779b8eSAndroid Build Coastguard Worker         const auto fieldsStr = printFields(AAudioStreamFields,
1447*ec779b8eSAndroid Build Coastguard Worker                 CONDITION(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
1448*ec779b8eSAndroid Build Coastguard Worker                 , path
1449*ec779b8eSAndroid Build Coastguard Worker                 , direction
1450*ec779b8eSAndroid Build Coastguard Worker                 , framesPerBurst
1451*ec779b8eSAndroid Build Coastguard Worker                 , bufferSizeInFrames
1452*ec779b8eSAndroid Build Coastguard Worker                 , bufferCapacityInFrames
1453*ec779b8eSAndroid Build Coastguard Worker                 , channelCount
1454*ec779b8eSAndroid Build Coastguard Worker                 , totalFramesTransferred
1455*ec779b8eSAndroid Build Coastguard Worker                 , perfModeRequested
1456*ec779b8eSAndroid Build Coastguard Worker                 , perfModeActual
1457*ec779b8eSAndroid Build Coastguard Worker                 , sharingModeActual
1458*ec779b8eSAndroid Build Coastguard Worker                 , xrunCount
1459*ec779b8eSAndroid Build Coastguard Worker                 , serializedDeviceTypes.c_str()
1460*ec779b8eSAndroid Build Coastguard Worker                 , formatApp
1461*ec779b8eSAndroid Build Coastguard Worker                 , formatDevice
1462*ec779b8eSAndroid Build Coastguard Worker                 , logSessionId.c_str()
1463*ec779b8eSAndroid Build Coastguard Worker                 , sampleRate
1464*ec779b8eSAndroid Build Coastguard Worker                 , contentType
1465*ec779b8eSAndroid Build Coastguard Worker                 , sharingModeRequested
1466*ec779b8eSAndroid Build Coastguard Worker                 , formatHardware
1467*ec779b8eSAndroid Build Coastguard Worker                 , channelCountHardware
1468*ec779b8eSAndroid Build Coastguard Worker                 , sampleRateHardware
1469*ec779b8eSAndroid Build Coastguard Worker                 , uid
1470*ec779b8eSAndroid Build Coastguard Worker                 , sampleRateClient
1471*ec779b8eSAndroid Build Coastguard Worker                 );
1472*ec779b8eSAndroid Build Coastguard Worker         ss << " " << fieldsStr;
1473*ec779b8eSAndroid Build Coastguard Worker         std::string str = ss.str();
1474*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: statsd %s", __func__, str.c_str());
1475*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED, str);
1476*ec779b8eSAndroid Build Coastguard Worker     }
1477*ec779b8eSAndroid Build Coastguard Worker }
1478*ec779b8eSAndroid Build Coastguard Worker 
1479*ec779b8eSAndroid Build Coastguard Worker // Create new state, typically occurs after an AudioFlinger ctor event.
newState()1480*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::newState()
1481*ec779b8eSAndroid Build Coastguard Worker {
1482*ec779b8eSAndroid Build Coastguard Worker     mPreviousAnalyticsState.set(std::make_shared<AnalyticsState>(
1483*ec779b8eSAndroid Build Coastguard Worker             *mAnalyticsState.get()));
1484*ec779b8eSAndroid Build Coastguard Worker     // Note: get returns shared_ptr temp, whose lifetime is extended
1485*ec779b8eSAndroid Build Coastguard Worker     // to end of full expression.
1486*ec779b8eSAndroid Build Coastguard Worker     mAnalyticsState->clear();  // TODO: filter the analytics state.
1487*ec779b8eSAndroid Build Coastguard Worker     // Perhaps report this.
1488*ec779b8eSAndroid Build Coastguard Worker 
1489*ec779b8eSAndroid Build Coastguard Worker     // Set up a timer to expire the previous audio state to save space.
1490*ec779b8eSAndroid Build Coastguard Worker     // Use the transaction log size as a cookie to see if it is the
1491*ec779b8eSAndroid Build Coastguard Worker     // same as before.  A benign race is possible where a state is cleared early.
1492*ec779b8eSAndroid Build Coastguard Worker     const size_t size = mPreviousAnalyticsState->transactionLog().size();
1493*ec779b8eSAndroid Build Coastguard Worker     mTimedAction.postIn(
1494*ec779b8eSAndroid Build Coastguard Worker             std::chrono::seconds(PREVIOUS_STATE_EXPIRE_SEC), [this, size](){
1495*ec779b8eSAndroid Build Coastguard Worker         if (mPreviousAnalyticsState->transactionLog().size() == size) {
1496*ec779b8eSAndroid Build Coastguard Worker             ALOGD("expiring previous audio state after %d seconds.",
1497*ec779b8eSAndroid Build Coastguard Worker                     PREVIOUS_STATE_EXPIRE_SEC);
1498*ec779b8eSAndroid Build Coastguard Worker             mPreviousAnalyticsState->clear();  // removes data from the state.
1499*ec779b8eSAndroid Build Coastguard Worker         }
1500*ec779b8eSAndroid Build Coastguard Worker     });
1501*ec779b8eSAndroid Build Coastguard Worker }
1502*ec779b8eSAndroid Build Coastguard Worker 
onAudioServerStart(Module module,const std::shared_ptr<const android::mediametrics::Item> & item)1503*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::Health::onAudioServerStart(Module module,
1504*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<const android::mediametrics::Item> &item)
1505*ec779b8eSAndroid Build Coastguard Worker {
1506*ec779b8eSAndroid Build Coastguard Worker     const auto nowTime = std::chrono::system_clock::now();
1507*ec779b8eSAndroid Build Coastguard Worker     if (module == Module::AUDIOFLINGER) {
1508*ec779b8eSAndroid Build Coastguard Worker        {
1509*ec779b8eSAndroid Build Coastguard Worker             std::lock_guard lg(mLock);
1510*ec779b8eSAndroid Build Coastguard Worker             // reset state on AudioFlinger construction.
1511*ec779b8eSAndroid Build Coastguard Worker             // AudioPolicy is created after AudioFlinger.
1512*ec779b8eSAndroid Build Coastguard Worker             mAudioFlingerCtorTime = nowTime;
1513*ec779b8eSAndroid Build Coastguard Worker             mSimpleLog.log("AudioFlinger ctor");
1514*ec779b8eSAndroid Build Coastguard Worker         }
1515*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.newState();
1516*ec779b8eSAndroid Build Coastguard Worker         return;
1517*ec779b8eSAndroid Build Coastguard Worker     }
1518*ec779b8eSAndroid Build Coastguard Worker     if (module == Module::AUDIOPOLICY) {
1519*ec779b8eSAndroid Build Coastguard Worker         // A start event occurs when audioserver
1520*ec779b8eSAndroid Build Coastguard Worker         //
1521*ec779b8eSAndroid Build Coastguard Worker         // (1) Starts the first time
1522*ec779b8eSAndroid Build Coastguard Worker         // (2) Restarts because of the TimeCheck watchdog
1523*ec779b8eSAndroid Build Coastguard Worker         // (3) Restarts not because of the TimeCheck watchdog.
1524*ec779b8eSAndroid Build Coastguard Worker         int64_t executionTimeNs = 0;
1525*ec779b8eSAndroid Build Coastguard Worker         (void)item->get(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, &executionTimeNs);
1526*ec779b8eSAndroid Build Coastguard Worker         const float loadTimeMs = executionTimeNs * 1e-6f;
1527*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard lg(mLock);
1528*ec779b8eSAndroid Build Coastguard Worker         const int64_t restarts = mStartCount;
1529*ec779b8eSAndroid Build Coastguard Worker         if (mStopCount == mStartCount) {
1530*ec779b8eSAndroid Build Coastguard Worker             mAudioPolicyCtorTime = nowTime;
1531*ec779b8eSAndroid Build Coastguard Worker             ++mStartCount;
1532*ec779b8eSAndroid Build Coastguard Worker             if (mStopCount == 0) {
1533*ec779b8eSAndroid Build Coastguard Worker                 // (1) First time initialization.
1534*ec779b8eSAndroid Build Coastguard Worker                 ALOGW("%s: (key=%s) AudioPolicy ctor, loadTimeMs:%f",
1535*ec779b8eSAndroid Build Coastguard Worker                         __func__, item->getKey().c_str(), loadTimeMs);
1536*ec779b8eSAndroid Build Coastguard Worker                 mSimpleLog.log("AudioPolicy ctor, loadTimeMs:%f", loadTimeMs);
1537*ec779b8eSAndroid Build Coastguard Worker             } else {
1538*ec779b8eSAndroid Build Coastguard Worker                 // (2) Previous failure caught due to TimeCheck.  We know how long restart takes.
1539*ec779b8eSAndroid Build Coastguard Worker                 const float restartMs =
1540*ec779b8eSAndroid Build Coastguard Worker                         std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(
1541*ec779b8eSAndroid Build Coastguard Worker                                 mAudioFlingerCtorTime - mStopTime).count();
1542*ec779b8eSAndroid Build Coastguard Worker                 ALOGW("%s: (key=%s) AudioPolicy ctor, "
1543*ec779b8eSAndroid Build Coastguard Worker                         "restarts:%lld restartMs:%f loadTimeMs:%f",
1544*ec779b8eSAndroid Build Coastguard Worker                         __func__, item->getKey().c_str(),
1545*ec779b8eSAndroid Build Coastguard Worker                         (long long)restarts, restartMs, loadTimeMs);
1546*ec779b8eSAndroid Build Coastguard Worker                 mSimpleLog.log("AudioPolicy ctor restarts:%lld restartMs:%f loadTimeMs:%f",
1547*ec779b8eSAndroid Build Coastguard Worker                         (long long)restarts, restartMs, loadTimeMs);
1548*ec779b8eSAndroid Build Coastguard Worker             }
1549*ec779b8eSAndroid Build Coastguard Worker         } else {
1550*ec779b8eSAndroid Build Coastguard Worker             // (3) Previous failure is NOT due to TimeCheck, so we don't know the restart time.
1551*ec779b8eSAndroid Build Coastguard Worker             // However we can estimate the uptime from the delta time from previous ctor.
1552*ec779b8eSAndroid Build Coastguard Worker             const float uptimeMs =
1553*ec779b8eSAndroid Build Coastguard Worker                     std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(
1554*ec779b8eSAndroid Build Coastguard Worker                             nowTime - mAudioFlingerCtorTime).count();
1555*ec779b8eSAndroid Build Coastguard Worker             mStopCount = mStartCount;
1556*ec779b8eSAndroid Build Coastguard Worker             mAudioPolicyCtorTime = nowTime;
1557*ec779b8eSAndroid Build Coastguard Worker             ++mStartCount;
1558*ec779b8eSAndroid Build Coastguard Worker 
1559*ec779b8eSAndroid Build Coastguard Worker             ALOGW("%s: (key=%s) AudioPolicy ctor after uncaught failure, "
1560*ec779b8eSAndroid Build Coastguard Worker                     "mStartCount:%lld mStopCount:%lld uptimeMs:%f loadTimeMs:%f",
1561*ec779b8eSAndroid Build Coastguard Worker                     __func__, item->getKey().c_str(),
1562*ec779b8eSAndroid Build Coastguard Worker                     (long long)mStartCount, (long long)mStopCount, uptimeMs, loadTimeMs);
1563*ec779b8eSAndroid Build Coastguard Worker             mSimpleLog.log("AudioPolicy ctor after uncaught failure, "
1564*ec779b8eSAndroid Build Coastguard Worker                     "restarts:%lld uptimeMs:%f loadTimeMs:%f",
1565*ec779b8eSAndroid Build Coastguard Worker                     (long long)restarts, uptimeMs, loadTimeMs);
1566*ec779b8eSAndroid Build Coastguard Worker         }
1567*ec779b8eSAndroid Build Coastguard Worker     }
1568*ec779b8eSAndroid Build Coastguard Worker }
1569*ec779b8eSAndroid Build Coastguard Worker 
onAudioServerTimeout(Module module,const std::shared_ptr<const android::mediametrics::Item> & item)1570*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::Health::onAudioServerTimeout(Module module,
1571*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<const android::mediametrics::Item> &item)
1572*ec779b8eSAndroid Build Coastguard Worker {
1573*ec779b8eSAndroid Build Coastguard Worker     std::string moduleName = getModuleName(module);
1574*ec779b8eSAndroid Build Coastguard Worker     int64_t methodCode{};
1575*ec779b8eSAndroid Build Coastguard Worker     std::string methodName;
1576*ec779b8eSAndroid Build Coastguard Worker     (void)item->get(AMEDIAMETRICS_PROP_METHODCODE, &methodCode);
1577*ec779b8eSAndroid Build Coastguard Worker     (void)item->get(AMEDIAMETRICS_PROP_METHODNAME, &methodName);
1578*ec779b8eSAndroid Build Coastguard Worker 
1579*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard lg(mLock);
1580*ec779b8eSAndroid Build Coastguard Worker     if (mStopCount >= mStartCount) {
1581*ec779b8eSAndroid Build Coastguard Worker         ALOGD("%s: (key=%s) %s timeout %s(%lld) "
1582*ec779b8eSAndroid Build Coastguard Worker             "unmatched mStopCount(%lld) >= mStartCount(%lld), ignoring",
1583*ec779b8eSAndroid Build Coastguard Worker             __func__, item->getKey().c_str(), moduleName.c_str(),
1584*ec779b8eSAndroid Build Coastguard Worker             methodName.c_str(), (long long)methodCode,
1585*ec779b8eSAndroid Build Coastguard Worker             (long long)mStopCount, (long long)mStartCount);
1586*ec779b8eSAndroid Build Coastguard Worker         return;
1587*ec779b8eSAndroid Build Coastguard Worker     }
1588*ec779b8eSAndroid Build Coastguard Worker 
1589*ec779b8eSAndroid Build Coastguard Worker     const int64_t restarts = mStartCount - 1;
1590*ec779b8eSAndroid Build Coastguard Worker     ++mStopCount;
1591*ec779b8eSAndroid Build Coastguard Worker     mStopTime = std::chrono::system_clock::now();
1592*ec779b8eSAndroid Build Coastguard Worker     const float uptimeMs = std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(
1593*ec779b8eSAndroid Build Coastguard Worker             mStopTime - mAudioFlingerCtorTime).count();
1594*ec779b8eSAndroid Build Coastguard Worker     ALOGW("%s: (key=%s) %s timeout %s(%lld) restarts:%lld uptimeMs:%f",
1595*ec779b8eSAndroid Build Coastguard Worker          __func__, item->getKey().c_str(), moduleName.c_str(),
1596*ec779b8eSAndroid Build Coastguard Worker          methodName.c_str(), (long long)methodCode,
1597*ec779b8eSAndroid Build Coastguard Worker          (long long)restarts, uptimeMs);
1598*ec779b8eSAndroid Build Coastguard Worker     mSimpleLog.log("%s timeout %s(%lld) restarts:%lld uptimeMs:%f",
1599*ec779b8eSAndroid Build Coastguard Worker             moduleName.c_str(), methodName.c_str(), (long long)methodCode,
1600*ec779b8eSAndroid Build Coastguard Worker             (long long)restarts, uptimeMs);
1601*ec779b8eSAndroid Build Coastguard Worker }
1602*ec779b8eSAndroid Build Coastguard Worker 
dump(int32_t lines,const char * prefix) const1603*ec779b8eSAndroid Build Coastguard Worker std::pair<std::string, int32_t> AudioAnalytics::Health::dump(
1604*ec779b8eSAndroid Build Coastguard Worker         int32_t lines, const char *prefix) const
1605*ec779b8eSAndroid Build Coastguard Worker {
1606*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard lg(mLock);
1607*ec779b8eSAndroid Build Coastguard Worker     std::string s = mSimpleLog.dumpToString(prefix == nullptr ? "" : prefix, lines);
1608*ec779b8eSAndroid Build Coastguard Worker     size_t n = std::count(s.begin(), s.end(), '\n');
1609*ec779b8eSAndroid Build Coastguard Worker     return { s, n };
1610*ec779b8eSAndroid Build Coastguard Worker }
1611*ec779b8eSAndroid Build Coastguard Worker 
1612*ec779b8eSAndroid Build Coastguard Worker // Classifies the setting event for statsd (use generated statsd enums.proto constants).
classifySettingEvent(bool isSetAlready,bool withinBoot)1613*ec779b8eSAndroid Build Coastguard Worker static int32_t classifySettingEvent(bool isSetAlready, bool withinBoot) {
1614*ec779b8eSAndroid Build Coastguard Worker     if (isSetAlready) {
1615*ec779b8eSAndroid Build Coastguard Worker         return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_NORMAL;
1616*ec779b8eSAndroid Build Coastguard Worker     }
1617*ec779b8eSAndroid Build Coastguard Worker     if (withinBoot) {
1618*ec779b8eSAndroid Build Coastguard Worker         return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_BOOT;
1619*ec779b8eSAndroid Build Coastguard Worker     }
1620*ec779b8eSAndroid Build Coastguard Worker     return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_FIRST;
1621*ec779b8eSAndroid Build Coastguard Worker }
1622*ec779b8eSAndroid Build Coastguard Worker 
onEvent(const std::shared_ptr<const android::mediametrics::Item> & item)1623*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::Spatializer::onEvent(
1624*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<const android::mediametrics::Item> &item)
1625*ec779b8eSAndroid Build Coastguard Worker {
1626*ec779b8eSAndroid Build Coastguard Worker     const auto key = item->getKey();
1627*ec779b8eSAndroid Build Coastguard Worker 
1628*ec779b8eSAndroid Build Coastguard Worker     if (!startsWith(key, AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER)) return;
1629*ec779b8eSAndroid Build Coastguard Worker 
1630*ec779b8eSAndroid Build Coastguard Worker     const std::string suffix =
1631*ec779b8eSAndroid Build Coastguard Worker             key.substr(std::size(AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER) - 1);
1632*ec779b8eSAndroid Build Coastguard Worker 
1633*ec779b8eSAndroid Build Coastguard Worker     std::string eventStr; // optional - find the actual event string.
1634*ec779b8eSAndroid Build Coastguard Worker     (void)item->get(AMEDIAMETRICS_PROP_EVENT, &eventStr);
1635*ec779b8eSAndroid Build Coastguard Worker 
1636*ec779b8eSAndroid Build Coastguard Worker     const size_t delim = suffix.find('.'); // note could use split.
1637*ec779b8eSAndroid Build Coastguard Worker     if (delim == suffix.npos) {
1638*ec779b8eSAndroid Build Coastguard Worker         // on create with suffix == "0" for the first spatializer effect.
1639*ec779b8eSAndroid Build Coastguard Worker 
1640*ec779b8eSAndroid Build Coastguard Worker         std::string headTrackingModes;
1641*ec779b8eSAndroid Build Coastguard Worker         (void)item->get(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, &headTrackingModes);
1642*ec779b8eSAndroid Build Coastguard Worker 
1643*ec779b8eSAndroid Build Coastguard Worker         std::string levels;
1644*ec779b8eSAndroid Build Coastguard Worker         (void)item->get(AMEDIAMETRICS_PROP_LEVELS, &levels);
1645*ec779b8eSAndroid Build Coastguard Worker 
1646*ec779b8eSAndroid Build Coastguard Worker         std::string modes;
1647*ec779b8eSAndroid Build Coastguard Worker         (void)item->get(AMEDIAMETRICS_PROP_MODES, &modes);
1648*ec779b8eSAndroid Build Coastguard Worker 
1649*ec779b8eSAndroid Build Coastguard Worker         std::string channelMasks;
1650*ec779b8eSAndroid Build Coastguard Worker         (void)item->get(AMEDIAMETRICS_PROP_CHANNELMASKS, &channelMasks);
1651*ec779b8eSAndroid Build Coastguard Worker 
1652*ec779b8eSAndroid Build Coastguard Worker         LOG(LOG_LEVEL) << "key:" << key
1653*ec779b8eSAndroid Build Coastguard Worker                 << " headTrackingModes:" << headTrackingModes
1654*ec779b8eSAndroid Build Coastguard Worker                 << " levels:" << levels
1655*ec779b8eSAndroid Build Coastguard Worker                 << " modes:" << modes
1656*ec779b8eSAndroid Build Coastguard Worker                 << " channelMasks:" << channelMasks
1657*ec779b8eSAndroid Build Coastguard Worker                 ;
1658*ec779b8eSAndroid Build Coastguard Worker 
1659*ec779b8eSAndroid Build Coastguard Worker         const std::vector<int32_t> headTrackingModesVector =
1660*ec779b8eSAndroid Build Coastguard Worker                 types::vectorFromMap(headTrackingModes, types::getHeadTrackingModeMap());
1661*ec779b8eSAndroid Build Coastguard Worker         const std::vector<int32_t> levelsVector =
1662*ec779b8eSAndroid Build Coastguard Worker                 types::vectorFromMap(levels, types::getSpatializerLevelMap());
1663*ec779b8eSAndroid Build Coastguard Worker         const std::vector<int32_t> modesVector =
1664*ec779b8eSAndroid Build Coastguard Worker                 types::vectorFromMap(modes, types::getSpatializerModeMap());
1665*ec779b8eSAndroid Build Coastguard Worker         const std::vector<int64_t> channelMasksVector =
1666*ec779b8eSAndroid Build Coastguard Worker                 types::channelMaskVectorFromString(channelMasks);
1667*ec779b8eSAndroid Build Coastguard Worker 
1668*ec779b8eSAndroid Build Coastguard Worker         const auto [ result, str ] = sendToStatsd(SpatializerCapabilitiesFields,
1669*ec779b8eSAndroid Build Coastguard Worker                 CONDITION(stats::media_metrics::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED)
1670*ec779b8eSAndroid Build Coastguard Worker                 , headTrackingModesVector
1671*ec779b8eSAndroid Build Coastguard Worker                 , levelsVector
1672*ec779b8eSAndroid Build Coastguard Worker                 , modesVector
1673*ec779b8eSAndroid Build Coastguard Worker                 , channelMasksVector
1674*ec779b8eSAndroid Build Coastguard Worker                 );
1675*ec779b8eSAndroid Build Coastguard Worker 
1676*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mStatsdLog->log(
1677*ec779b8eSAndroid Build Coastguard Worker                 stats::media_metrics::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED, str);
1678*ec779b8eSAndroid Build Coastguard Worker 
1679*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard lg(mLock);
1680*ec779b8eSAndroid Build Coastguard Worker         if (mFirstCreateTimeNs == 0) {
1681*ec779b8eSAndroid Build Coastguard Worker             // Only update the create time once to prevent audioserver restart
1682*ec779b8eSAndroid Build Coastguard Worker             // from looking like a boot.
1683*ec779b8eSAndroid Build Coastguard Worker             mFirstCreateTimeNs = item->getTimestamp();
1684*ec779b8eSAndroid Build Coastguard Worker         }
1685*ec779b8eSAndroid Build Coastguard Worker         mSimpleLog.log("%s suffix: %s item: %s",
1686*ec779b8eSAndroid Build Coastguard Worker                 __func__, suffix.c_str(), item->toString().c_str());
1687*ec779b8eSAndroid Build Coastguard Worker     } else {
1688*ec779b8eSAndroid Build Coastguard Worker         std::string subtype = suffix.substr(0, delim);
1689*ec779b8eSAndroid Build Coastguard Worker         if (subtype != "device") return; // not a device.
1690*ec779b8eSAndroid Build Coastguard Worker 
1691*ec779b8eSAndroid Build Coastguard Worker         const std::string deviceType = suffix.substr(std::size("device.") - 1);
1692*ec779b8eSAndroid Build Coastguard Worker 
1693*ec779b8eSAndroid Build Coastguard Worker         const int32_t deviceTypeStatsd =
1694*ec779b8eSAndroid Build Coastguard Worker                 types::lookup<types::AUDIO_DEVICE_INFO_TYPE, int32_t>(deviceType);
1695*ec779b8eSAndroid Build Coastguard Worker 
1696*ec779b8eSAndroid Build Coastguard Worker         std::string address;
1697*ec779b8eSAndroid Build Coastguard Worker         (void)item->get(AMEDIAMETRICS_PROP_ADDRESS, &address);
1698*ec779b8eSAndroid Build Coastguard Worker         std::string enabled;
1699*ec779b8eSAndroid Build Coastguard Worker         (void)item->get(AMEDIAMETRICS_PROP_ENABLED, &enabled);
1700*ec779b8eSAndroid Build Coastguard Worker         std::string hasHeadTracker;
1701*ec779b8eSAndroid Build Coastguard Worker         (void)item->get(AMEDIAMETRICS_PROP_HASHEADTRACKER, &hasHeadTracker);
1702*ec779b8eSAndroid Build Coastguard Worker         std::string headTrackerEnabled;
1703*ec779b8eSAndroid Build Coastguard Worker         (void)item->get(AMEDIAMETRICS_PROP_HEADTRACKERENABLED, &headTrackerEnabled);
1704*ec779b8eSAndroid Build Coastguard Worker 
1705*ec779b8eSAndroid Build Coastguard Worker         std::lock_guard lg(mLock);
1706*ec779b8eSAndroid Build Coastguard Worker 
1707*ec779b8eSAndroid Build Coastguard Worker         // Validate from our cached state
1708*ec779b8eSAndroid Build Coastguard Worker 
1709*ec779b8eSAndroid Build Coastguard Worker         // Our deviceKey takes the device type and appends the address if any.
1710*ec779b8eSAndroid Build Coastguard Worker         // This distinguishes different wireless devices for the purposes of tracking.
1711*ec779b8eSAndroid Build Coastguard Worker         std::string deviceKey(deviceType);
1712*ec779b8eSAndroid Build Coastguard Worker         deviceKey.append("_").append(address);
1713*ec779b8eSAndroid Build Coastguard Worker         DeviceState& deviceState = mDeviceStateMap[deviceKey];
1714*ec779b8eSAndroid Build Coastguard Worker 
1715*ec779b8eSAndroid Build Coastguard Worker         // check whether the settings event is within a certain time of spatializer creation.
1716*ec779b8eSAndroid Build Coastguard Worker         const bool withinBoot =
1717*ec779b8eSAndroid Build Coastguard Worker                 item->getTimestamp() - mFirstCreateTimeNs < kBootDurationThreshold;
1718*ec779b8eSAndroid Build Coastguard Worker 
1719*ec779b8eSAndroid Build Coastguard Worker         if (!enabled.empty()) {
1720*ec779b8eSAndroid Build Coastguard Worker             if (enabled != deviceState.enabled) {
1721*ec779b8eSAndroid Build Coastguard Worker                 const int32_t settingEventStatsd =
1722*ec779b8eSAndroid Build Coastguard Worker                         classifySettingEvent(!deviceState.enabled.empty(), withinBoot);
1723*ec779b8eSAndroid Build Coastguard Worker                 deviceState.enabled = enabled;
1724*ec779b8eSAndroid Build Coastguard Worker                 const bool enabledStatsd = enabled == "true";
1725*ec779b8eSAndroid Build Coastguard Worker                 const auto [ result, str ] = sendToStatsd(SpatializerDeviceEnabledFields,
1726*ec779b8eSAndroid Build Coastguard Worker                         CONDITION(stats::media_metrics::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED)
1727*ec779b8eSAndroid Build Coastguard Worker                         , deviceTypeStatsd
1728*ec779b8eSAndroid Build Coastguard Worker                         , settingEventStatsd
1729*ec779b8eSAndroid Build Coastguard Worker                         , enabledStatsd
1730*ec779b8eSAndroid Build Coastguard Worker                         );
1731*ec779b8eSAndroid Build Coastguard Worker                 mAudioAnalytics.mStatsdLog->log(
1732*ec779b8eSAndroid Build Coastguard Worker                         stats::media_metrics::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED, str);
1733*ec779b8eSAndroid Build Coastguard Worker             }
1734*ec779b8eSAndroid Build Coastguard Worker         }
1735*ec779b8eSAndroid Build Coastguard Worker         if (!hasHeadTracker.empty()) {
1736*ec779b8eSAndroid Build Coastguard Worker             if (hasHeadTracker != deviceState.hasHeadTracker) {
1737*ec779b8eSAndroid Build Coastguard Worker                 const int32_t settingEventStatsd =
1738*ec779b8eSAndroid Build Coastguard Worker                         classifySettingEvent(!deviceState.hasHeadTracker.empty(), withinBoot);
1739*ec779b8eSAndroid Build Coastguard Worker                 deviceState.hasHeadTracker = hasHeadTracker;
1740*ec779b8eSAndroid Build Coastguard Worker                 const bool supportedStatsd = hasHeadTracker == "true";
1741*ec779b8eSAndroid Build Coastguard Worker                 const auto [ result, str ] = sendToStatsd(HeadTrackerDeviceSupportedFields,
1742*ec779b8eSAndroid Build Coastguard Worker                         CONDITION(stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED)
1743*ec779b8eSAndroid Build Coastguard Worker                         , deviceTypeStatsd
1744*ec779b8eSAndroid Build Coastguard Worker                         , settingEventStatsd
1745*ec779b8eSAndroid Build Coastguard Worker                         , supportedStatsd
1746*ec779b8eSAndroid Build Coastguard Worker                         );
1747*ec779b8eSAndroid Build Coastguard Worker                 mAudioAnalytics.mStatsdLog->log(
1748*ec779b8eSAndroid Build Coastguard Worker                         stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED, str);
1749*ec779b8eSAndroid Build Coastguard Worker             }
1750*ec779b8eSAndroid Build Coastguard Worker         }
1751*ec779b8eSAndroid Build Coastguard Worker         if (!headTrackerEnabled.empty()) {
1752*ec779b8eSAndroid Build Coastguard Worker             if (headTrackerEnabled != deviceState.headTrackerEnabled) {
1753*ec779b8eSAndroid Build Coastguard Worker                 const int32_t settingEventStatsd =
1754*ec779b8eSAndroid Build Coastguard Worker                         classifySettingEvent(!deviceState.headTrackerEnabled.empty(), withinBoot);
1755*ec779b8eSAndroid Build Coastguard Worker                 deviceState.headTrackerEnabled = headTrackerEnabled;
1756*ec779b8eSAndroid Build Coastguard Worker                 const bool enabledStatsd = headTrackerEnabled == "true";
1757*ec779b8eSAndroid Build Coastguard Worker                 const auto [ result, str ] = sendToStatsd(HeadTrackerDeviceEnabledFields,
1758*ec779b8eSAndroid Build Coastguard Worker                         CONDITION(stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED)
1759*ec779b8eSAndroid Build Coastguard Worker                         , deviceTypeStatsd
1760*ec779b8eSAndroid Build Coastguard Worker                         , settingEventStatsd
1761*ec779b8eSAndroid Build Coastguard Worker                         , enabledStatsd
1762*ec779b8eSAndroid Build Coastguard Worker                         );
1763*ec779b8eSAndroid Build Coastguard Worker                 mAudioAnalytics.mStatsdLog->log(
1764*ec779b8eSAndroid Build Coastguard Worker                         stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED, str);
1765*ec779b8eSAndroid Build Coastguard Worker             }
1766*ec779b8eSAndroid Build Coastguard Worker         }
1767*ec779b8eSAndroid Build Coastguard Worker         mSimpleLog.log("%s deviceKey: %s item: %s",
1768*ec779b8eSAndroid Build Coastguard Worker                 __func__, deviceKey.c_str(), item->toString().c_str());
1769*ec779b8eSAndroid Build Coastguard Worker     }
1770*ec779b8eSAndroid Build Coastguard Worker }
1771*ec779b8eSAndroid Build Coastguard Worker 
dump(int32_t lines,const char * prefix) const1772*ec779b8eSAndroid Build Coastguard Worker std::pair<std::string, int32_t> AudioAnalytics::Spatializer::dump(
1773*ec779b8eSAndroid Build Coastguard Worker         int32_t lines, const char *prefix) const
1774*ec779b8eSAndroid Build Coastguard Worker {
1775*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard lg(mLock);
1776*ec779b8eSAndroid Build Coastguard Worker     std::string s = mSimpleLog.dumpToString(prefix == nullptr ? "" : prefix, lines);
1777*ec779b8eSAndroid Build Coastguard Worker     size_t n = std::count(s.begin(), s.end(), '\n');
1778*ec779b8eSAndroid Build Coastguard Worker     return { s, n };
1779*ec779b8eSAndroid Build Coastguard Worker }
1780*ec779b8eSAndroid Build Coastguard Worker 
onEvent(const std::shared_ptr<const android::mediametrics::Item> & item) const1781*ec779b8eSAndroid Build Coastguard Worker void AudioAnalytics::MidiLogging::onEvent(
1782*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<const android::mediametrics::Item> &item) const {
1783*ec779b8eSAndroid Build Coastguard Worker     const std::string& key = item->getKey();
1784*ec779b8eSAndroid Build Coastguard Worker 
1785*ec779b8eSAndroid Build Coastguard Worker     const auto uid = item->getUid();
1786*ec779b8eSAndroid Build Coastguard Worker 
1787*ec779b8eSAndroid Build Coastguard Worker     int32_t deviceId = -1;
1788*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1789*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_DEVICEID, &deviceId);
1790*ec779b8eSAndroid Build Coastguard Worker 
1791*ec779b8eSAndroid Build Coastguard Worker     int32_t inputPortCount = -1;
1792*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1793*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_INPUTPORTCOUNT, &inputPortCount);
1794*ec779b8eSAndroid Build Coastguard Worker 
1795*ec779b8eSAndroid Build Coastguard Worker     int32_t outputPortCount = -1;
1796*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1797*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_OUTPUTPORTCOUNT, &outputPortCount);
1798*ec779b8eSAndroid Build Coastguard Worker 
1799*ec779b8eSAndroid Build Coastguard Worker     int32_t hardwareType = -1;
1800*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1801*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_HARDWARETYPE, &hardwareType);
1802*ec779b8eSAndroid Build Coastguard Worker 
1803*ec779b8eSAndroid Build Coastguard Worker     std::string isSharedString;
1804*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1805*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_ISSHARED, &isSharedString);
1806*ec779b8eSAndroid Build Coastguard Worker     const bool isShared = (isSharedString == "true");
1807*ec779b8eSAndroid Build Coastguard Worker 
1808*ec779b8eSAndroid Build Coastguard Worker     std::string supportsMidiUmpString;
1809*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1810*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_SUPPORTSMIDIUMP, &supportsMidiUmpString);
1811*ec779b8eSAndroid Build Coastguard Worker     const bool supportsMidiUmp = (supportsMidiUmpString == "true");
1812*ec779b8eSAndroid Build Coastguard Worker 
1813*ec779b8eSAndroid Build Coastguard Worker     std::string usingAlsaString;
1814*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1815*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_USINGALSA, &usingAlsaString);
1816*ec779b8eSAndroid Build Coastguard Worker     const bool usingAlsa = (usingAlsaString == "true");
1817*ec779b8eSAndroid Build Coastguard Worker 
1818*ec779b8eSAndroid Build Coastguard Worker     int64_t durationNs = -1;
1819*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1820*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_DURATIONNS, &durationNs);
1821*ec779b8eSAndroid Build Coastguard Worker 
1822*ec779b8eSAndroid Build Coastguard Worker     int32_t openedCount = -1;
1823*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1824*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_OPENEDCOUNT, &openedCount);
1825*ec779b8eSAndroid Build Coastguard Worker 
1826*ec779b8eSAndroid Build Coastguard Worker     int32_t closedCount = -1;
1827*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1828*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_CLOSEDCOUNT, &closedCount);
1829*ec779b8eSAndroid Build Coastguard Worker 
1830*ec779b8eSAndroid Build Coastguard Worker     std::string deviceDisconnectedString;
1831*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1832*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_DEVICEDISCONNECTED, &deviceDisconnectedString);
1833*ec779b8eSAndroid Build Coastguard Worker     const bool deviceDisconnected = (deviceDisconnectedString == "true");
1834*ec779b8eSAndroid Build Coastguard Worker 
1835*ec779b8eSAndroid Build Coastguard Worker     int32_t totalInputBytes = -1;
1836*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1837*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_TOTALINPUTBYTES, &totalInputBytes);
1838*ec779b8eSAndroid Build Coastguard Worker 
1839*ec779b8eSAndroid Build Coastguard Worker     int32_t totalOutputBytes = -1;
1840*ec779b8eSAndroid Build Coastguard Worker     mAudioAnalytics.mAnalyticsState->timeMachine().get(
1841*ec779b8eSAndroid Build Coastguard Worker             key, AMEDIAMETRICS_PROP_TOTALOUTPUTBYTES, &totalOutputBytes);
1842*ec779b8eSAndroid Build Coastguard Worker 
1843*ec779b8eSAndroid Build Coastguard Worker     LOG(LOG_LEVEL) << "key:" << key
1844*ec779b8eSAndroid Build Coastguard Worker             << " uid:" << uid
1845*ec779b8eSAndroid Build Coastguard Worker             << " id:" << deviceId
1846*ec779b8eSAndroid Build Coastguard Worker             << " input_port_count:" << inputPortCount
1847*ec779b8eSAndroid Build Coastguard Worker             << " output_port_count:" << outputPortCount
1848*ec779b8eSAndroid Build Coastguard Worker             << " device_type:" << hardwareType
1849*ec779b8eSAndroid Build Coastguard Worker             << " is_shared:" << isSharedString
1850*ec779b8eSAndroid Build Coastguard Worker             << " supports_ump:" << supportsMidiUmpString
1851*ec779b8eSAndroid Build Coastguard Worker             << " using_alsa:" << usingAlsaString
1852*ec779b8eSAndroid Build Coastguard Worker             << " duration_opened_ms:" << durationNs
1853*ec779b8eSAndroid Build Coastguard Worker             << " opened_count:" << openedCount
1854*ec779b8eSAndroid Build Coastguard Worker             << " closed_count:" << closedCount
1855*ec779b8eSAndroid Build Coastguard Worker             << " device_disconnected:" << deviceDisconnectedString
1856*ec779b8eSAndroid Build Coastguard Worker             << " total_input_bytes:" << totalInputBytes
1857*ec779b8eSAndroid Build Coastguard Worker             << " total_output_bytes:" << totalOutputBytes;
1858*ec779b8eSAndroid Build Coastguard Worker 
1859*ec779b8eSAndroid Build Coastguard Worker     if (mAudioAnalytics.mDeliverStatistics) {
1860*ec779b8eSAndroid Build Coastguard Worker         const auto result = sendToStatsd(
1861*ec779b8eSAndroid Build Coastguard Worker                 CONDITION(stats::media_metrics::MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED)
1862*ec779b8eSAndroid Build Coastguard Worker                 , uid
1863*ec779b8eSAndroid Build Coastguard Worker                 , deviceId
1864*ec779b8eSAndroid Build Coastguard Worker                 , inputPortCount
1865*ec779b8eSAndroid Build Coastguard Worker                 , outputPortCount
1866*ec779b8eSAndroid Build Coastguard Worker                 , hardwareType
1867*ec779b8eSAndroid Build Coastguard Worker                 , isShared
1868*ec779b8eSAndroid Build Coastguard Worker                 , supportsMidiUmp
1869*ec779b8eSAndroid Build Coastguard Worker                 , usingAlsa
1870*ec779b8eSAndroid Build Coastguard Worker                 , durationNs
1871*ec779b8eSAndroid Build Coastguard Worker                 , openedCount
1872*ec779b8eSAndroid Build Coastguard Worker                 , closedCount
1873*ec779b8eSAndroid Build Coastguard Worker                 , deviceDisconnected
1874*ec779b8eSAndroid Build Coastguard Worker                 , totalInputBytes
1875*ec779b8eSAndroid Build Coastguard Worker                 , totalOutputBytes);
1876*ec779b8eSAndroid Build Coastguard Worker         std::stringstream ss;
1877*ec779b8eSAndroid Build Coastguard Worker         ss << "result:" << result;
1878*ec779b8eSAndroid Build Coastguard Worker         const auto fieldsStr = printFields(MidiDeviceCloseFields,
1879*ec779b8eSAndroid Build Coastguard Worker                 CONDITION(stats::media_metrics::MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED)
1880*ec779b8eSAndroid Build Coastguard Worker                 , uid
1881*ec779b8eSAndroid Build Coastguard Worker                 , deviceId
1882*ec779b8eSAndroid Build Coastguard Worker                 , inputPortCount
1883*ec779b8eSAndroid Build Coastguard Worker                 , outputPortCount
1884*ec779b8eSAndroid Build Coastguard Worker                 , hardwareType
1885*ec779b8eSAndroid Build Coastguard Worker                 , isShared
1886*ec779b8eSAndroid Build Coastguard Worker                 , supportsMidiUmp
1887*ec779b8eSAndroid Build Coastguard Worker                 , usingAlsa
1888*ec779b8eSAndroid Build Coastguard Worker                 , durationNs
1889*ec779b8eSAndroid Build Coastguard Worker                 , openedCount
1890*ec779b8eSAndroid Build Coastguard Worker                 , closedCount
1891*ec779b8eSAndroid Build Coastguard Worker                 , deviceDisconnected
1892*ec779b8eSAndroid Build Coastguard Worker                 , totalInputBytes
1893*ec779b8eSAndroid Build Coastguard Worker                 , totalOutputBytes);
1894*ec779b8eSAndroid Build Coastguard Worker         ss << " " << fieldsStr;
1895*ec779b8eSAndroid Build Coastguard Worker         std::string str = ss.str();
1896*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: statsd %s", __func__, str.c_str());
1897*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mStatsdLog->log(
1898*ec779b8eSAndroid Build Coastguard Worker                 stats::media_metrics::MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED, str);
1899*ec779b8eSAndroid Build Coastguard Worker     }
1900*ec779b8eSAndroid Build Coastguard Worker }
1901*ec779b8eSAndroid Build Coastguard Worker 
1902*ec779b8eSAndroid Build Coastguard Worker // This method currently suppresses the name.
getDeviceNamesFromOutputDevices(std::string_view devices) const1903*ec779b8eSAndroid Build Coastguard Worker std::string AudioAnalytics::getDeviceNamesFromOutputDevices(std::string_view devices) const {
1904*ec779b8eSAndroid Build Coastguard Worker     std::string deviceNames;
1905*ec779b8eSAndroid Build Coastguard Worker     if (stringutils::hasBluetoothOutputDevice(devices)) {
1906*ec779b8eSAndroid Build Coastguard Worker         deviceNames = SUPPRESSED;
1907*ec779b8eSAndroid Build Coastguard Worker #if 0   // TODO(b/161554630) sanitize name
1908*ec779b8eSAndroid Build Coastguard Worker         mAudioAnalytics.mAnalyticsState->timeMachine().get(
1909*ec779b8eSAndroid Build Coastguard Worker             "audio.device.bt_a2dp", AMEDIAMETRICS_PROP_NAME, &deviceNames);
1910*ec779b8eSAndroid Build Coastguard Worker         // Remove | if present
1911*ec779b8eSAndroid Build Coastguard Worker         stringutils::replace(deviceNames, "|", '?');
1912*ec779b8eSAndroid Build Coastguard Worker         if (deviceNames.size() > STATSD_DEVICE_NAME_MAX_LENGTH) {
1913*ec779b8eSAndroid Build Coastguard Worker             deviceNames.resize(STATSD_DEVICE_NAME_MAX_LENGTH); // truncate
1914*ec779b8eSAndroid Build Coastguard Worker         }
1915*ec779b8eSAndroid Build Coastguard Worker #endif
1916*ec779b8eSAndroid Build Coastguard Worker     }
1917*ec779b8eSAndroid Build Coastguard Worker     return deviceNames;
1918*ec779b8eSAndroid Build Coastguard Worker }
1919*ec779b8eSAndroid Build Coastguard Worker 
1920*ec779b8eSAndroid Build Coastguard Worker } // namespace android::mediametrics
1921