1f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock/*
2f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * Copyright (C) 2015 The Android Open Source Project
3f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *
4f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License");
5f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * you may not use this file except in compliance with the License.
6f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * You may obtain a copy of the License at
7f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *
8f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *      http://www.apache.org/licenses/LICENSE-2.0
9f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *
10f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * Unless required by applicable law or agreed to in writing, software
11f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS,
12f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * See the License for the specific language governing permissions and
14f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * limitations under the License.
15f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock */
16f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
17f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockpackage com.android.systemui.volume;
18f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
19f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.app.NotificationManager;
20f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.BroadcastReceiver;
21f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.ComponentName;
22f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.Context;
23f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.Intent;
24f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.IntentFilter;
25f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.pm.ApplicationInfo;
26f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.pm.PackageManager;
27f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.pm.PackageManager.NameNotFoundException;
28f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.database.ContentObserver;
29f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.AudioManager;
30f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.AudioSystem;
31f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.IVolumeController;
32f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.VolumePolicy;
33f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.session.MediaController.PlaybackInfo;
34f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.session.MediaSession.Token;
35f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.net.Uri;
36f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.os.Handler;
37f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.os.HandlerThread;
38f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.os.Looper;
39f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.os.Message;
40f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.os.RemoteException;
41f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.os.Vibrator;
42f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.provider.Settings;
43f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.service.notification.Condition;
4403c548f292b71eaad576bbc10208283467c775b3Julia Reynoldsimport android.util.ArrayMap;
45f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.util.Log;
46f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
47634acb9712f2627acf9279a78d120ea2da1e0464Yao Chenimport com.android.internal.annotations.GuardedBy;
48782cd6711bc15e3f03456210b3543a67606d6591Jason Monkimport com.android.systemui.Dumpable;
49f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport com.android.systemui.R;
50782cd6711bc15e3f03456210b3543a67606d6591Jason Monkimport com.android.systemui.plugins.VolumeDialogController;
51cd863ad094f38ab6b2339bb7961a34ae11414412John Spurlockimport com.android.systemui.qs.tiles.DndTile;
52f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
53f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.io.FileDescriptor;
54f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.io.PrintWriter;
55f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.util.HashMap;
56f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.util.Map;
57f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.util.Objects;
58f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
59f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock/**
60f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *  Source of truth for all state / events related to the volume dialog.  No presentation.
61f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *
62f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *  All work done on a dedicated background worker thread & associated worker.
63f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *
64f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *  Methods ending in "W" must be called on the worker thread.
65f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock */
66782cd6711bc15e3f03456210b3543a67606d6591Jason Monkpublic class VolumeDialogControllerImpl implements VolumeDialogController, Dumpable {
67782cd6711bc15e3f03456210b3543a67606d6591Jason Monk    private static final String TAG = Util.logTag(VolumeDialogControllerImpl.class);
68f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
69f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private static final int DYNAMIC_STREAM_START_INDEX = 100;
70f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private static final int VIBRATE_HINT_DURATION = 50;
71f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
7203c548f292b71eaad576bbc10208283467c775b3Julia Reynolds    private static final ArrayMap<Integer, Integer> STREAMS = new ArrayMap<>();
7303c548f292b71eaad576bbc10208283467c775b3Julia Reynolds    static {
7403c548f292b71eaad576bbc10208283467c775b3Julia Reynolds        STREAMS.put(AudioSystem.STREAM_ALARM, R.string.stream_alarm);
7503c548f292b71eaad576bbc10208283467c775b3Julia Reynolds        STREAMS.put(AudioSystem.STREAM_BLUETOOTH_SCO, R.string.stream_bluetooth_sco);
7603c548f292b71eaad576bbc10208283467c775b3Julia Reynolds        STREAMS.put(AudioSystem.STREAM_DTMF, R.string.stream_dtmf);
7703c548f292b71eaad576bbc10208283467c775b3Julia Reynolds        STREAMS.put(AudioSystem.STREAM_MUSIC, R.string.stream_music);
78dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds        STREAMS.put(AudioSystem.STREAM_ACCESSIBILITY, R.string.stream_accessibility);
7903c548f292b71eaad576bbc10208283467c775b3Julia Reynolds        STREAMS.put(AudioSystem.STREAM_NOTIFICATION, R.string.stream_notification);
8003c548f292b71eaad576bbc10208283467c775b3Julia Reynolds        STREAMS.put(AudioSystem.STREAM_RING, R.string.stream_ring);
8103c548f292b71eaad576bbc10208283467c775b3Julia Reynolds        STREAMS.put(AudioSystem.STREAM_SYSTEM, R.string.stream_system);
8203c548f292b71eaad576bbc10208283467c775b3Julia Reynolds        STREAMS.put(AudioSystem.STREAM_SYSTEM_ENFORCED, R.string.stream_system_enforced);
8303c548f292b71eaad576bbc10208283467c775b3Julia Reynolds        STREAMS.put(AudioSystem.STREAM_TTS, R.string.stream_tts);
8403c548f292b71eaad576bbc10208283467c775b3Julia Reynolds        STREAMS.put(AudioSystem.STREAM_VOICE_CALL, R.string.stream_voice_call);
8503c548f292b71eaad576bbc10208283467c775b3Julia Reynolds    }
86f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
87f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final HandlerThread mWorkerThread;
88f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final W mWorker;
89f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final Context mContext;
90634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    private AudioManager mAudio;
91f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final NotificationManager mNoMan;
92f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final SettingObserver mObserver;
93f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final Receiver mReceiver = new Receiver();
94f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final MediaSessions mMediaSessions;
95f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final C mCallbacks = new C();
96f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final State mState = new State();
97f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final MediaSessionsCallbacks mMediaSessionsCallbacksW = new MediaSessionsCallbacks();
98f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final Vibrator mVibrator;
99f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final boolean mHasVibrator;
100dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds    private boolean mShowA11yStream;
101f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
102f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean mDestroyed;
103b02c744f05b0cca05b77fcbaad4a546ad86081ebJohn Spurlock    private VolumePolicy mVolumePolicy;
104d9c75dba75ad4742dbaadc34db99d2b76cebca91John Spurlock    private boolean mShowDndTile = true;
105634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    @GuardedBy("this")
106634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    private UserActivityListener mUserActivityListener;
107634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen
108634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    protected final VC mVolumeController = new VC();
109f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
110782cd6711bc15e3f03456210b3543a67606d6591Jason Monk    public VolumeDialogControllerImpl(Context context) {
111f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mContext = context.getApplicationContext();
112e565ee6ccbac4e820eb2737890aadb5efe9d4e3bChris Wren        Events.writeEvent(mContext, Events.EVENT_COLLECTION_STARTED);
113782cd6711bc15e3f03456210b3543a67606d6591Jason Monk        mWorkerThread = new HandlerThread(VolumeDialogControllerImpl.class.getSimpleName());
114f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorkerThread.start();
115f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorker = new W(mWorkerThread.getLooper());
116f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mMediaSessions = createMediaSessions(mContext, mWorkerThread.getLooper(),
117f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mMediaSessionsCallbacksW);
118f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mAudio = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
119f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mNoMan = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
120f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mObserver = new SettingObserver(mWorker);
121f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mObserver.init();
122f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mReceiver.init();
123f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
124f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mHasVibrator = mVibrator != null && mVibrator.hasVibrator();
125f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
126f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
12776b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock    public AudioManager getAudioManager() {
12876b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock        return mAudio;
12976b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock    }
13076b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock
131f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void dismiss() {
132f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mCallbacks.onDismissRequested(Events.DISMISS_REASON_VOLUME_CONTROLLER);
133f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
134f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
135634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    protected void setVolumeController() {
136f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        try {
137f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mAudio.setVolumeController(mVolumeController);
138f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        } catch (SecurityException e) {
139f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            Log.w(TAG, "Unable to set the volume controller", e);
140f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            return;
141f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
142634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    }
143634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen
144634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    protected void setAudioManagerStreamVolume(int stream, int level, int flag) {
145634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        mAudio.setStreamVolume(stream, level, flag);
146634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    }
147634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen
148634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    protected int getAudioManagerStreamVolume(int stream) {
149634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        return mAudio.getLastAudibleStreamVolume(stream);
150634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    }
151634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen
152634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    protected int getAudioManagerStreamMaxVolume(int stream) {
153634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        return mAudio.getStreamMaxVolume(stream);
154634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    }
155634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen
156634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    protected int getAudioManagerStreamMinVolume(int stream) {
157634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        return mAudio.getStreamMinVolume(stream);
158634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    }
159634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen
160634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    public void register() {
161634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        setVolumeController();
162f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        setVolumePolicy(mVolumePolicy);
163f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        showDndTile(mShowDndTile);
164f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        try {
165f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mMediaSessions.init();
166f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        } catch (SecurityException e) {
167f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            Log.w(TAG, "No access to media sessions", e);
168f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
169f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
170f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
171f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void setVolumePolicy(VolumePolicy policy) {
172f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mVolumePolicy = policy;
173b02c744f05b0cca05b77fcbaad4a546ad86081ebJohn Spurlock        if (mVolumePolicy == null) return;
174f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        try {
175f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mAudio.setVolumePolicy(mVolumePolicy);
176f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        } catch (NoSuchMethodError e) {
177f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            Log.w(TAG, "No volume policy api");
178f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
179f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
180f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
181f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    protected MediaSessions createMediaSessions(Context context, Looper looper,
182f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            MediaSessions.Callbacks callbacks) {
183f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return new MediaSessions(context, looper, callbacks);
184f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
185f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
186f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void destroy() {
187f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (D.BUG) Log.d(TAG, "destroy");
188f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mDestroyed) return;
189f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mDestroyed = true;
190e565ee6ccbac4e820eb2737890aadb5efe9d4e3bChris Wren        Events.writeEvent(mContext, Events.EVENT_COLLECTION_STOPPED);
191f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mMediaSessions.destroy();
192f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mObserver.destroy();
193f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mReceiver.destroy();
194f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorkerThread.quitSafely();
195f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
196f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
197f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
198782cd6711bc15e3f03456210b3543a67606d6591Jason Monk        pw.println(VolumeDialogControllerImpl.class.getSimpleName() + " state:");
199f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        pw.print("  mDestroyed: "); pw.println(mDestroyed);
200f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        pw.print("  mVolumePolicy: "); pw.println(mVolumePolicy);
201e56efa71bbb71b65ffdc37313c2745bff9ab912eJohn Spurlock        pw.print("  mState: "); pw.println(mState.toString(4));
202f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        pw.print("  mShowDndTile: "); pw.println(mShowDndTile);
203f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        pw.print("  mHasVibrator: "); pw.println(mHasVibrator);
204f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        pw.print("  mRemoteStreams: "); pw.println(mMediaSessionsCallbacksW.mRemoteStreams
205f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                .values());
206dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds        pw.print("  mShowA11yStream: "); pw.println(mShowA11yStream);
207f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        pw.println();
208f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mMediaSessions.dump(pw);
209f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
210f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
211f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void addCallback(Callbacks callback, Handler handler) {
212f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mCallbacks.add(callback, handler);
213f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
214f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
215634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    public void setUserActivityListener(UserActivityListener listener) {
216634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        if (mDestroyed) return;
217634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        synchronized (this) {
218634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen            mUserActivityListener = listener;
219634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        }
220634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    }
221634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen
222f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void removeCallback(Callbacks callback) {
223f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mCallbacks.remove(callback);
224f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
225f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
226f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void getState() {
227f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mDestroyed) return;
228f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorker.sendEmptyMessage(W.GET_STATE);
229f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
230f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
231f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void notifyVisible(boolean visible) {
232f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mDestroyed) return;
233f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorker.obtainMessage(W.NOTIFY_VISIBLE, visible ? 1 : 0, 0).sendToTarget();
234f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
235f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
236f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void userActivity() {
237f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mDestroyed) return;
238f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorker.removeMessages(W.USER_ACTIVITY);
239f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorker.sendEmptyMessage(W.USER_ACTIVITY);
240f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
241f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
242f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void setRingerMode(int value, boolean external) {
243f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mDestroyed) return;
244f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorker.obtainMessage(W.SET_RINGER_MODE, value, external ? 1 : 0).sendToTarget();
245f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
246f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
247f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void setZenMode(int value) {
248f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mDestroyed) return;
249f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorker.obtainMessage(W.SET_ZEN_MODE, value, 0).sendToTarget();
250f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
251f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
252f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void setExitCondition(Condition condition) {
253f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mDestroyed) return;
254f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorker.obtainMessage(W.SET_EXIT_CONDITION, condition).sendToTarget();
255f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
256f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
257f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void setStreamMute(int stream, boolean mute) {
258f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mDestroyed) return;
259f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorker.obtainMessage(W.SET_STREAM_MUTE, stream, mute ? 1 : 0).sendToTarget();
260f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
261f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
262f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void setStreamVolume(int stream, int level) {
263f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mDestroyed) return;
264f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorker.obtainMessage(W.SET_STREAM_VOLUME, stream, level).sendToTarget();
265f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
266f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
267f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void setActiveStream(int stream) {
268f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mDestroyed) return;
269f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mWorker.obtainMessage(W.SET_ACTIVE_STREAM, stream, 0).sendToTarget();
270f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
271f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
272f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void vibrate() {
273f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mHasVibrator) {
274f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mVibrator.vibrate(VIBRATE_HINT_DURATION);
275f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
276f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
277f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
278f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public boolean hasVibrator() {
279f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return mHasVibrator;
280f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
281f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
282f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private void onNotifyVisibleW(boolean visible) {
283f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mDestroyed) return;
284f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mAudio.notifyVolumeControllerVisible(mVolumeController, visible);
285f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (!visible) {
286f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (updateActiveStreamW(-1)) {
287f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mCallbacks.onStateChanged(mState);
288f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
289f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
290f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
291f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
292634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    private void onUserActivityW() {
293634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        synchronized (this) {
294634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen            if (mUserActivityListener != null) {
295634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen                mUserActivityListener.onUserActivity();
296634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen            }
297634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        }
298f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
299f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
30076b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock    private void onShowSafetyWarningW(int flags) {
30176b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock        mCallbacks.onShowSafetyWarning(flags);
30276b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock    }
30376b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock
304dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds    private void onAccessibilityModeChanged(Boolean showA11yStream) {
305dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds        mCallbacks.onAccessibilityModeChanged(showA11yStream);
306dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds    }
307dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds
308f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean checkRoutedToBluetoothW(int stream) {
309f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        boolean changed = false;
310f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (stream == AudioManager.STREAM_MUSIC) {
311f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final boolean routedToBluetooth =
312f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    (mAudio.getDevicesForStream(AudioManager.STREAM_MUSIC) &
313f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                            (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP |
314f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                            AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
315f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                            AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0;
316f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            changed |= updateStreamRoutedToBluetoothW(stream, routedToBluetooth);
317f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
318f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return changed;
319f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
320f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
3218ae994f841f0e729b5a22ffb90d97710e12082bdJulia Reynolds    private boolean onVolumeChangedW(int stream, int flags) {
322f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final boolean showUI = (flags & AudioManager.FLAG_SHOW_UI) != 0;
323f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final boolean fromKey = (flags & AudioManager.FLAG_FROM_KEY) != 0;
324f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final boolean showVibrateHint = (flags & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0;
325f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final boolean showSilentHint = (flags & AudioManager.FLAG_SHOW_SILENT_HINT) != 0;
326f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        boolean changed = false;
327f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (showUI) {
328f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            changed |= updateActiveStreamW(stream);
329f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
330634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        int lastAudibleStreamVolume = getAudioManagerStreamVolume(stream);
331e565ee6ccbac4e820eb2737890aadb5efe9d4e3bChris Wren        changed |= updateStreamLevelW(stream, lastAudibleStreamVolume);
332f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        changed |= checkRoutedToBluetoothW(showUI ? AudioManager.STREAM_MUSIC : stream);
333f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (changed) {
334f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mCallbacks.onStateChanged(mState);
335f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
336f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (showUI) {
337f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mCallbacks.onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED);
338f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
339f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (showVibrateHint) {
340f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mCallbacks.onShowVibrateHint();
341f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
342f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (showSilentHint) {
343f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mCallbacks.onShowSilentHint();
344f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
345f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (changed && fromKey) {
346e565ee6ccbac4e820eb2737890aadb5efe9d4e3bChris Wren            Events.writeEvent(mContext, Events.EVENT_KEY, stream, lastAudibleStreamVolume);
347f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
3488ae994f841f0e729b5a22ffb90d97710e12082bdJulia Reynolds        return changed;
349f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
350f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
351f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean updateActiveStreamW(int activeStream) {
352f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (activeStream == mState.activeStream) return false;
353f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mState.activeStream = activeStream;
354e565ee6ccbac4e820eb2737890aadb5efe9d4e3bChris Wren        Events.writeEvent(mContext, Events.EVENT_ACTIVE_STREAM_CHANGED, activeStream);
355f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (D.BUG) Log.d(TAG, "updateActiveStreamW " + activeStream);
356f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final int s = activeStream < DYNAMIC_STREAM_START_INDEX ? activeStream : -1;
357f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (D.BUG) Log.d(TAG, "forceVolumeControlStream " + s);
358f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mAudio.forceVolumeControlStream(s);
359f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return true;
360f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
361f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
362f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private StreamState streamStateW(int stream) {
363f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        StreamState ss = mState.states.get(stream);
364f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (ss == null) {
365f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            ss = new StreamState();
366f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mState.states.put(stream, ss);
367f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
368f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return ss;
369f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
370f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
371f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private void onGetStateW() {
37203c548f292b71eaad576bbc10208283467c775b3Julia Reynolds        for (int stream : STREAMS.keySet()) {
373634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen            updateStreamLevelW(stream, getAudioManagerStreamVolume(stream));
374634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen            streamStateW(stream).levelMin = getAudioManagerStreamMinVolume(stream);
375634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen            streamStateW(stream).levelMax = getAudioManagerStreamMaxVolume(stream);
376f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            updateStreamMuteW(stream, mAudio.isStreamMute(stream));
377f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final StreamState ss = streamStateW(stream);
378f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            ss.muteSupported = mAudio.isStreamAffectedByMute(stream);
37903c548f292b71eaad576bbc10208283467c775b3Julia Reynolds            ss.name = STREAMS.get(stream);
380f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            checkRoutedToBluetoothW(stream);
381f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
382f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        updateRingerModeExternalW(mAudio.getRingerMode());
383f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        updateZenModeW();
384f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
385f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mCallbacks.onStateChanged(mState);
386f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
387f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
388f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean updateStreamRoutedToBluetoothW(int stream, boolean routedToBluetooth) {
389f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final StreamState ss = streamStateW(stream);
390f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (ss.routedToBluetooth == routedToBluetooth) return false;
391f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        ss.routedToBluetooth = routedToBluetooth;
392f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (D.BUG) Log.d(TAG, "updateStreamRoutedToBluetoothW stream=" + stream
393f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                + " routedToBluetooth=" + routedToBluetooth);
394f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return true;
395f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
396f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
397f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean updateStreamLevelW(int stream, int level) {
398f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final StreamState ss = streamStateW(stream);
399f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (ss.level == level) return false;
400f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        ss.level = level;
401f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (isLogWorthy(stream)) {
402e565ee6ccbac4e820eb2737890aadb5efe9d4e3bChris Wren            Events.writeEvent(mContext, Events.EVENT_LEVEL_CHANGED, stream, level);
403f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
404f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return true;
405f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
406f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
407f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private static boolean isLogWorthy(int stream) {
408f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        switch (stream) {
409f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            case AudioSystem.STREAM_ALARM:
410f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            case AudioSystem.STREAM_BLUETOOTH_SCO:
411f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            case AudioSystem.STREAM_MUSIC:
412f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            case AudioSystem.STREAM_RING:
413f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            case AudioSystem.STREAM_SYSTEM:
414f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            case AudioSystem.STREAM_VOICE_CALL:
415f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                return true;
416f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
417f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return false;
418f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
419f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
420f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean updateStreamMuteW(int stream, boolean muted) {
421f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final StreamState ss = streamStateW(stream);
422f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (ss.muted == muted) return false;
423f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        ss.muted = muted;
424f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (isLogWorthy(stream)) {
425e565ee6ccbac4e820eb2737890aadb5efe9d4e3bChris Wren            Events.writeEvent(mContext, Events.EVENT_MUTE_CHANGED, stream, muted);
426f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
427f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (muted && isRinger(stream)) {
428f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            updateRingerModeInternalW(mAudio.getRingerModeInternal());
429f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
430f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return true;
431f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
432f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
433f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private static boolean isRinger(int stream) {
434f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION;
435f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
436f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
437f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean updateEffectsSuppressorW(ComponentName effectsSuppressor) {
438f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (Objects.equals(mState.effectsSuppressor, effectsSuppressor)) return false;
439f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mState.effectsSuppressor = effectsSuppressor;
440f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mState.effectsSuppressorName = getApplicationName(mContext, mState.effectsSuppressor);
441e565ee6ccbac4e820eb2737890aadb5efe9d4e3bChris Wren        Events.writeEvent(mContext, Events.EVENT_SUPPRESSOR_CHANGED, mState.effectsSuppressor,
442f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mState.effectsSuppressorName);
443f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return true;
444f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
445f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
446f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private static String getApplicationName(Context context, ComponentName component) {
447f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (component == null) return null;
448f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final PackageManager pm = context.getPackageManager();
449f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final String pkg = component.getPackageName();
450f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        try {
451f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
452f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final String rt = Objects.toString(ai.loadLabel(pm), "").trim();
453f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (rt.length() > 0) {
454f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                return rt;
455f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
456f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        } catch (NameNotFoundException e) {}
457f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return pkg;
458f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
459f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
460f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean updateZenModeW() {
461f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final int zen = Settings.Global.getInt(mContext.getContentResolver(),
462f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
463f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mState.zenMode == zen) return false;
464f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mState.zenMode = zen;
465e565ee6ccbac4e820eb2737890aadb5efe9d4e3bChris Wren        Events.writeEvent(mContext, Events.EVENT_ZEN_MODE_CHANGED, zen);
466f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return true;
467f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
468f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
469f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean updateRingerModeExternalW(int rm) {
470f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (rm == mState.ringerModeExternal) return false;
471f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mState.ringerModeExternal = rm;
472e565ee6ccbac4e820eb2737890aadb5efe9d4e3bChris Wren        Events.writeEvent(mContext, Events.EVENT_EXTERNAL_RINGER_MODE_CHANGED, rm);
473f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return true;
474f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
475f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
476f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean updateRingerModeInternalW(int rm) {
477f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (rm == mState.ringerModeInternal) return false;
478f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mState.ringerModeInternal = rm;
479e565ee6ccbac4e820eb2737890aadb5efe9d4e3bChris Wren        Events.writeEvent(mContext, Events.EVENT_INTERNAL_RINGER_MODE_CHANGED, rm);
480f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return true;
481f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
482f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
483f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private void onSetRingerModeW(int mode, boolean external) {
484f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (external) {
485f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mAudio.setRingerMode(mode);
486f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        } else {
487f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mAudio.setRingerModeInternal(mode);
488f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
489f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
490f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
491f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private void onSetStreamMuteW(int stream, boolean mute) {
492f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mAudio.adjustStreamVolume(stream, mute ? AudioManager.ADJUST_MUTE
493f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                : AudioManager.ADJUST_UNMUTE, 0);
494f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
495f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
496f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private void onSetStreamVolumeW(int stream, int level) {
497f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (D.BUG) Log.d(TAG, "onSetStreamVolume " + stream + " level=" + level);
498f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (stream >= DYNAMIC_STREAM_START_INDEX) {
499f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mMediaSessionsCallbacksW.setStreamVolume(stream, level);
500f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            return;
501f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
502634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        setAudioManagerStreamVolume(stream, level, 0);
503f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
504f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
505f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private void onSetActiveStreamW(int stream) {
506f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        boolean changed = updateActiveStreamW(stream);
507f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (changed) {
508f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mCallbacks.onStateChanged(mState);
509f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
510f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
511f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
512f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private void onSetExitConditionW(Condition condition) {
513b2278d65714c0dd0a6f94d1913db1ebc8bfc8b06John Spurlock        mNoMan.setZenMode(mState.zenMode, condition != null ? condition.id : null, TAG);
514f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
515f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
516f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private void onSetZenModeW(int mode) {
517f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (D.BUG) Log.d(TAG, "onSetZenModeW " + mode);
518b2278d65714c0dd0a6f94d1913db1ebc8bfc8b06John Spurlock        mNoMan.setZenMode(mode, null, TAG);
519f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
520f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
521f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private void onDismissRequestedW(int reason) {
522f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mCallbacks.onDismissRequested(reason);
523f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
524f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
525f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void showDndTile(boolean visible) {
526f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (D.BUG) Log.d(TAG, "showDndTile");
527cd863ad094f38ab6b2339bb7961a34ae11414412John Spurlock        DndTile.setVisible(mContext, visible);
528f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
529f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
530f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final class VC extends IVolumeController.Stub {
531782cd6711bc15e3f03456210b3543a67606d6591Jason Monk        private final String TAG = VolumeDialogControllerImpl.TAG + ".VC";
532f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
533f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
534f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void displaySafeVolumeWarning(int flags) throws RemoteException {
53576b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock            if (D.BUG) Log.d(TAG, "displaySafeVolumeWarning "
53676b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock                    + Util.audioManagerFlagsToString(flags));
53776b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock            if (mDestroyed) return;
53876b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock            mWorker.obtainMessage(W.SHOW_SAFETY_WARNING, flags, 0).sendToTarget();
539f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
540f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
541f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
542f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void volumeChanged(int streamType, int flags) throws RemoteException {
543f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (D.BUG) Log.d(TAG, "volumeChanged " + AudioSystem.streamToString(streamType)
544f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    + " " + Util.audioManagerFlagsToString(flags));
545f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (mDestroyed) return;
546f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mWorker.obtainMessage(W.VOLUME_CHANGED, streamType, flags).sendToTarget();
547f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
548f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
549f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
550f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void masterMuteChanged(int flags) throws RemoteException {
551f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (D.BUG) Log.d(TAG, "masterMuteChanged");
552f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
553f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
554f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
555f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void setLayoutDirection(int layoutDirection) throws RemoteException {
556f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (D.BUG) Log.d(TAG, "setLayoutDirection");
557f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (mDestroyed) return;
558f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mWorker.obtainMessage(W.LAYOUT_DIRECTION_CHANGED, layoutDirection, 0).sendToTarget();
559f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
560f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
561f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
562f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void dismiss() throws RemoteException {
563f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (D.BUG) Log.d(TAG, "dismiss requested");
564f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (mDestroyed) return;
565f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mWorker.obtainMessage(W.DISMISS_REQUESTED, Events.DISMISS_REASON_VOLUME_CONTROLLER, 0)
566f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    .sendToTarget();
567f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mWorker.sendEmptyMessage(W.DISMISS_REQUESTED);
568f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
569ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi
570ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi        @Override
571ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi        public void setA11yMode(int mode) {
572ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi            if (D.BUG) Log.d(TAG, "setA11yMode to " + mode);
573ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi            if (mDestroyed) return;
574ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi            switch (mode) {
575ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi                case VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME:
576ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi                    // "legacy" mode
577dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds                    mShowA11yStream = false;
578ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi                    break;
579ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi                case VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME:
580dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds                    mShowA11yStream = true;
581ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi                    break;
582ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi                default:
583ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi                    Log.e(TAG, "Invalid accessibility mode " + mode);
584ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi                    break;
585ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi            }
586dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds            mWorker.obtainMessage(W.ACCESSIBILITY_MODE_CHANGED, mShowA11yStream).sendToTarget();
587ac48767f919e2a641e4ff5597f7bc24c6d481d41Jean-Michel Trivi        }
588f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
589f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
590f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final class W extends Handler {
591f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int VOLUME_CHANGED = 1;
592f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int DISMISS_REQUESTED = 2;
593f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int GET_STATE = 3;
594f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int SET_RINGER_MODE = 4;
595f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int SET_ZEN_MODE = 5;
596f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int SET_EXIT_CONDITION = 6;
597f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int SET_STREAM_MUTE = 7;
598f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int LAYOUT_DIRECTION_CHANGED = 8;
599f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int CONFIGURATION_CHANGED = 9;
600f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int SET_STREAM_VOLUME = 10;
601f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int SET_ACTIVE_STREAM = 11;
602f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int NOTIFY_VISIBLE = 12;
603f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private static final int USER_ACTIVITY = 13;
60476b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock        private static final int SHOW_SAFETY_WARNING = 14;
605dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds        private static final int ACCESSIBILITY_MODE_CHANGED = 15;
606f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
607f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        W(Looper looper) {
608f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            super(looper);
609f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
610f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
611f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
612f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void handleMessage(Message msg) {
613f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            switch (msg.what) {
614f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                case VOLUME_CHANGED: onVolumeChangedW(msg.arg1, msg.arg2); break;
615f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                case DISMISS_REQUESTED: onDismissRequestedW(msg.arg1); break;
616f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                case GET_STATE: onGetStateW(); break;
617f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                case SET_RINGER_MODE: onSetRingerModeW(msg.arg1, msg.arg2 != 0); break;
618f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                case SET_ZEN_MODE: onSetZenModeW(msg.arg1); break;
619f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                case SET_EXIT_CONDITION: onSetExitConditionW((Condition) msg.obj); break;
620f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                case SET_STREAM_MUTE: onSetStreamMuteW(msg.arg1, msg.arg2 != 0); break;
621f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                case LAYOUT_DIRECTION_CHANGED: mCallbacks.onLayoutDirectionChanged(msg.arg1); break;
622f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                case CONFIGURATION_CHANGED: mCallbacks.onConfigurationChanged(); break;
623f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                case SET_STREAM_VOLUME: onSetStreamVolumeW(msg.arg1, msg.arg2); break;
624f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                case SET_ACTIVE_STREAM: onSetActiveStreamW(msg.arg1); break;
62576b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock                case NOTIFY_VISIBLE: onNotifyVisibleW(msg.arg1 != 0); break;
62676b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock                case USER_ACTIVITY: onUserActivityW(); break;
62776b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock                case SHOW_SAFETY_WARNING: onShowSafetyWarningW(msg.arg1); break;
628dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds                case ACCESSIBILITY_MODE_CHANGED: onAccessibilityModeChanged((Boolean) msg.obj);
629f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
630f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
631f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
632f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
633f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final class C implements Callbacks {
634f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private final HashMap<Callbacks, Handler> mCallbackMap = new HashMap<>();
635f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
636f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void add(Callbacks callback, Handler handler) {
637f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (callback == null || handler == null) throw new IllegalArgumentException();
638f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mCallbackMap.put(callback, handler);
639f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
640f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
641f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void remove(Callbacks callback) {
642f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mCallbackMap.remove(callback);
643f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
644f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
645f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
646f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onShowRequested(final int reason) {
647f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
648f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                entry.getValue().post(new Runnable() {
649f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    @Override
650f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    public void run() {
651f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        entry.getKey().onShowRequested(reason);
652f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    }
653f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                });
654f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
655f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
656f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
657f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
658f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onDismissRequested(final int reason) {
659f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
660f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                entry.getValue().post(new Runnable() {
661f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    @Override
662f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    public void run() {
663f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        entry.getKey().onDismissRequested(reason);
664f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    }
665f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                });
666f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
667f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
668f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
669f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
670f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onStateChanged(final State state) {
671f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final long time = System.currentTimeMillis();
672f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final State copy = state.copy();
673f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
674f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                entry.getValue().post(new Runnable() {
675f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    @Override
676f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    public void run() {
677f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        entry.getKey().onStateChanged(copy);
678f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    }
679f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                });
680f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
681f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            Events.writeState(time, copy);
682f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
683f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
684f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
685f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onLayoutDirectionChanged(final int layoutDirection) {
686f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
687f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                entry.getValue().post(new Runnable() {
688f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    @Override
689f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    public void run() {
690f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        entry.getKey().onLayoutDirectionChanged(layoutDirection);
691f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    }
692f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                });
693f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
694f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
695f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
696f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
697f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onConfigurationChanged() {
698f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
699f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                entry.getValue().post(new Runnable() {
700f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    @Override
701f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    public void run() {
702f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        entry.getKey().onConfigurationChanged();
703f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    }
704f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                });
705f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
706f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
707f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
708f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
709f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onShowVibrateHint() {
710f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
711f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                entry.getValue().post(new Runnable() {
712f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    @Override
713f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    public void run() {
714f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        entry.getKey().onShowVibrateHint();
715f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    }
716f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                });
717f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
718f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
719f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
720f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
721f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onShowSilentHint() {
722f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
723f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                entry.getValue().post(new Runnable() {
724f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    @Override
725f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    public void run() {
726f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        entry.getKey().onShowSilentHint();
727f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    }
728f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                });
729f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
730f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
731f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
732f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
733f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onScreenOff() {
734f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
735f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                entry.getValue().post(new Runnable() {
736f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    @Override
737f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    public void run() {
738f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        entry.getKey().onScreenOff();
739f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    }
740f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                });
741f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
742f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
74376b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock
74476b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock        @Override
74576b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock        public void onShowSafetyWarning(final int flags) {
74676b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
74776b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock                entry.getValue().post(new Runnable() {
74876b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock                    @Override
74976b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock                    public void run() {
75076b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock                        entry.getKey().onShowSafetyWarning(flags);
75176b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock                    }
75276b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock                });
75376b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock            }
75476b52b3f9b0dde7d7800508271cf5851d92b25d5John Spurlock        }
755dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds
756dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds        @Override
757dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds        public void onAccessibilityModeChanged(Boolean showA11yStream) {
758dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds            boolean show = showA11yStream == null ? false : showA11yStream;
759dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
760dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds                entry.getValue().post(new Runnable() {
761dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds                    @Override
762dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds                    public void run() {
763dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds                        entry.getKey().onAccessibilityModeChanged(show);
764dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds                    }
765dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds                });
766dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds            }
767dbfb40f163f98a9aadba68e38222ee4734d17ebaJulia Reynolds        }
768f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
769f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
770f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
771f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final class SettingObserver extends ContentObserver {
772f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private final Uri ZEN_MODE_URI =
773f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
774f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private final Uri ZEN_MODE_CONFIG_URI =
775f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                Settings.Global.getUriFor(Settings.Global.ZEN_MODE_CONFIG_ETAG);
776f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
777f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public SettingObserver(Handler handler) {
778f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            super(handler);
779f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
780f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
781f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void init() {
782f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mContext.getContentResolver().registerContentObserver(ZEN_MODE_URI, false, this);
783f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mContext.getContentResolver().registerContentObserver(ZEN_MODE_CONFIG_URI, false, this);
784f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
785f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
786f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void destroy() {
787f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mContext.getContentResolver().unregisterContentObserver(this);
788f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
789f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
790f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
791f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onChange(boolean selfChange, Uri uri) {
792f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            boolean changed = false;
793f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (ZEN_MODE_URI.equals(uri)) {
794f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                changed = updateZenModeW();
795f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
796f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (changed) {
797f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mCallbacks.onStateChanged(mState);
798f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
799f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
800f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
801f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
802f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final class Receiver extends BroadcastReceiver {
803f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
804f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void init() {
805f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final IntentFilter filter = new IntentFilter();
806f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
807f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
808f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
809f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
810f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            filter.addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION);
811f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
812f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
813f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            filter.addAction(Intent.ACTION_SCREEN_OFF);
814bc7233a8a37dd8090d6e04b8c92bc93c868e16b2John Spurlock            filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
815f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mContext.registerReceiver(this, filter, null, mWorker);
816f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
817f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
818f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void destroy() {
819f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mContext.unregisterReceiver(this);
820f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
821f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
822f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
823f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onReceive(Context context, Intent intent) {
824f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final String action = intent.getAction();
825f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            boolean changed = false;
826f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
827f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
828f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                final int level = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
829f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                final int oldLevel = intent
830f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        .getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);
831f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (D.BUG) Log.d(TAG, "onReceive VOLUME_CHANGED_ACTION stream=" + stream
832f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        + " level=" + level + " oldLevel=" + oldLevel);
833f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                changed = updateStreamLevelW(stream, level);
834f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            } else if (action.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION)) {
835f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
836f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                final int devices = intent
837f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        .getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, -1);
838f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                final int oldDevices = intent
839f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        .getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, -1);
840f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (D.BUG) Log.d(TAG, "onReceive STREAM_DEVICES_CHANGED_ACTION stream="
841f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        + stream + " devices=" + devices + " oldDevices=" + oldDevices);
842f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                changed = checkRoutedToBluetoothW(stream);
8438ae994f841f0e729b5a22ffb90d97710e12082bdJulia Reynolds                changed |= onVolumeChangedW(stream, 0);
844f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
845f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                final int rm = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
846f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (D.BUG) Log.d(TAG, "onReceive RINGER_MODE_CHANGED_ACTION rm="
847f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        + Util.ringerModeToString(rm));
848f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                changed = updateRingerModeExternalW(rm);
849f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            } else if (action.equals(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)) {
850f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                final int rm = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
851f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (D.BUG) Log.d(TAG, "onReceive INTERNAL_RINGER_MODE_CHANGED_ACTION rm="
852f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        + Util.ringerModeToString(rm));
853f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                changed = updateRingerModeInternalW(rm);
854f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            } else if (action.equals(AudioManager.STREAM_MUTE_CHANGED_ACTION)) {
855f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
856f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                final boolean muted = intent
857f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        .getBooleanExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, false);
858f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (D.BUG) Log.d(TAG, "onReceive STREAM_MUTE_CHANGED_ACTION stream=" + stream
859f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        + " muted=" + muted);
860f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                changed = updateStreamMuteW(stream, muted);
861f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            } else if (action.equals(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED)) {
862f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (D.BUG) Log.d(TAG, "onReceive ACTION_EFFECTS_SUPPRESSOR_CHANGED");
863f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                changed = updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
864f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
865f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (D.BUG) Log.d(TAG, "onReceive ACTION_CONFIGURATION_CHANGED");
866f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mCallbacks.onConfigurationChanged();
867f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
868f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (D.BUG) Log.d(TAG, "onReceive ACTION_SCREEN_OFF");
869f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mCallbacks.onScreenOff();
870bc7233a8a37dd8090d6e04b8c92bc93c868e16b2John Spurlock            } else if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
871bc7233a8a37dd8090d6e04b8c92bc93c868e16b2John Spurlock                if (D.BUG) Log.d(TAG, "onReceive ACTION_CLOSE_SYSTEM_DIALOGS");
872bc7233a8a37dd8090d6e04b8c92bc93c868e16b2John Spurlock                dismiss();
873f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
874f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (changed) {
875f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mCallbacks.onStateChanged(mState);
876f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
877f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
878f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
879f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
880f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final class MediaSessionsCallbacks implements MediaSessions.Callbacks {
881f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private final HashMap<Token, Integer> mRemoteStreams = new HashMap<>();
882f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
883f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private int mNextStream = DYNAMIC_STREAM_START_INDEX;
884f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
885f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
886f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onRemoteUpdate(Token token, String name, PlaybackInfo pi) {
887f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (!mRemoteStreams.containsKey(token)) {
888f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mRemoteStreams.put(token, mNextStream);
889f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (D.BUG) Log.d(TAG, "onRemoteUpdate: " + name + " is stream " + mNextStream);
890f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mNextStream++;
891f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
892f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final int stream = mRemoteStreams.get(token);
893f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            boolean changed = mState.states.indexOfKey(stream) < 0;
894f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final StreamState ss = streamStateW(stream);
895f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            ss.dynamic = true;
896f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            ss.levelMin = 0;
897f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            ss.levelMax = pi.getMaxVolume();
898f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (ss.level != pi.getCurrentVolume()) {
899f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                ss.level = pi.getCurrentVolume();
900f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                changed = true;
901f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
90203c548f292b71eaad576bbc10208283467c775b3Julia Reynolds            if (!Objects.equals(ss.remoteLabel, name)) {
90303c548f292b71eaad576bbc10208283467c775b3Julia Reynolds                ss.name = -1;
90403c548f292b71eaad576bbc10208283467c775b3Julia Reynolds                ss.remoteLabel = name;
905f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                changed = true;
906f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
907f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (changed) {
908f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (D.BUG) Log.d(TAG, "onRemoteUpdate: " + name + ": " + ss.level
909f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        + " of " + ss.levelMax);
910f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mCallbacks.onStateChanged(mState);
911f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
912f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
913f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
914f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
915f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onRemoteVolumeChanged(Token token, int flags) {
916f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final int stream = mRemoteStreams.get(token);
917f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final boolean showUI = (flags & AudioManager.FLAG_SHOW_UI) != 0;
918f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            boolean changed = updateActiveStreamW(stream);
919f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (showUI) {
920f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                changed |= checkRoutedToBluetoothW(AudioManager.STREAM_MUSIC);
921f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
922f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (changed) {
923f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mCallbacks.onStateChanged(mState);
924f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
925f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (showUI) {
926f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mCallbacks.onShowRequested(Events.SHOW_REASON_REMOTE_VOLUME_CHANGED);
927f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
928f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
929f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
930f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
931f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onRemoteRemoved(Token token) {
932f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final int stream = mRemoteStreams.get(token);
933f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mState.states.remove(stream);
934f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (mState.activeStream == stream) {
935f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                updateActiveStreamW(-1);
936f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
937f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mCallbacks.onStateChanged(mState);
938f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
939f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
940f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void setStreamVolume(int stream, int level) {
941f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            final Token t = findToken(stream);
942f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (t == null) {
943f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                Log.w(TAG, "setStreamVolume: No token found for stream: " + stream);
944f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                return;
945f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
946f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mMediaSessions.setVolume(t, level);
947f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
948f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
949f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        private Token findToken(int stream) {
950f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            for (Map.Entry<Token, Integer> entry : mRemoteStreams.entrySet()) {
951f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (entry.getValue().equals(stream)) {
952f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    return entry.getKey();
953f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                }
954f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
955f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            return null;
956f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
957f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
958f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
959634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    public interface UserActivityListener {
960634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen        void onUserActivity();
961634acb9712f2627acf9279a78d120ea2da1e0464Yao Chen    }
962f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock}
963