1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.audio;
18 
19 import android.media.AudioAttributes;
20 import android.media.AudioManager;
21 import android.media.AudioSystem;
22 import android.media.MediaMetrics;
23 
24 import com.android.server.audio.AudioDeviceInventory.WiredDeviceConnectionState;
25 
26 
27 public class AudioServiceEvents {
28 
29     final static class PhoneStateEvent extends AudioEventLogger.Event {
30         static final int MODE_SET = 0;
31         static final int MODE_IN_COMMUNICATION_TIMEOUT = 1;
32 
33         final int mOp;
34         final String mPackage;
35         final int mOwnerPid;
36         final int mRequesterPid;
37         final int mRequestedMode;
38         final int mActualMode;
39 
40         /** used for MODE_SET */
PhoneStateEvent(String callingPackage, int requesterPid, int requestedMode, int ownerPid, int actualMode)41         PhoneStateEvent(String callingPackage, int requesterPid, int requestedMode,
42                         int ownerPid, int actualMode) {
43             mOp = MODE_SET;
44             mPackage = callingPackage;
45             mRequesterPid = requesterPid;
46             mRequestedMode = requestedMode;
47             mOwnerPid = ownerPid;
48             mActualMode = actualMode;
49             logMetricEvent();
50         }
51 
52         /** used for MODE_IN_COMMUNICATION_TIMEOUT */
PhoneStateEvent(String callingPackage, int ownerPid)53         PhoneStateEvent(String callingPackage, int ownerPid) {
54             mOp = MODE_IN_COMMUNICATION_TIMEOUT;
55             mPackage = callingPackage;
56             mOwnerPid = ownerPid;
57             mRequesterPid = 0;
58             mRequestedMode = 0;
59             mActualMode = 0;
60             logMetricEvent();
61         }
62 
63         @Override
eventToString()64         public String eventToString() {
65             switch (mOp) {
66                 case MODE_SET:
67                     return new StringBuilder("setMode(")
68                             .append(AudioSystem.modeToString(mRequestedMode))
69                             .append(") from package=").append(mPackage)
70                             .append(" pid=").append(mRequesterPid)
71                             .append(" selected mode=")
72                             .append(AudioSystem.modeToString(mActualMode))
73                             .append(" by pid=").append(mOwnerPid).toString();
74                 case MODE_IN_COMMUNICATION_TIMEOUT:
75                     return new StringBuilder("mode IN COMMUNICATION timeout")
76                             .append(" for package=").append(mPackage)
77                             .append(" pid=").append(mOwnerPid).toString();
78                 default: return new StringBuilder("FIXME invalid op:").append(mOp).toString();
79             }
80         }
81 
82         /**
83          * Audio Analytics unique Id.
84          */
85         private static final String mMetricsId = MediaMetrics.Name.AUDIO_MODE;
86 
logMetricEvent()87         private void logMetricEvent() {
88             switch (mOp) {
89                 case MODE_SET:
90                     new MediaMetrics.Item(mMetricsId)
91                             .set(MediaMetrics.Property.EVENT, "set")
92                             .set(MediaMetrics.Property.REQUESTED_MODE,
93                                     AudioSystem.modeToString(mRequestedMode))
94                             .set(MediaMetrics.Property.MODE, AudioSystem.modeToString(mActualMode))
95                             .set(MediaMetrics.Property.CALLING_PACKAGE, mPackage)
96                             .record();
97                     return;
98                 case MODE_IN_COMMUNICATION_TIMEOUT:
99                     new MediaMetrics.Item(mMetricsId)
100                             .set(MediaMetrics.Property.EVENT, "inCommunicationTimeout")
101                             .set(MediaMetrics.Property.CALLING_PACKAGE, mPackage)
102                             .record();
103                     return;
104                 default: return;
105             }
106         }
107     }
108 
109     final static class WiredDevConnectEvent extends AudioEventLogger.Event {
110         final WiredDeviceConnectionState mState;
111 
WiredDevConnectEvent(WiredDeviceConnectionState state)112         WiredDevConnectEvent(WiredDeviceConnectionState state) {
113             mState = state;
114         }
115 
116         @Override
eventToString()117         public String eventToString() {
118             return new StringBuilder("setWiredDeviceConnectionState(")
119                     .append(" type:").append(Integer.toHexString(mState.mType))
120                     .append(" state:").append(AudioSystem.deviceStateToString(mState.mState))
121                     .append(" addr:").append(mState.mAddress)
122                     .append(" name:").append(mState.mName)
123                     .append(") from ").append(mState.mCaller).toString();
124         }
125     }
126 
127     final static class ForceUseEvent extends AudioEventLogger.Event {
128         final int mUsage;
129         final int mConfig;
130         final String mReason;
131 
ForceUseEvent(int usage, int config, String reason)132         ForceUseEvent(int usage, int config, String reason) {
133             mUsage = usage;
134             mConfig = config;
135             mReason = reason;
136         }
137 
138         @Override
eventToString()139         public String eventToString() {
140             return new StringBuilder("setForceUse(")
141                     .append(AudioSystem.forceUseUsageToString(mUsage))
142                     .append(", ").append(AudioSystem.forceUseConfigToString(mConfig))
143                     .append(") due to ").append(mReason).toString();
144         }
145     }
146 
147     final static class VolumeEvent extends AudioEventLogger.Event {
148         static final int VOL_ADJUST_SUGG_VOL = 0;
149         static final int VOL_ADJUST_STREAM_VOL = 1;
150         static final int VOL_SET_STREAM_VOL = 2;
151         static final int VOL_SET_HEARING_AID_VOL = 3;
152         static final int VOL_SET_AVRCP_VOL = 4;
153         static final int VOL_ADJUST_VOL_UID = 5;
154         static final int VOL_VOICE_ACTIVITY_HEARING_AID = 6;
155         static final int VOL_MODE_CHANGE_HEARING_AID = 7;
156         static final int VOL_SET_GROUP_VOL = 8;
157         static final int VOL_MUTE_STREAM_INT = 9;
158 
159         final int mOp;
160         final int mStream;
161         final int mVal1;
162         final int mVal2;
163         final String mCaller;
164         final String mGroupName;
165         final AudioAttributes mAudioAttributes;
166 
167         /** used for VOL_ADJUST_VOL_UID,
168          *           VOL_ADJUST_SUGG_VOL,
169          *           VOL_ADJUST_STREAM_VOL,
170          *           VOL_SET_STREAM_VOL */
VolumeEvent(int op, int stream, int val1, int val2, String caller)171         VolumeEvent(int op, int stream, int val1, int val2, String caller) {
172             mOp = op;
173             mStream = stream;
174             mVal1 = val1;
175             mVal2 = val2;
176             mCaller = caller;
177             mGroupName = null;
178             mAudioAttributes = null;
179             logMetricEvent();
180         }
181 
182         /** used for VOL_SET_HEARING_AID_VOL*/
VolumeEvent(int op, int index, int gainDb)183         VolumeEvent(int op, int index, int gainDb) {
184             mOp = op;
185             mVal1 = index;
186             mVal2 = gainDb;
187             // unused
188             mStream = -1;
189             mCaller = null;
190             mGroupName = null;
191             mAudioAttributes = null;
192             logMetricEvent();
193         }
194 
195         /** used for VOL_SET_AVRCP_VOL */
VolumeEvent(int op, int index)196         VolumeEvent(int op, int index) {
197             mOp = op;
198             mVal1 = index;
199             // unused
200             mVal2 = 0;
201             mStream = -1;
202             mCaller = null;
203             mGroupName = null;
204             mAudioAttributes = null;
205             logMetricEvent();
206         }
207 
208         /** used for VOL_VOICE_ACTIVITY_HEARING_AID */
VolumeEvent(int op, boolean voiceActive, int stream, int index)209         VolumeEvent(int op, boolean voiceActive, int stream, int index) {
210             mOp = op;
211             mStream = stream;
212             mVal1 = index;
213             mVal2 = voiceActive ? 1 : 0;
214             // unused
215             mCaller = null;
216             mGroupName = null;
217             mAudioAttributes = null;
218             logMetricEvent();
219         }
220 
221         /** used for VOL_MODE_CHANGE_HEARING_AID */
VolumeEvent(int op, int mode, int stream, int index)222         VolumeEvent(int op, int mode, int stream, int index) {
223             mOp = op;
224             mStream = stream;
225             mVal1 = index;
226             mVal2 = mode;
227             // unused
228             mCaller = null;
229             mGroupName = null;
230             mAudioAttributes = null;
231             logMetricEvent();
232         }
233 
234         /** used for VOL_SET_GROUP_VOL */
VolumeEvent(int op, AudioAttributes aa, String group, int index, int flags, String caller)235         VolumeEvent(int op, AudioAttributes aa, String group, int index, int flags, String caller) {
236             mOp = op;
237             mStream = -1;
238             mVal1 = index;
239             mVal2 = flags;
240             mCaller = caller;
241             mGroupName = group;
242             mAudioAttributes = aa;
243             logMetricEvent();
244         }
245 
246         /** used for VOL_MUTE_STREAM_INT */
VolumeEvent(int op, int stream, boolean state)247         VolumeEvent(int op, int stream, boolean state) {
248             mOp = op;
249             mStream = stream;
250             mVal1 = state ? 1 : 0;
251             mVal2 = 0;
252             mCaller = null;
253             mGroupName = null;
254             mAudioAttributes = null;
255             logMetricEvent();
256         }
257 
258 
259         /**
260          * Audio Analytics unique Id.
261          */
262         private static final String mMetricsId = MediaMetrics.Name.AUDIO_VOLUME_EVENT;
263 
264         /**
265          * Log mediametrics event
266          */
logMetricEvent()267         private void logMetricEvent() {
268             switch (mOp) {
269                 case VOL_ADJUST_SUGG_VOL:
270                 case VOL_ADJUST_VOL_UID:
271                 case VOL_ADJUST_STREAM_VOL: {
272                     String eventName;
273                     switch (mOp) {
274                         case VOL_ADJUST_SUGG_VOL:
275                             eventName = "adjustSuggestedStreamVolume";
276                             break;
277                         case VOL_ADJUST_STREAM_VOL:
278                             eventName = "adjustStreamVolume";
279                             break;
280                         case VOL_ADJUST_VOL_UID:
281                             eventName = "adjustStreamVolumeForUid";
282                             break;
283                         default:
284                             return; // not possible, just return here
285                     }
286                     new MediaMetrics.Item(mMetricsId)
287                             .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
288                             .set(MediaMetrics.Property.DIRECTION, mVal1 > 0 ? "up" : "down")
289                             .set(MediaMetrics.Property.EVENT, eventName)
290                             .set(MediaMetrics.Property.FLAGS, mVal2)
291                             .set(MediaMetrics.Property.STREAM_TYPE,
292                                     AudioSystem.streamToString(mStream))
293                             .record();
294                     return;
295                 }
296                 case VOL_SET_STREAM_VOL:
297                     new MediaMetrics.Item(mMetricsId)
298                             .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
299                             .set(MediaMetrics.Property.EVENT, "setStreamVolume")
300                             .set(MediaMetrics.Property.FLAGS, mVal2)
301                             .set(MediaMetrics.Property.INDEX, mVal1)
302                             .set(MediaMetrics.Property.STREAM_TYPE,
303                                     AudioSystem.streamToString(mStream))
304                             .record();
305                     return;
306                 case VOL_SET_HEARING_AID_VOL:
307                     new MediaMetrics.Item(mMetricsId)
308                             .set(MediaMetrics.Property.EVENT, "setHearingAidVolume")
309                             .set(MediaMetrics.Property.GAIN_DB, (double) mVal2)
310                             .set(MediaMetrics.Property.INDEX, mVal1)
311                             .record();
312                     return;
313                 case VOL_SET_AVRCP_VOL:
314                     new MediaMetrics.Item(mMetricsId)
315                             .set(MediaMetrics.Property.EVENT, "setAvrcpVolume")
316                             .set(MediaMetrics.Property.INDEX, mVal1)
317                             .record();
318                     return;
319                 case VOL_VOICE_ACTIVITY_HEARING_AID:
320                     new MediaMetrics.Item(mMetricsId)
321                             .set(MediaMetrics.Property.EVENT, "voiceActivityHearingAid")
322                             .set(MediaMetrics.Property.INDEX, mVal1)
323                             .set(MediaMetrics.Property.STATE,
324                                     mVal2 == 1 ? "active" : "inactive")
325                             .set(MediaMetrics.Property.STREAM_TYPE,
326                                     AudioSystem.streamToString(mStream))
327                             .record();
328                     return;
329                 case VOL_MODE_CHANGE_HEARING_AID:
330                     new MediaMetrics.Item(mMetricsId)
331                             .set(MediaMetrics.Property.EVENT, "modeChangeHearingAid")
332                             .set(MediaMetrics.Property.INDEX, mVal1)
333                             .set(MediaMetrics.Property.MODE, AudioSystem.modeToString(mVal2))
334                             .set(MediaMetrics.Property.STREAM_TYPE,
335                                     AudioSystem.streamToString(mStream))
336                             .record();
337                     return;
338                 case VOL_SET_GROUP_VOL:
339                     new MediaMetrics.Item(mMetricsId)
340                             .set(MediaMetrics.Property.ATTRIBUTES, mAudioAttributes.toString())
341                             .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
342                             .set(MediaMetrics.Property.EVENT, "setVolumeIndexForAttributes")
343                             .set(MediaMetrics.Property.FLAGS, mVal2)
344                             .set(MediaMetrics.Property.GROUP, mGroupName)
345                             .set(MediaMetrics.Property.INDEX, mVal1)
346                             .record();
347                     return;
348                 case VOL_MUTE_STREAM_INT:
349                     // No value in logging metrics for this internal event
350                     return;
351                 default:
352                     return;
353             }
354         }
355 
356         @Override
eventToString()357         public String eventToString() {
358             switch (mOp) {
359                 case VOL_ADJUST_SUGG_VOL:
360                     return new StringBuilder("adjustSuggestedStreamVolume(sugg:")
361                             .append(AudioSystem.streamToString(mStream))
362                             .append(" dir:").append(AudioManager.adjustToString(mVal1))
363                             .append(" flags:0x").append(Integer.toHexString(mVal2))
364                             .append(") from ").append(mCaller)
365                             .toString();
366                 case VOL_ADJUST_STREAM_VOL:
367                     return new StringBuilder("adjustStreamVolume(stream:")
368                             .append(AudioSystem.streamToString(mStream))
369                             .append(" dir:").append(AudioManager.adjustToString(mVal1))
370                             .append(" flags:0x").append(Integer.toHexString(mVal2))
371                             .append(") from ").append(mCaller)
372                             .toString();
373                 case VOL_SET_STREAM_VOL:
374                     return new StringBuilder("setStreamVolume(stream:")
375                             .append(AudioSystem.streamToString(mStream))
376                             .append(" index:").append(mVal1)
377                             .append(" flags:0x").append(Integer.toHexString(mVal2))
378                             .append(") from ").append(mCaller)
379                             .toString();
380                 case VOL_SET_HEARING_AID_VOL:
381                     return new StringBuilder("setHearingAidVolume:")
382                             .append(" index:").append(mVal1)
383                             .append(" gain dB:").append(mVal2)
384                             .toString();
385                 case VOL_SET_AVRCP_VOL:
386                     return new StringBuilder("setAvrcpVolume:")
387                             .append(" index:").append(mVal1)
388                             .toString();
389                 case VOL_ADJUST_VOL_UID:
390                     return new StringBuilder("adjustStreamVolumeForUid(stream:")
391                             .append(AudioSystem.streamToString(mStream))
392                             .append(" dir:").append(AudioManager.adjustToString(mVal1))
393                             .append(" flags:0x").append(Integer.toHexString(mVal2))
394                             .append(") from ").append(mCaller)
395                             .toString();
396                 case VOL_VOICE_ACTIVITY_HEARING_AID:
397                     return new StringBuilder("Voice activity change (")
398                             .append(mVal2 == 1 ? "active" : "inactive")
399                             .append(") causes setting HEARING_AID volume to idx:").append(mVal1)
400                             .append(" stream:").append(AudioSystem.streamToString(mStream))
401                             .toString();
402                 case VOL_MODE_CHANGE_HEARING_AID:
403                     return new StringBuilder("setMode(")
404                             .append(AudioSystem.modeToString(mVal2))
405                             .append(") causes setting HEARING_AID volume to idx:").append(mVal1)
406                             .append(" stream:").append(AudioSystem.streamToString(mStream))
407                             .toString();
408                 case VOL_SET_GROUP_VOL:
409                     return new StringBuilder("setVolumeIndexForAttributes(attr:")
410                             .append(mAudioAttributes.toString())
411                             .append(" group: ").append(mGroupName)
412                             .append(" index:").append(mVal1)
413                             .append(" flags:0x").append(Integer.toHexString(mVal2))
414                             .append(") from ").append(mCaller)
415                             .toString();
416                 case VOL_MUTE_STREAM_INT:
417                     return new StringBuilder("VolumeStreamState.muteInternally(stream:")
418                             .append(AudioSystem.streamToString(mStream))
419                             .append(mVal1 == 1 ? ", muted)" : ", unmuted)")
420                             .toString();
421                 default: return new StringBuilder("FIXME invalid op:").append(mOp).toString();
422             }
423         }
424     }
425 }
426