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.annotation.NonNull;
20 import android.media.AudioDeviceAttributes;
21 import android.media.AudioManager;
22 import android.media.AudioSystem;
23 import android.media.MediaMetrics;
24 
25 import com.android.server.audio.AudioDeviceInventory.WiredDeviceConnectionState;
26 import com.android.server.utils.EventLogger;
27 
28 
29 public class AudioServiceEvents {
30 
31     final static class PhoneStateEvent extends EventLogger.Event {
32         static final int MODE_SET = 0;
33         static final int MODE_IN_COMMUNICATION_TIMEOUT = 1;
34 
35         final int mOp;
36         final String mPackage;
37         final int mOwnerPid;
38         final int mRequesterPid;
39         final int mRequestedMode;
40         final int mActualMode;
41 
42         /** used for MODE_SET */
PhoneStateEvent(String callingPackage, int requesterPid, int requestedMode, int ownerPid, int actualMode)43         PhoneStateEvent(String callingPackage, int requesterPid, int requestedMode,
44                         int ownerPid, int actualMode) {
45             mOp = MODE_SET;
46             mPackage = callingPackage;
47             mRequesterPid = requesterPid;
48             mRequestedMode = requestedMode;
49             mOwnerPid = ownerPid;
50             mActualMode = actualMode;
51             logMetricEvent();
52         }
53 
54         /** used for MODE_IN_COMMUNICATION_TIMEOUT */
PhoneStateEvent(String callingPackage, int ownerPid)55         PhoneStateEvent(String callingPackage, int ownerPid) {
56             mOp = MODE_IN_COMMUNICATION_TIMEOUT;
57             mPackage = callingPackage;
58             mOwnerPid = ownerPid;
59             mRequesterPid = 0;
60             mRequestedMode = 0;
61             mActualMode = 0;
62             logMetricEvent();
63         }
64 
65         @Override
eventToString()66         public String eventToString() {
67             switch (mOp) {
68                 case MODE_SET:
69                     return new StringBuilder("setMode(")
70                             .append(AudioSystem.modeToString(mRequestedMode))
71                             .append(") from package=").append(mPackage)
72                             .append(" pid=").append(mRequesterPid)
73                             .append(" selected mode=")
74                             .append(AudioSystem.modeToString(mActualMode))
75                             .append(" by pid=").append(mOwnerPid).toString();
76                 case MODE_IN_COMMUNICATION_TIMEOUT:
77                     return new StringBuilder("mode IN COMMUNICATION timeout")
78                             .append(" for package=").append(mPackage)
79                             .append(" pid=").append(mOwnerPid).toString();
80                 default: return new StringBuilder("FIXME invalid op:").append(mOp).toString();
81             }
82         }
83 
84         /**
85          * Audio Analytics unique Id.
86          */
87         private static final String mMetricsId = MediaMetrics.Name.AUDIO_MODE;
88 
logMetricEvent()89         private void logMetricEvent() {
90             switch (mOp) {
91                 case MODE_SET:
92                     new MediaMetrics.Item(mMetricsId)
93                             .set(MediaMetrics.Property.EVENT, "set")
94                             .set(MediaMetrics.Property.REQUESTED_MODE,
95                                     AudioSystem.modeToString(mRequestedMode))
96                             .set(MediaMetrics.Property.MODE, AudioSystem.modeToString(mActualMode))
97                             .set(MediaMetrics.Property.CALLING_PACKAGE, mPackage)
98                             .record();
99                     return;
100                 case MODE_IN_COMMUNICATION_TIMEOUT:
101                     new MediaMetrics.Item(mMetricsId)
102                             .set(MediaMetrics.Property.EVENT, "inCommunicationTimeout")
103                             .set(MediaMetrics.Property.CALLING_PACKAGE, mPackage)
104                             .record();
105                     return;
106                 default: return;
107             }
108         }
109     }
110 
111     final static class WiredDevConnectEvent extends EventLogger.Event {
112         final WiredDeviceConnectionState mState;
113 
WiredDevConnectEvent(WiredDeviceConnectionState state)114         WiredDevConnectEvent(WiredDeviceConnectionState state) {
115             mState = state;
116         }
117 
118         @Override
eventToString()119         public String eventToString() {
120             return new StringBuilder("setWiredDeviceConnectionState(")
121                     .append(" type:").append(
122                             Integer.toHexString(mState.mAttributes.getInternalType()))
123                     .append(" (").append(AudioSystem.isInputDevice(
124                             mState.mAttributes.getInternalType()) ? "source" : "sink").append(") ")
125                     .append(" state:").append(AudioSystem.deviceStateToString(mState.mState))
126                     .append(" addr:").append(mState.mAttributes.getAddress())
127                     .append(" name:").append(mState.mAttributes.getName())
128                     .append(") from ").append(mState.mCaller).toString();
129         }
130     }
131 
132     final static class ForceUseEvent extends EventLogger.Event {
133         final int mUsage;
134         final int mConfig;
135         final String mReason;
136 
ForceUseEvent(int usage, int config, String reason)137         ForceUseEvent(int usage, int config, String reason) {
138             mUsage = usage;
139             mConfig = config;
140             mReason = reason;
141         }
142 
143         @Override
eventToString()144         public String eventToString() {
145             return new StringBuilder("setForceUse(")
146                     .append(AudioSystem.forceUseUsageToString(mUsage))
147                     .append(", ").append(AudioSystem.forceUseConfigToString(mConfig))
148                     .append(") due to ").append(mReason).toString();
149         }
150     }
151 
152     static final class VolChangedBroadcastEvent extends EventLogger.Event {
153         final int mStreamType;
154         final String mAliasStreamIndexes;
155         final int mIndex;
156         final int mOldIndex;
157 
VolChangedBroadcastEvent(int stream, String aliasIndexes, int index, int oldIndex)158         VolChangedBroadcastEvent(int stream, String aliasIndexes, int index, int oldIndex) {
159             mStreamType = stream;
160             mAliasStreamIndexes = aliasIndexes;
161             mIndex = index;
162             mOldIndex = oldIndex;
163         }
164 
165         @Override
eventToString()166         public String eventToString() {
167             return new StringBuilder("sending VOLUME_CHANGED stream:")
168                     .append(AudioSystem.streamToString(mStreamType))
169                     .append(" index:").append(mIndex)
170                     .append(" (was:").append(mOldIndex).append(")")
171                     .append(mAliasStreamIndexes)
172                     .toString();
173         }
174     }
175 
176     static final class DeviceVolumeEvent extends EventLogger.Event {
177         final int mStream;
178         final int mVolIndex;
179         final String mDeviceNativeType;
180         final String mDeviceAddress;
181         final String mCaller;
182         final int mDeviceForStream;
183         final boolean mSkipped;
184 
DeviceVolumeEvent(int streamType, int index, @NonNull AudioDeviceAttributes device, int deviceForStream, String callingPackage, boolean skipped)185         DeviceVolumeEvent(int streamType, int index, @NonNull AudioDeviceAttributes device,
186                 int deviceForStream, String callingPackage, boolean skipped) {
187             mStream = streamType;
188             mVolIndex = index;
189             mDeviceNativeType = "0x" + Integer.toHexString(device.getInternalType());
190             mDeviceAddress = device.getAddress();
191             mDeviceForStream = deviceForStream;
192             mCaller = callingPackage;
193             mSkipped = skipped;
194             // log metrics
195             new MediaMetrics.Item(MediaMetrics.Name.AUDIO_VOLUME_EVENT)
196                     .set(MediaMetrics.Property.EVENT, "setDeviceVolume")
197                     .set(MediaMetrics.Property.STREAM_TYPE,
198                             AudioSystem.streamToString(mStream))
199                     .set(MediaMetrics.Property.INDEX, mVolIndex)
200                     .set(MediaMetrics.Property.DEVICE, mDeviceNativeType)
201                     .set(MediaMetrics.Property.ADDRESS, mDeviceAddress)
202                     .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
203                     .record();
204         }
205 
206         @Override
eventToString()207         public String eventToString() {
208             final StringBuilder sb = new StringBuilder("setDeviceVolume(stream:")
209                     .append(AudioSystem.streamToString(mStream))
210                     .append(" index:").append(mVolIndex)
211                     .append(" device:").append(mDeviceNativeType)
212                     .append(" addr:").append(mDeviceAddress)
213                     .append(") from ").append(mCaller);
214             if (mSkipped) {
215                 sb.append(" skipped [device in use]");
216             } else {
217                 sb.append(" currDevForStream:Ox").append(Integer.toHexString(mDeviceForStream));
218             }
219             return sb.toString();
220         }
221     }
222 
223     final static class VolumeEvent extends EventLogger.Event {
224         static final int VOL_ADJUST_SUGG_VOL = 0;
225         static final int VOL_ADJUST_STREAM_VOL = 1;
226         static final int VOL_SET_STREAM_VOL = 2;
227         static final int VOL_SET_HEARING_AID_VOL = 3;
228         static final int VOL_SET_AVRCP_VOL = 4;
229         static final int VOL_ADJUST_VOL_UID = 5;
230         static final int VOL_VOICE_ACTIVITY_HEARING_AID = 6;
231         static final int VOL_MODE_CHANGE_HEARING_AID = 7;
232         static final int VOL_SET_GROUP_VOL = 8;
233         static final int VOL_MUTE_STREAM_INT = 9;
234         static final int VOL_SET_LE_AUDIO_VOL = 10;
235         static final int VOL_ADJUST_GROUP_VOL = 11;
236         static final int VOL_MASTER_MUTE = 12;
237 
238         final int mOp;
239         final int mStream;
240         final int mVal1;
241         final int mVal2;
242         final int mVal3;
243         final String mCaller;
244         final String mGroupName;
245 
246         /** used for VOL_SET_STREAM_VOL */
VolumeEvent(int op, int stream, int val1, int val2, int val3, String caller)247         VolumeEvent(int op, int stream, int val1, int val2, int val3, String caller) {
248             mOp = op;
249             mStream = stream;
250             mVal1 = val1;
251             mVal2 = val2;
252             mVal3 = val3;
253             mCaller = caller;
254             // unused
255             mGroupName = null;
256             logMetricEvent();
257         }
258 
259         /** used for VOL_ADJUST_VOL_UID,
260          *           VOL_ADJUST_SUGG_VOL,
261          *           VOL_ADJUST_STREAM_VOL,
262          *           VOL_SET_LE_AUDIO_VOL
263          */
VolumeEvent(int op, int stream, int val1, int val2, String caller)264         VolumeEvent(int op, int stream, int val1, int val2, String caller) {
265             mOp = op;
266             mStream = stream;
267             mVal1 = val1;
268             mVal2 = val2;
269             mCaller = caller;
270             // unused
271             mVal3 = -1;
272             mGroupName = null;
273             logMetricEvent();
274         }
275 
276         /** used for VOL_SET_HEARING_AID_VOL*/
VolumeEvent(int op, int index, int gainDb)277         VolumeEvent(int op, int index, int gainDb) {
278             mOp = op;
279             mVal1 = index;
280             mVal2 = gainDb;
281             // unused
282             mVal3 = -1;
283             mStream = -1;
284             mCaller = null;
285             mGroupName = null;
286             logMetricEvent();
287         }
288 
289         /** used for VOL_SET_AVRCP_VOL */
VolumeEvent(int op, int index)290         VolumeEvent(int op, int index) {
291             mOp = op;
292             mVal1 = index;
293             // unused
294             mVal2 = 0;
295             mVal3 = -1;
296             mStream = -1;
297             mCaller = null;
298             mGroupName = null;
299             logMetricEvent();
300         }
301 
302         /** used for VOL_VOICE_ACTIVITY_HEARING_AID */
VolumeEvent(int op, boolean voiceActive, int stream, int index)303         VolumeEvent(int op, boolean voiceActive, int stream, int index) {
304             mOp = op;
305             mStream = stream;
306             mVal1 = index;
307             mVal2 = voiceActive ? 1 : 0;
308             // unused
309             mVal3 = -1;
310             mCaller = null;
311             mGroupName = null;
312             logMetricEvent();
313         }
314 
315         /** used for VOL_MODE_CHANGE_HEARING_AID */
VolumeEvent(int op, int mode, int stream, int index)316         VolumeEvent(int op, int mode, int stream, int index) {
317             mOp = op;
318             mStream = stream;
319             mVal1 = index;
320             mVal2 = mode;
321             // unused
322             mVal3 = -1;
323             mCaller = null;
324             mGroupName = null;
325             logMetricEvent();
326         }
327 
328         /** used for VOL_SET_GROUP_VOL,
329          *           VOL_ADJUST_GROUP_VOL */
VolumeEvent(int op, String group, int index, int flags, String caller)330         VolumeEvent(int op, String group, int index, int flags, String caller) {
331             mOp = op;
332             mStream = -1;
333             mVal1 = index;
334             mVal2 = flags;
335             mCaller = caller;
336             mGroupName = group;
337             // unused
338             mVal3 = -1;
339             logMetricEvent();
340         }
341 
342         /** used for VOL_MUTE_STREAM_INT */
VolumeEvent(int op, int stream, boolean state)343         VolumeEvent(int op, int stream, boolean state) {
344             mOp = op;
345             mStream = stream;
346             mVal1 = state ? 1 : 0;
347             mVal2 = 0;
348             // unused
349             mCaller = null;
350             mGroupName = null;
351             mVal3 = -1;
352             logMetricEvent();
353         }
354 
355         /** used for VOL_MASTER_MUTE */
VolumeEvent(int op, boolean state)356         VolumeEvent(int op, boolean state) {
357             mOp = op;
358             mStream = -1;
359             mVal1 = state ? 1 : 0;
360             mVal2 = 0;
361             // unused
362             mVal3 = -1;
363             mCaller = null;
364             mGroupName = null;
365             logMetricEvent();
366         }
367 
368 
369         /**
370          * Audio Analytics unique Id.
371          */
372         private static final String mMetricsId = MediaMetrics.Name.AUDIO_VOLUME_EVENT;
373 
374         /**
375          * Log mediametrics event
376          */
logMetricEvent()377         private void logMetricEvent() {
378             switch (mOp) {
379                 case VOL_ADJUST_SUGG_VOL:
380                 case VOL_ADJUST_VOL_UID:
381                 case VOL_ADJUST_STREAM_VOL: {
382                     String eventName;
383                     switch (mOp) {
384                         case VOL_ADJUST_SUGG_VOL:
385                             eventName = "adjustSuggestedStreamVolume";
386                             break;
387                         case VOL_ADJUST_STREAM_VOL:
388                             eventName = "adjustStreamVolume";
389                             break;
390                         case VOL_ADJUST_VOL_UID:
391                             eventName = "adjustStreamVolumeForUid";
392                             break;
393                         default:
394                             return; // not possible, just return here
395                     }
396                     new MediaMetrics.Item(mMetricsId)
397                             .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
398                             .set(MediaMetrics.Property.DIRECTION, mVal1 > 0 ? "up" : "down")
399                             .set(MediaMetrics.Property.EVENT, eventName)
400                             .set(MediaMetrics.Property.FLAGS, mVal2)
401                             .set(MediaMetrics.Property.STREAM_TYPE,
402                                     AudioSystem.streamToString(mStream))
403                             .record();
404                     return;
405                 }
406                 case VOL_ADJUST_GROUP_VOL:
407                     new MediaMetrics.Item(mMetricsId)
408                             .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
409                             .set(MediaMetrics.Property.DIRECTION, mVal1 > 0 ? "up" : "down")
410                             .set(MediaMetrics.Property.EVENT, "adjustVolumeGroupVolume")
411                             .set(MediaMetrics.Property.FLAGS, mVal2)
412                             .set(MediaMetrics.Property.GROUP, mGroupName)
413                             .record();
414                     return;
415                 case VOL_SET_STREAM_VOL:
416                     new MediaMetrics.Item(mMetricsId)
417                             .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
418                             .set(MediaMetrics.Property.EVENT, "setStreamVolume")
419                             .set(MediaMetrics.Property.FLAGS, mVal2)
420                             .set(MediaMetrics.Property.INDEX, mVal1)
421                             .set(MediaMetrics.Property.OLD_INDEX, mVal3)
422                             .set(MediaMetrics.Property.STREAM_TYPE,
423                                     AudioSystem.streamToString(mStream))
424                             .record();
425                     return;
426                 case VOL_SET_HEARING_AID_VOL:
427                     new MediaMetrics.Item(mMetricsId)
428                             .set(MediaMetrics.Property.EVENT, "setHearingAidVolume")
429                             .set(MediaMetrics.Property.GAIN_DB, (double) mVal2)
430                             .set(MediaMetrics.Property.INDEX, mVal1)
431                             .record();
432                     return;
433                 case VOL_SET_LE_AUDIO_VOL:
434                     new MediaMetrics.Item(mMetricsId)
435                             .set(MediaMetrics.Property.EVENT, "setLeAudioVolume")
436                             .set(MediaMetrics.Property.INDEX, mVal1)
437                             .set(MediaMetrics.Property.MAX_INDEX, mVal2)
438                             .set(MediaMetrics.Property.STREAM_TYPE,
439                                     AudioSystem.streamToString(mStream))
440                             .record();
441                     return;
442                 case VOL_SET_AVRCP_VOL:
443                     new MediaMetrics.Item(mMetricsId)
444                             .set(MediaMetrics.Property.EVENT, "setAvrcpVolume")
445                             .set(MediaMetrics.Property.INDEX, mVal1)
446                             .record();
447                     return;
448                 case VOL_VOICE_ACTIVITY_HEARING_AID:
449                     new MediaMetrics.Item(mMetricsId)
450                             .set(MediaMetrics.Property.EVENT, "voiceActivityHearingAid")
451                             .set(MediaMetrics.Property.INDEX, mVal1)
452                             .set(MediaMetrics.Property.STATE,
453                                     mVal2 == 1 ? "active" : "inactive")
454                             .set(MediaMetrics.Property.STREAM_TYPE,
455                                     AudioSystem.streamToString(mStream))
456                             .record();
457                     return;
458                 case VOL_MODE_CHANGE_HEARING_AID:
459                     new MediaMetrics.Item(mMetricsId)
460                             .set(MediaMetrics.Property.EVENT, "modeChangeHearingAid")
461                             .set(MediaMetrics.Property.INDEX, mVal1)
462                             .set(MediaMetrics.Property.MODE, AudioSystem.modeToString(mVal2))
463                             .set(MediaMetrics.Property.STREAM_TYPE,
464                                     AudioSystem.streamToString(mStream))
465                             .record();
466                     return;
467                 case VOL_SET_GROUP_VOL:
468                     new MediaMetrics.Item(mMetricsId)
469                             .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
470                             .set(MediaMetrics.Property.EVENT, "setVolumeIndexForAttributes")
471                             .set(MediaMetrics.Property.FLAGS, mVal2)
472                             .set(MediaMetrics.Property.GROUP, mGroupName)
473                             .set(MediaMetrics.Property.INDEX, mVal1)
474                             .record();
475                     return;
476                 case VOL_MUTE_STREAM_INT:
477                     // No value in logging metrics for this internal event
478                     return;
479                 case VOL_MASTER_MUTE:
480                     // No value in logging metrics for this internal event
481                     return;
482                 default:
483                     return;
484             }
485         }
486 
487         @Override
eventToString()488         public String eventToString() {
489             switch (mOp) {
490                 case VOL_ADJUST_SUGG_VOL:
491                     return new StringBuilder("adjustSuggestedStreamVolume(sugg:")
492                             .append(AudioSystem.streamToString(mStream))
493                             .append(" dir:").append(AudioManager.adjustToString(mVal1))
494                             .append(" flags:0x").append(Integer.toHexString(mVal2))
495                             .append(") from ").append(mCaller)
496                             .toString();
497                 case VOL_ADJUST_GROUP_VOL:
498                     return new StringBuilder("adjustVolumeGroupVolume(group:")
499                             .append(mGroupName)
500                             .append(" dir:").append(AudioManager.adjustToString(mVal1))
501                             .append(" flags:0x").append(Integer.toHexString(mVal2))
502                             .append(") from ").append(mCaller)
503                             .toString();
504                 case VOL_ADJUST_STREAM_VOL:
505                     return new StringBuilder("adjustStreamVolume(stream:")
506                             .append(AudioSystem.streamToString(mStream))
507                             .append(" dir:").append(AudioManager.adjustToString(mVal1))
508                             .append(" flags:0x").append(Integer.toHexString(mVal2))
509                             .append(") from ").append(mCaller)
510                             .toString();
511                 case VOL_SET_STREAM_VOL:
512                     return new StringBuilder("setStreamVolume(stream:")
513                             .append(AudioSystem.streamToString(mStream))
514                             .append(" index:").append(mVal1)
515                             .append(" flags:0x").append(Integer.toHexString(mVal2))
516                             .append(" oldIndex:").append(mVal3)
517                             .append(") from ").append(mCaller)
518                             .toString();
519                 case VOL_SET_HEARING_AID_VOL:
520                     return new StringBuilder("setHearingAidVolume:")
521                             .append(" index:").append(mVal1)
522                             .append(" gain dB:").append(mVal2)
523                             .toString();
524                 case VOL_SET_LE_AUDIO_VOL:
525                     return new StringBuilder("setLeAudioVolume(stream:")
526                             .append(AudioSystem.streamToString(mStream))
527                             .append(" index:").append(mVal1)
528                             .append(" maxIndex:").append(mVal2)
529                             .toString();
530                 case VOL_SET_AVRCP_VOL:
531                     return new StringBuilder("setAvrcpVolume:")
532                             .append(" index:").append(mVal1)
533                             .toString();
534                 case VOL_ADJUST_VOL_UID:
535                     return new StringBuilder("adjustStreamVolumeForUid(stream:")
536                             .append(AudioSystem.streamToString(mStream))
537                             .append(" dir:").append(AudioManager.adjustToString(mVal1))
538                             .append(" flags:0x").append(Integer.toHexString(mVal2))
539                             .append(") from ").append(mCaller)
540                             .toString();
541                 case VOL_VOICE_ACTIVITY_HEARING_AID:
542                     return new StringBuilder("Voice activity change (")
543                             .append(mVal2 == 1 ? "active" : "inactive")
544                             .append(") causes setting HEARING_AID volume to idx:").append(mVal1)
545                             .append(" stream:").append(AudioSystem.streamToString(mStream))
546                             .toString();
547                 case VOL_MODE_CHANGE_HEARING_AID:
548                     return new StringBuilder("setMode(")
549                             .append(AudioSystem.modeToString(mVal2))
550                             .append(") causes setting HEARING_AID volume to idx:").append(mVal1)
551                             .append(" stream:").append(AudioSystem.streamToString(mStream))
552                             .toString();
553                 case VOL_SET_GROUP_VOL:
554                     return new StringBuilder("setVolumeIndexForAttributes(group:")
555                             .append(" group: ").append(mGroupName)
556                             .append(" index:").append(mVal1)
557                             .append(" flags:0x").append(Integer.toHexString(mVal2))
558                             .append(") from ").append(mCaller)
559                             .toString();
560                 case VOL_MUTE_STREAM_INT:
561                     return new StringBuilder("VolumeStreamState.muteInternally(stream:")
562                             .append(AudioSystem.streamToString(mStream))
563                             .append(mVal1 == 1 ? ", muted)" : ", unmuted)")
564                             .toString();
565                 case VOL_MASTER_MUTE:
566                     return new StringBuilder("Master mute:")
567                             .append(mVal1 == 1 ? " muted)" : " unmuted)")
568                             .toString();
569                 default: return new StringBuilder("FIXME invalid op:").append(mOp).toString();
570             }
571         }
572     }
573 
574     static final class SoundDoseEvent extends EventLogger.Event {
575         static final int MOMENTARY_EXPOSURE = 0;
576         static final int DOSE_UPDATE = 1;
577         static final int DOSE_REPEAT_5X = 2;
578         static final int DOSE_ACCUMULATION_START = 3;
579         static final int LOWER_VOLUME_TO_RS1 = 4;
580 
581         final int mEventType;
582         final float mFloatValue;
583         final long mLongValue;
584 
SoundDoseEvent(int event, float f, long l)585         private SoundDoseEvent(int event, float f, long l) {
586             mEventType = event;
587             mFloatValue = f;
588             mLongValue = l;
589         }
590 
getMomentaryExposureEvent(float mel)591         static SoundDoseEvent getMomentaryExposureEvent(float mel) {
592             return new SoundDoseEvent(MOMENTARY_EXPOSURE, mel, 0 /*ignored*/);
593         }
594 
getDoseUpdateEvent(float csd, long totalDuration)595         static SoundDoseEvent getDoseUpdateEvent(float csd, long totalDuration) {
596             return new SoundDoseEvent(DOSE_UPDATE, csd, totalDuration);
597         }
598 
getDoseRepeat5xEvent()599         static SoundDoseEvent getDoseRepeat5xEvent() {
600             return new SoundDoseEvent(DOSE_REPEAT_5X, 0 /*ignored*/, 0 /*ignored*/);
601         }
602 
getDoseAccumulationStartEvent()603         static SoundDoseEvent getDoseAccumulationStartEvent() {
604             return new SoundDoseEvent(DOSE_ACCUMULATION_START, 0 /*ignored*/, 0 /*ignored*/);
605         }
606 
getLowerVolumeToRs1Event()607         static SoundDoseEvent getLowerVolumeToRs1Event() {
608             return new SoundDoseEvent(LOWER_VOLUME_TO_RS1, 0 /*ignored*/, 0 /*ignored*/);
609         }
610 
611         @Override
eventToString()612         public String eventToString() {
613             switch (mEventType) {
614                 case MOMENTARY_EXPOSURE:
615                     return String.format("momentary exposure MEL=%.2f", mFloatValue);
616                 case DOSE_UPDATE:
617                     return String.format(java.util.Locale.US,
618                             "dose update CSD=%.1f%% total duration=%d",
619                             mFloatValue * 100.0f, mLongValue);
620                 case DOSE_REPEAT_5X:
621                     return "CSD reached 500%";
622                 case DOSE_ACCUMULATION_START:
623                     return "CSD accumulating: RS2 entered";
624                 case LOWER_VOLUME_TO_RS1:
625                     return "CSD lowering volume to RS1";
626             }
627             return new StringBuilder("FIXME invalid event type:").append(mEventType).toString();
628         }
629     }
630 
631     static final class LoudnessEvent extends EventLogger.Event {
632         static final int START_PIID = 0;
633 
634         static final int STOP_PIID = 1;
635 
636         static final int CLIENT_DIED = 2;
637 
638         final int mEventType;
639         final int mIntValue1;
640         final int mIntValue2;
641 
LoudnessEvent(int event, int i1, int i2)642         private LoudnessEvent(int event, int i1, int i2) {
643             mEventType = event;
644             mIntValue1 = i1;
645             mIntValue2 = i2;
646         }
647 
getStartPiid(int piid, int pid)648         static LoudnessEvent getStartPiid(int piid, int pid) {
649             return new LoudnessEvent(START_PIID, piid, pid);
650         }
651 
getStopPiid(int piid, int pid)652         static LoudnessEvent getStopPiid(int piid, int pid) {
653             return new LoudnessEvent(STOP_PIID, piid, pid);
654         }
655 
getClientDied(int pid)656         static LoudnessEvent getClientDied(int pid) {
657             return new LoudnessEvent(CLIENT_DIED, 0 /* ignored */, pid);
658         }
659 
660 
661         @Override
eventToString()662         public String eventToString() {
663             switch (mEventType) {
664                 case START_PIID:
665                     return String.format(
666                             "Start loudness updates for piid %d for client pid %d",
667                             mIntValue1, mIntValue2);
668                 case STOP_PIID:
669                     return String.format(
670                             "Stop loudness updates for piid %d for client pid %d",
671                             mIntValue1, mIntValue2);
672                 case CLIENT_DIED:
673                     return String.format("Loudness client with pid %d died", mIntValue2);
674 
675             }
676             return new StringBuilder("FIXME invalid event type:").append(mEventType).toString();
677         }
678     }
679 
680     /**
681      * Class to log stream type mute/unmute events
682      */
683     static final class StreamMuteEvent extends EventLogger.Event {
684         final int mStreamType;
685         final boolean mMuted;
686         final String mSource;
687 
StreamMuteEvent(int streamType, boolean muted, String source)688         StreamMuteEvent(int streamType, boolean muted, String source) {
689             mStreamType = streamType;
690             mMuted = muted;
691             mSource = source;
692         }
693 
694         @Override
eventToString()695         public String eventToString() {
696             final String streamName =
697                     (mStreamType <= AudioSystem.getNumStreamTypes() && mStreamType >= 0)
698                     ? AudioSystem.STREAM_NAMES[mStreamType]
699                     : ("stream " + mStreamType);
700             return new StringBuilder(streamName)
701                     .append(mMuted ? " muting by " : " unmuting by ")
702                     .append(mSource)
703                     .toString();
704         }
705     }
706 
707     /**
708      * Class to log unmute errors that contradict the ringer/zen mode muted streams
709      */
710     static final class StreamUnmuteErrorEvent extends EventLogger.Event {
711         final int mStreamType;
712         final int mRingerZenMutedStreams;
713 
StreamUnmuteErrorEvent(int streamType, int ringerZenMutedStreams)714         StreamUnmuteErrorEvent(int streamType, int ringerZenMutedStreams) {
715             mStreamType = streamType;
716             mRingerZenMutedStreams = ringerZenMutedStreams;
717         }
718 
719         @Override
eventToString()720         public String eventToString() {
721             final String streamName =
722                     (mStreamType <= AudioSystem.getNumStreamTypes() && mStreamType >= 0)
723                             ? AudioSystem.STREAM_NAMES[mStreamType]
724                             : ("stream " + mStreamType);
725             return new StringBuilder("Invalid call to unmute ")
726                     .append(streamName)
727                     .append(" despite muted streams 0x")
728                     .append(Integer.toHexString(mRingerZenMutedStreams))
729                     .toString();
730         }
731     }
732 
733     static final class RingerZenMutedStreamsEvent extends EventLogger.Event {
734         final int mRingerZenMutedStreams;
735         final String mSource;
736 
RingerZenMutedStreamsEvent(int ringerZenMutedStreams, String source)737         RingerZenMutedStreamsEvent(int ringerZenMutedStreams, String source) {
738             mRingerZenMutedStreams = ringerZenMutedStreams;
739             mSource = source;
740         }
741 
742         @Override
eventToString()743         public String eventToString() {
744             return new StringBuilder("RingerZenMutedStreams 0x")
745                     .append(Integer.toHexString(mRingerZenMutedStreams))
746                     .append(" from ").append(mSource)
747                     .toString();
748         }
749     }
750 }
751