• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.systemui.volume;
18 
19 import android.media.AudioManager;
20 import android.media.AudioSystem;
21 import android.provider.Settings.Global;
22 import android.util.Log;
23 
24 import com.android.internal.annotations.VisibleForTesting;
25 import com.android.internal.logging.MetricsLogger;
26 import com.android.internal.logging.UiEvent;
27 import com.android.internal.logging.UiEventLogger;
28 import com.android.internal.logging.UiEventLoggerImpl;
29 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
30 import com.android.systemui.plugins.VolumeDialogController.State;
31 
32 import java.util.Arrays;
33 
34 /**
35  *  Interesting events related to the volume.
36  */
37 public class Events {
38     private static final String TAG = Util.logTag(Events.class);
39 
40     public static final int EVENT_SHOW_DIALOG = 0;  // (reason|int) (keyguard|bool)
41     public static final int EVENT_DISMISS_DIALOG = 1; // (reason|int)
42     public static final int EVENT_ACTIVE_STREAM_CHANGED = 2; // (stream|int)
43     public static final int EVENT_EXPAND = 3; // (expand|bool)
44     public static final int EVENT_KEY = 4; // (stream|int) (lastAudibleStreamVolume)
45     public static final int EVENT_COLLECTION_STARTED = 5;
46     public static final int EVENT_COLLECTION_STOPPED = 6;
47     public static final int EVENT_ICON_CLICK = 7; // (stream|int) (icon_state|int)
48     public static final int EVENT_SETTINGS_CLICK = 8;
49     public static final int EVENT_TOUCH_LEVEL_CHANGED = 9; // (stream|int) (level|int)
50     public static final int EVENT_LEVEL_CHANGED = 10; // (stream|int) (level|int)
51     public static final int EVENT_INTERNAL_RINGER_MODE_CHANGED = 11; // (mode|int)
52     public static final int EVENT_EXTERNAL_RINGER_MODE_CHANGED = 12; // (mode|int)
53     public static final int EVENT_ZEN_MODE_CHANGED = 13; // (mode|int)
54     public static final int EVENT_SUPPRESSOR_CHANGED = 14;  // (component|string) (name|string)
55     public static final int EVENT_MUTE_CHANGED = 15;  // (stream|int) (muted|bool)
56     public static final int EVENT_TOUCH_LEVEL_DONE = 16;  // (stream|int) (level|int)
57     public static final int EVENT_ZEN_CONFIG_CHANGED = 17; // (allow/disallow|string)
58     public static final int EVENT_RINGER_TOGGLE = 18; // (ringer_mode)
59     public static final int EVENT_SHOW_USB_OVERHEAT_ALARM = 19; // (reason|int) (keyguard|bool)
60     public static final int EVENT_DISMISS_USB_OVERHEAT_ALARM = 20; // (reason|int) (keyguard|bool)
61     public static final int EVENT_ODI_CAPTIONS_CLICK = 21;
62     public static final int EVENT_ODI_CAPTIONS_TOOLTIP_CLICK = 22;
63 
64     private static final String[] EVENT_TAGS = {
65             "show_dialog",
66             "dismiss_dialog",
67             "active_stream_changed",
68             "expand",
69             "key",
70             "collection_started",
71             "collection_stopped",
72             "icon_click",
73             "settings_click",
74             "touch_level_changed",
75             "level_changed",
76             "internal_ringer_mode_changed",
77             "external_ringer_mode_changed",
78             "zen_mode_changed",
79             "suppressor_changed",
80             "mute_changed",
81             "touch_level_done",
82             "zen_mode_config_changed",
83             "ringer_toggle",
84             "show_usb_overheat_alarm",
85             "dismiss_usb_overheat_alarm",
86             "odi_captions_click",
87             "odi_captions_tooltip_click"
88     };
89 
90     public static final int DISMISS_REASON_UNKNOWN = 0;
91     public static final int DISMISS_REASON_TOUCH_OUTSIDE = 1;
92     public static final int DISMISS_REASON_VOLUME_CONTROLLER = 2;
93     public static final int DISMISS_REASON_TIMEOUT = 3;
94     public static final int DISMISS_REASON_SCREEN_OFF = 4;
95     public static final int DISMISS_REASON_SETTINGS_CLICKED = 5;
96     public static final int DISMISS_REASON_DONE_CLICKED = 6;
97     public static final int DISMISS_STREAM_GONE = 7;
98     public static final int DISMISS_REASON_OUTPUT_CHOOSER = 8;
99     public static final int DISMISS_REASON_USB_OVERHEAD_ALARM_CHANGED = 9;
100     public static final String[] DISMISS_REASONS = {
101             "unknown",
102             "touch_outside",
103             "volume_controller",
104             "timeout",
105             "screen_off",
106             "settings_clicked",
107             "done_clicked",
108             "a11y_stream_changed",
109             "output_chooser",
110             "usb_temperature_below_threshold"
111     };
112 
113     public static final int SHOW_REASON_UNKNOWN = 0;
114     public static final int SHOW_REASON_VOLUME_CHANGED = 1;
115     public static final int SHOW_REASON_REMOTE_VOLUME_CHANGED = 2;
116     public static final int SHOW_REASON_USB_OVERHEAD_ALARM_CHANGED = 3;
117     public static final String[] SHOW_REASONS = {
118         "unknown",
119         "volume_changed",
120         "remote_volume_changed",
121         "usb_temperature_above_threshold"
122     };
123 
124     public static final int ICON_STATE_UNKNOWN = 0;
125     public static final int ICON_STATE_UNMUTE = 1;
126     public static final int ICON_STATE_MUTE = 2;
127     public static final int ICON_STATE_VIBRATE = 3;
128 
129     @VisibleForTesting
130     public enum VolumeDialogOpenEvent implements UiEventLogger.UiEventEnum {
131         //TODO zap the lock/unlock distinction
132         INVALID(0),
133         @UiEvent(doc = "The volume dialog was shown because the volume changed")
134         VOLUME_DIALOG_SHOW_VOLUME_CHANGED(128),
135         @UiEvent(doc = "The volume dialog was shown because the volume changed remotely")
136         VOLUME_DIALOG_SHOW_REMOTE_VOLUME_CHANGED(129),
137         @UiEvent(doc = "The volume dialog was shown because the usb high temperature alarm changed")
138         VOLUME_DIALOG_SHOW_USB_TEMP_ALARM_CHANGED(130);
139 
140         private final int mId;
VolumeDialogOpenEvent(int id)141         VolumeDialogOpenEvent(int id) {
142             mId = id;
143         }
getId()144         public int getId() {
145             return mId;
146         }
fromReasons(int reason)147         static VolumeDialogOpenEvent fromReasons(int reason) {
148             switch (reason) {
149                 case SHOW_REASON_VOLUME_CHANGED:
150                     return VOLUME_DIALOG_SHOW_VOLUME_CHANGED;
151                 case SHOW_REASON_REMOTE_VOLUME_CHANGED:
152                     return VOLUME_DIALOG_SHOW_REMOTE_VOLUME_CHANGED;
153                 case SHOW_REASON_USB_OVERHEAD_ALARM_CHANGED:
154                     return VOLUME_DIALOG_SHOW_USB_TEMP_ALARM_CHANGED;
155             }
156             return INVALID;
157         }
158     }
159 
160     @VisibleForTesting
161     public enum VolumeDialogCloseEvent implements UiEventLogger.UiEventEnum {
162         INVALID(0),
163         @UiEvent(doc = "The volume dialog was dismissed because of a touch outside the dialog")
164         VOLUME_DIALOG_DISMISS_TOUCH_OUTSIDE(134),
165         @UiEvent(doc = "The system asked the volume dialog to close, e.g. for a navigation bar "
166                  + "touch, or ActivityManager ACTION_CLOSE_SYSTEM_DIALOGS broadcast.")
167         VOLUME_DIALOG_DISMISS_SYSTEM(135),
168         @UiEvent(doc = "The volume dialog was dismissed because it timed out")
169         VOLUME_DIALOG_DISMISS_TIMEOUT(136),
170         @UiEvent(doc = "The volume dialog was dismissed because the screen turned off")
171         VOLUME_DIALOG_DISMISS_SCREEN_OFF(137),
172         @UiEvent(doc = "The volume dialog was dismissed because the settings icon was clicked")
173         VOLUME_DIALOG_DISMISS_SETTINGS(138),
174         // reserving 139 for DISMISS_REASON_DONE_CLICKED which is currently unused
175         @UiEvent(doc = "The volume dialog was dismissed because the stream no longer exists")
176         VOLUME_DIALOG_DISMISS_STREAM_GONE(140),
177         // reserving 141 for DISMISS_REASON_OUTPUT_CHOOSER which is currently unused
178         @UiEvent(doc = "The volume dialog was dismissed because the usb high temperature alarm "
179                  + "changed")
180         VOLUME_DIALOG_DISMISS_USB_TEMP_ALARM_CHANGED(142);
181 
182         private final int mId;
VolumeDialogCloseEvent(int id)183         VolumeDialogCloseEvent(int id) {
184             mId = id;
185         }
getId()186         public int getId() {
187             return mId;
188         }
189 
fromReason(int reason)190         static VolumeDialogCloseEvent fromReason(int reason) {
191             switch (reason) {
192                 case DISMISS_REASON_TOUCH_OUTSIDE:
193                     return VOLUME_DIALOG_DISMISS_TOUCH_OUTSIDE;
194                 case DISMISS_REASON_VOLUME_CONTROLLER:
195                     return VOLUME_DIALOG_DISMISS_SYSTEM;
196                 case DISMISS_REASON_TIMEOUT:
197                     return VOLUME_DIALOG_DISMISS_TIMEOUT;
198                 case DISMISS_REASON_SCREEN_OFF:
199                     return VOLUME_DIALOG_DISMISS_SCREEN_OFF;
200                 case DISMISS_REASON_SETTINGS_CLICKED:
201                     return VOLUME_DIALOG_DISMISS_SETTINGS;
202                 case DISMISS_STREAM_GONE:
203                     return VOLUME_DIALOG_DISMISS_STREAM_GONE;
204                 case DISMISS_REASON_USB_OVERHEAD_ALARM_CHANGED:
205                     return VOLUME_DIALOG_DISMISS_USB_TEMP_ALARM_CHANGED;
206             }
207             return INVALID;
208         }
209     }
210 
211     @VisibleForTesting
212     public enum VolumeDialogEvent implements UiEventLogger.UiEventEnum {
213         INVALID(0),
214         @UiEvent(doc = "The volume dialog settings icon was clicked")
215         VOLUME_DIALOG_SETTINGS_CLICK(143),
216         @UiEvent(doc = "The volume dialog details were expanded")
217         VOLUME_DIALOG_EXPAND_DETAILS(144),
218         @UiEvent(doc = "The volume dialog details were collapsed")
219         VOLUME_DIALOG_COLLAPSE_DETAILS(145),
220         @UiEvent(doc = "The active audio stream changed")
221         VOLUME_DIALOG_ACTIVE_STREAM_CHANGED(146),
222         @UiEvent(doc = "The audio stream was muted via icon")
223         VOLUME_DIALOG_MUTE_STREAM(147),
224         @UiEvent(doc = "The audio stream was unmuted via icon")
225         VOLUME_DIALOG_UNMUTE_STREAM(148),
226         @UiEvent(doc = "The audio stream was set to vibrate via icon")
227         VOLUME_DIALOG_TO_VIBRATE_STREAM(149),
228         @UiEvent(doc = "The audio stream was set to non-silent via slider")
229         VOLUME_DIALOG_SLIDER(150),
230         @UiEvent(doc = "The audio stream was set to silent via slider")
231         VOLUME_DIALOG_SLIDER_TO_ZERO(151),
232         @UiEvent(doc = "The audio volume was adjusted to silent via key")
233         VOLUME_KEY_TO_ZERO(152),
234         @UiEvent(doc = "The audio volume was adjusted to non-silent via key")
235         VOLUME_KEY(153),
236         @UiEvent(doc = "The ringer mode was toggled to silent")
237         RINGER_MODE_SILENT(154),
238         @UiEvent(doc = "The ringer mode was toggled to vibrate")
239         RINGER_MODE_VIBRATE(155),
240         @UiEvent(doc = "The ringer mode was toggled to normal")
241         RINGER_MODE_NORMAL(334),
242         @UiEvent(doc = "USB Overheat alarm was raised")
243         USB_OVERHEAT_ALARM(160),
244         @UiEvent(doc = "USB Overheat alarm was dismissed")
245         USB_OVERHEAT_ALARM_DISMISSED(161);
246 
247         private final int mId;
248 
VolumeDialogEvent(int id)249         VolumeDialogEvent(int id) {
250             mId = id;
251         }
252 
getId()253         public int getId() {
254             return mId;
255         }
256 
fromIconState(int iconState)257         static VolumeDialogEvent fromIconState(int iconState) {
258             switch (iconState) {
259                 case ICON_STATE_UNMUTE:
260                     return VOLUME_DIALOG_UNMUTE_STREAM;
261                 case ICON_STATE_MUTE:
262                     return VOLUME_DIALOG_MUTE_STREAM;
263                 case ICON_STATE_VIBRATE:
264                     return VOLUME_DIALOG_TO_VIBRATE_STREAM;
265                 default:
266                     return INVALID;
267             }
268         }
269 
fromSliderLevel(int level)270         static VolumeDialogEvent fromSliderLevel(int level) {
271             return level == 0 ? VOLUME_DIALOG_SLIDER_TO_ZERO : VOLUME_DIALOG_SLIDER;
272         }
273 
fromKeyLevel(int level)274         static VolumeDialogEvent fromKeyLevel(int level) {
275             return level == 0 ? VOLUME_KEY_TO_ZERO : VOLUME_KEY;
276         }
277 
fromRingerMode(int ringerMode)278         static VolumeDialogEvent fromRingerMode(int ringerMode) {
279             switch (ringerMode) {
280                 case AudioManager.RINGER_MODE_SILENT:
281                     return RINGER_MODE_SILENT;
282                 case AudioManager.RINGER_MODE_VIBRATE:
283                     return RINGER_MODE_VIBRATE;
284                 case AudioManager.RINGER_MODE_NORMAL:
285                     return RINGER_MODE_NORMAL;
286                 default:
287                     return INVALID;
288             }
289         }
290     }
291 
292     @VisibleForTesting
293     public enum ZenModeEvent implements UiEventLogger.UiEventEnum {
294         INVALID(0),
295         @UiEvent(doc = "Zen (do not disturb) mode was toggled to off")
296         ZEN_MODE_OFF(335),
297         @UiEvent(doc = "Zen (do not disturb) mode was toggled to important interruptions only")
298         ZEN_MODE_IMPORTANT_ONLY(157),
299         @UiEvent(doc = "Zen (do not disturb) mode was toggled to alarms only")
300         ZEN_MODE_ALARMS_ONLY(158),
301         @UiEvent(doc = "Zen (do not disturb) mode was toggled to block all interruptions")
302         ZEN_MODE_NO_INTERRUPTIONS(159);
303 
304         private final int mId;
ZenModeEvent(int id)305         ZenModeEvent(int id) {
306             mId = id;
307         }
getId()308         public int getId() {
309             return mId;
310         }
311 
fromZenMode(int zenMode)312         static ZenModeEvent fromZenMode(int zenMode) {
313             switch (zenMode) {
314                 case Global.ZEN_MODE_OFF: return ZEN_MODE_OFF;
315                 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return ZEN_MODE_IMPORTANT_ONLY;
316                 case Global.ZEN_MODE_ALARMS: return ZEN_MODE_ALARMS_ONLY;
317                 case Global.ZEN_MODE_NO_INTERRUPTIONS: return ZEN_MODE_NO_INTERRUPTIONS;
318                 default: return INVALID;
319             }
320         }
321     }
322 
323     public static Callback sCallback;
324     @VisibleForTesting
325     static MetricsLogger sLegacyLogger = new MetricsLogger();
326     @VisibleForTesting
327     static UiEventLogger sUiEventLogger = new UiEventLoggerImpl();
328 
329     /**
330      * Logs an event to the system log, to sCallback if present, and to the logEvent destinations.
331      * @param tag One of the EVENT_* codes above.
332      * @param list Any additional event-specific arguments, documented above.
333      */
writeEvent(int tag, Object... list)334     public static void writeEvent(int tag, Object... list) {
335         final long time = System.currentTimeMillis();
336         Log.i(TAG, logEvent(tag, list));
337         if (sCallback != null) {
338             sCallback.writeEvent(time, tag, list);
339         }
340     }
341 
342     /**
343      * Logs an event to the event log and UiEvent (statsd) logging. Compare writeEvent, which
344      * adds more log destinations.
345      * @param tag One of the EVENT_* codes above.
346      * @param list Any additional event-specific arguments, documented above.
347      * @return String a readable description of the event.  Begins "writeEvent <tag_description>"
348      * if the tag is valid.
349      */
logEvent(int tag, Object... list)350     public static String logEvent(int tag, Object... list) {
351         if (tag >= EVENT_TAGS.length) {
352             return "";
353         }
354         final StringBuilder sb = new StringBuilder("writeEvent ").append(EVENT_TAGS[tag]);
355         // Handle events without extra data
356         if (list == null || list.length == 0) {
357             if (tag == EVENT_SETTINGS_CLICK) {
358                 sLegacyLogger.action(MetricsEvent.ACTION_VOLUME_SETTINGS);
359                 sUiEventLogger.log(VolumeDialogEvent.VOLUME_DIALOG_SETTINGS_CLICK);
360             }
361             return sb.toString();
362         }
363         // Handle events with extra data. We've established list[0] exists.
364         sb.append(" ");
365         switch (tag) {
366             case EVENT_SHOW_DIALOG:
367                 sLegacyLogger.visible(MetricsEvent.VOLUME_DIALOG);
368                 if (list.length > 1) {
369                     final Integer reason = (Integer) list[0];
370                     final Boolean keyguard = (Boolean) list[1];
371                     sLegacyLogger.histogram("volume_from_keyguard", keyguard ? 1 : 0);
372                     sUiEventLogger.log(VolumeDialogOpenEvent.fromReasons(reason));
373                     sb.append(SHOW_REASONS[reason]).append(" keyguard=").append(keyguard);
374                 }
375                 break;
376             case EVENT_EXPAND: {
377                 final Boolean expand = (Boolean) list[0];
378                 sLegacyLogger.visibility(MetricsEvent.VOLUME_DIALOG_DETAILS, expand);
379                 sUiEventLogger.log(expand ? VolumeDialogEvent.VOLUME_DIALOG_EXPAND_DETAILS
380                         : VolumeDialogEvent.VOLUME_DIALOG_COLLAPSE_DETAILS);
381                 sb.append(expand);
382                 break;
383             }
384             case EVENT_DISMISS_DIALOG: {
385                 sLegacyLogger.hidden(MetricsEvent.VOLUME_DIALOG);
386                 final Integer reason = (Integer) list[0];
387                 sUiEventLogger.log(VolumeDialogCloseEvent.fromReason(reason));
388                 sb.append(DISMISS_REASONS[reason]);
389                 break;
390             }
391             case EVENT_ACTIVE_STREAM_CHANGED: {
392                 final Integer stream = (Integer) list[0];
393                 sLegacyLogger.action(MetricsEvent.ACTION_VOLUME_STREAM, stream);
394                 sUiEventLogger.log(VolumeDialogEvent.VOLUME_DIALOG_ACTIVE_STREAM_CHANGED);
395                 sb.append(AudioSystem.streamToString(stream));
396                 break;
397             }
398             case EVENT_ICON_CLICK:
399                 if (list.length > 1) {
400                     final Integer stream = (Integer) list[0];
401                     sLegacyLogger.action(MetricsEvent.ACTION_VOLUME_ICON, stream);
402                     final Integer iconState = (Integer) list[1];
403                     sUiEventLogger.log(VolumeDialogEvent.fromIconState(iconState));
404                     sb.append(AudioSystem.streamToString(stream)).append(' ')
405                             .append(iconStateToString(iconState));
406                 }
407                 break;
408             case EVENT_TOUCH_LEVEL_DONE: // (stream|int) (level|int)
409                 if (list.length > 1) {
410                     final Integer level = (Integer) list[1];
411                     sLegacyLogger.action(MetricsEvent.ACTION_VOLUME_SLIDER, level);
412                     sUiEventLogger.log(VolumeDialogEvent.fromSliderLevel(level));
413                 }
414                 // fall through
415             case EVENT_TOUCH_LEVEL_CHANGED:
416             case EVENT_LEVEL_CHANGED:
417             case EVENT_MUTE_CHANGED:  // (stream|int) (level|int)
418                 if (list.length > 1) {
419                     sb.append(AudioSystem.streamToString((Integer) list[0])).append(' ')
420                             .append(list[1]);
421                 }
422                 break;
423             case EVENT_KEY: // (stream|int) (lastAudibleStreamVolume)
424                 if (list.length > 1) {
425                     final Integer stream = (Integer) list[0];
426                     sLegacyLogger.action(MetricsEvent.ACTION_VOLUME_KEY, stream);
427                     final Integer level = (Integer) list[1];
428                     sUiEventLogger.log(VolumeDialogEvent.fromKeyLevel(level));
429                     sb.append(AudioSystem.streamToString(stream)).append(' ').append(level);
430                 }
431                 break;
432             case EVENT_RINGER_TOGGLE: {
433                 final Integer ringerMode = (Integer) list[0];
434                 sLegacyLogger.action(MetricsEvent.ACTION_VOLUME_RINGER_TOGGLE, ringerMode);
435                 sUiEventLogger.log(VolumeDialogEvent.fromRingerMode(ringerMode));
436                 sb.append(ringerModeToString(ringerMode));
437                 break;
438             }
439             case EVENT_EXTERNAL_RINGER_MODE_CHANGED: {
440                 final Integer ringerMode = (Integer) list[0];
441                 sLegacyLogger.action(MetricsEvent.ACTION_RINGER_MODE, ringerMode);
442             }
443                 // fall through
444             case EVENT_INTERNAL_RINGER_MODE_CHANGED: {
445                 final Integer ringerMode = (Integer) list[0];
446                 sb.append(ringerModeToString(ringerMode));
447                 break;
448             }
449             case EVENT_ZEN_MODE_CHANGED: {
450                 final Integer zenMode = (Integer) list[0];
451                 sb.append(zenModeToString(zenMode));
452                 sUiEventLogger.log(ZenModeEvent.fromZenMode(zenMode));
453                 break;
454             }
455             case EVENT_SUPPRESSOR_CHANGED:  // (component|string) (name|string)
456                 if (list.length > 1) {
457                     sb.append(list[0]).append(' ').append(list[1]);
458                 }
459                 break;
460             case EVENT_SHOW_USB_OVERHEAT_ALARM:
461                 sLegacyLogger.visible(MetricsEvent.POWER_OVERHEAT_ALARM);
462                 sUiEventLogger.log(VolumeDialogEvent.USB_OVERHEAT_ALARM);
463                 if (list.length > 1) {
464                     final Boolean keyguard = (Boolean) list[1];
465                     sLegacyLogger.histogram("show_usb_overheat_alarm", keyguard ? 1 : 0);
466                     final Integer reason = (Integer) list[0];
467                     sb.append(SHOW_REASONS[reason]).append(" keyguard=").append(keyguard);
468                 }
469                 break;
470             case EVENT_DISMISS_USB_OVERHEAT_ALARM:
471                 sLegacyLogger.hidden(MetricsEvent.POWER_OVERHEAT_ALARM);
472                 sUiEventLogger.log(VolumeDialogEvent.USB_OVERHEAT_ALARM_DISMISSED);
473                 if (list.length > 1) {
474                     final Boolean keyguard = (Boolean) list[1];
475                     sLegacyLogger.histogram("dismiss_usb_overheat_alarm", keyguard ? 1 : 0);
476                     final Integer reason = (Integer) list[0];
477                     sb.append(DISMISS_REASONS[reason])
478                             .append(" keyguard=").append(keyguard);
479                 }
480                 break;
481             default:
482                 sb.append(Arrays.asList(list));
483                 break;
484         }
485         return sb.toString();
486     }
487 
writeState(long time, State state)488     public static void writeState(long time, State state) {
489         if (sCallback != null) {
490             sCallback.writeState(time, state);
491         }
492     }
493 
iconStateToString(int iconState)494     private static String iconStateToString(int iconState) {
495         switch (iconState) {
496             case ICON_STATE_UNMUTE: return "unmute";
497             case ICON_STATE_MUTE: return "mute";
498             case ICON_STATE_VIBRATE: return "vibrate";
499             default: return "unknown_state_" + iconState;
500         }
501     }
502 
ringerModeToString(int ringerMode)503     private static String ringerModeToString(int ringerMode) {
504         switch (ringerMode) {
505             case AudioManager.RINGER_MODE_SILENT: return "silent";
506             case AudioManager.RINGER_MODE_VIBRATE: return "vibrate";
507             case AudioManager.RINGER_MODE_NORMAL: return "normal";
508             default: return "unknown";
509         }
510     }
511 
zenModeToString(int zenMode)512     private static String zenModeToString(int zenMode) {
513         switch (zenMode) {
514             case Global.ZEN_MODE_OFF: return "off";
515             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return "important_interruptions";
516             case Global.ZEN_MODE_ALARMS: return "alarms";
517             case Global.ZEN_MODE_NO_INTERRUPTIONS: return "no_interruptions";
518             default: return "unknown";
519         }
520     }
521 
522     public interface Callback {
writeEvent(long time, int tag, Object[] list)523         void writeEvent(long time, int tag, Object[] list);
writeState(long time, State state)524         void writeState(long time, State state);
525     }
526 
527 }
528