/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.volume;

import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.ContentObserver;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.IVolumeController;
import android.media.VolumePolicy;
import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession.Token;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.Vibrator;
import android.provider.Settings;
import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
import android.util.Log;
import android.util.SparseArray;

import com.android.systemui.R;
import com.android.systemui.qs.tiles.DndTile;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 *  Source of truth for all state / events related to the volume dialog.  No presentation.
 *
 *  All work done on a dedicated background worker thread & associated worker.
 *
 *  Methods ending in "W" must be called on the worker thread.
 */
public class VolumeDialogController {
    private static final String TAG = Util.logTag(VolumeDialogController.class);

    private static final int DYNAMIC_STREAM_START_INDEX = 100;
    private static final int VIBRATE_HINT_DURATION = 50;

    private static final int[] STREAMS = {
        AudioSystem.STREAM_ALARM,
        AudioSystem.STREAM_BLUETOOTH_SCO,
        AudioSystem.STREAM_DTMF,
        AudioSystem.STREAM_MUSIC,
        AudioSystem.STREAM_NOTIFICATION,
        AudioSystem.STREAM_RING,
        AudioSystem.STREAM_SYSTEM,
        AudioSystem.STREAM_SYSTEM_ENFORCED,
        AudioSystem.STREAM_TTS,
        AudioSystem.STREAM_VOICE_CALL,
    };

    private final HandlerThread mWorkerThread;
    private final W mWorker;
    private final Context mContext;
    private final AudioManager mAudio;
    private final NotificationManager mNoMan;
    private final ComponentName mComponent;
    private final SettingObserver mObserver;
    private final Receiver mReceiver = new Receiver();
    private final MediaSessions mMediaSessions;
    private final VC mVolumeController = new VC();
    private final C mCallbacks = new C();
    private final State mState = new State();
    private final String[] mStreamTitles;
    private final MediaSessionsCallbacks mMediaSessionsCallbacksW = new MediaSessionsCallbacks();
    private final Vibrator mVibrator;
    private final boolean mHasVibrator;

    private boolean mEnabled;
    private boolean mDestroyed;
    private VolumePolicy mVolumePolicy;
    private boolean mShowDndTile = true;

    public VolumeDialogController(Context context, ComponentName component) {
        mContext = context.getApplicationContext();
        Events.writeEvent(mContext, Events.EVENT_COLLECTION_STARTED);
        mComponent = component;
        mWorkerThread = new HandlerThread(VolumeDialogController.class.getSimpleName());
        mWorkerThread.start();
        mWorker = new W(mWorkerThread.getLooper());
        mMediaSessions = createMediaSessions(mContext, mWorkerThread.getLooper(),
                mMediaSessionsCallbacksW);
        mAudio = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        mNoMan = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        mObserver = new SettingObserver(mWorker);
        mObserver.init();
        mReceiver.init();
        mStreamTitles = mContext.getResources().getStringArray(R.array.volume_stream_titles);
        mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
        mHasVibrator = mVibrator != null && mVibrator.hasVibrator();
    }

    public AudioManager getAudioManager() {
        return mAudio;
    }

    public ZenModeConfig getZenModeConfig() {
        return mNoMan.getZenModeConfig();
    }

    public void dismiss() {
        mCallbacks.onDismissRequested(Events.DISMISS_REASON_VOLUME_CONTROLLER);
    }

    public void register() {
        try {
            mAudio.setVolumeController(mVolumeController);
        } catch (SecurityException e) {
            Log.w(TAG, "Unable to set the volume controller", e);
            return;
        }
        setVolumePolicy(mVolumePolicy);
        showDndTile(mShowDndTile);
        try {
            mMediaSessions.init();
        } catch (SecurityException e) {
            Log.w(TAG, "No access to media sessions", e);
        }
    }

    public void setVolumePolicy(VolumePolicy policy) {
        mVolumePolicy = policy;
        if (mVolumePolicy == null) return;
        try {
            mAudio.setVolumePolicy(mVolumePolicy);
        } catch (NoSuchMethodError e) {
            Log.w(TAG, "No volume policy api");
        }
    }

    protected MediaSessions createMediaSessions(Context context, Looper looper,
            MediaSessions.Callbacks callbacks) {
        return new MediaSessions(context, looper, callbacks);
    }

    public void destroy() {
        if (D.BUG) Log.d(TAG, "destroy");
        if (mDestroyed) return;
        mDestroyed = true;
        Events.writeEvent(mContext, Events.EVENT_COLLECTION_STOPPED);
        mMediaSessions.destroy();
        mObserver.destroy();
        mReceiver.destroy();
        mWorkerThread.quitSafely();
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println(VolumeDialogController.class.getSimpleName() + " state:");
        pw.print("  mEnabled: "); pw.println(mEnabled);
        pw.print("  mDestroyed: "); pw.println(mDestroyed);
        pw.print("  mVolumePolicy: "); pw.println(mVolumePolicy);
        pw.print("  mState: "); pw.println(mState.toString(4));
        pw.print("  mShowDndTile: "); pw.println(mShowDndTile);
        pw.print("  mHasVibrator: "); pw.println(mHasVibrator);
        pw.print("  mRemoteStreams: "); pw.println(mMediaSessionsCallbacksW.mRemoteStreams
                .values());
        pw.println();
        mMediaSessions.dump(pw);
    }

    public void addCallback(Callbacks callback, Handler handler) {
        mCallbacks.add(callback, handler);
    }

    public void removeCallback(Callbacks callback) {
        mCallbacks.remove(callback);
    }

    public void getState() {
        if (mDestroyed) return;
        mWorker.sendEmptyMessage(W.GET_STATE);
    }

    public void notifyVisible(boolean visible) {
        if (mDestroyed) return;
        mWorker.obtainMessage(W.NOTIFY_VISIBLE, visible ? 1 : 0, 0).sendToTarget();
    }

    public void userActivity() {
        if (mDestroyed) return;
        mWorker.removeMessages(W.USER_ACTIVITY);
        mWorker.sendEmptyMessage(W.USER_ACTIVITY);
    }

    public void setRingerMode(int value, boolean external) {
        if (mDestroyed) return;
        mWorker.obtainMessage(W.SET_RINGER_MODE, value, external ? 1 : 0).sendToTarget();
    }

    public void setZenMode(int value) {
        if (mDestroyed) return;
        mWorker.obtainMessage(W.SET_ZEN_MODE, value, 0).sendToTarget();
    }

    public void setExitCondition(Condition condition) {
        if (mDestroyed) return;
        mWorker.obtainMessage(W.SET_EXIT_CONDITION, condition).sendToTarget();
    }

    public void setStreamMute(int stream, boolean mute) {
        if (mDestroyed) return;
        mWorker.obtainMessage(W.SET_STREAM_MUTE, stream, mute ? 1 : 0).sendToTarget();
    }

    public void setStreamVolume(int stream, int level) {
        if (mDestroyed) return;
        mWorker.obtainMessage(W.SET_STREAM_VOLUME, stream, level).sendToTarget();
    }

    public void setActiveStream(int stream) {
        if (mDestroyed) return;
        mWorker.obtainMessage(W.SET_ACTIVE_STREAM, stream, 0).sendToTarget();
    }

    public void vibrate() {
        if (mHasVibrator) {
            mVibrator.vibrate(VIBRATE_HINT_DURATION);
        }
    }

    public boolean hasVibrator() {
        return mHasVibrator;
    }

    private void onNotifyVisibleW(boolean visible) {
        if (mDestroyed) return;
        mAudio.notifyVolumeControllerVisible(mVolumeController, visible);
        if (!visible) {
            if (updateActiveStreamW(-1)) {
                mCallbacks.onStateChanged(mState);
            }
        }
    }

    protected void onUserActivityW() {
        // hook for subclasses
    }

    private void onShowSafetyWarningW(int flags) {
        mCallbacks.onShowSafetyWarning(flags);
    }

    private boolean checkRoutedToBluetoothW(int stream) {
        boolean changed = false;
        if (stream == AudioManager.STREAM_MUSIC) {
            final boolean routedToBluetooth =
                    (mAudio.getDevicesForStream(AudioManager.STREAM_MUSIC) &
                            (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP |
                            AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
                            AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0;
            changed |= updateStreamRoutedToBluetoothW(stream, routedToBluetooth);
        }
        return changed;
    }

    private void onVolumeChangedW(int stream, int flags) {
        final boolean showUI = (flags & AudioManager.FLAG_SHOW_UI) != 0;
        final boolean fromKey = (flags & AudioManager.FLAG_FROM_KEY) != 0;
        final boolean showVibrateHint = (flags & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0;
        final boolean showSilentHint = (flags & AudioManager.FLAG_SHOW_SILENT_HINT) != 0;
        boolean changed = false;
        if (showUI) {
            changed |= updateActiveStreamW(stream);
        }
        int lastAudibleStreamVolume = mAudio.getLastAudibleStreamVolume(stream);
        changed |= updateStreamLevelW(stream, lastAudibleStreamVolume);
        changed |= checkRoutedToBluetoothW(showUI ? AudioManager.STREAM_MUSIC : stream);
        if (changed) {
            mCallbacks.onStateChanged(mState);
        }
        if (showUI) {
            mCallbacks.onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED);
        }
        if (showVibrateHint) {
            mCallbacks.onShowVibrateHint();
        }
        if (showSilentHint) {
            mCallbacks.onShowSilentHint();
        }
        if (changed && fromKey) {
            Events.writeEvent(mContext, Events.EVENT_KEY, stream, lastAudibleStreamVolume);
        }
    }

    private boolean updateActiveStreamW(int activeStream) {
        if (activeStream == mState.activeStream) return false;
        mState.activeStream = activeStream;
        Events.writeEvent(mContext, Events.EVENT_ACTIVE_STREAM_CHANGED, activeStream);
        if (D.BUG) Log.d(TAG, "updateActiveStreamW " + activeStream);
        final int s = activeStream < DYNAMIC_STREAM_START_INDEX ? activeStream : -1;
        if (D.BUG) Log.d(TAG, "forceVolumeControlStream " + s);
        mAudio.forceVolumeControlStream(s);
        return true;
    }

    private StreamState streamStateW(int stream) {
        StreamState ss = mState.states.get(stream);
        if (ss == null) {
            ss = new StreamState();
            mState.states.put(stream, ss);
        }
        return ss;
    }

    private void onGetStateW() {
        for (int stream : STREAMS) {
            updateStreamLevelW(stream, mAudio.getLastAudibleStreamVolume(stream));
            streamStateW(stream).levelMin = mAudio.getStreamMinVolume(stream);
            streamStateW(stream).levelMax = mAudio.getStreamMaxVolume(stream);
            updateStreamMuteW(stream, mAudio.isStreamMute(stream));
            final StreamState ss = streamStateW(stream);
            ss.muteSupported = mAudio.isStreamAffectedByMute(stream);
            ss.name = mStreamTitles[stream];
            checkRoutedToBluetoothW(stream);
        }
        updateRingerModeExternalW(mAudio.getRingerMode());
        updateZenModeW();
        updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
        updateZenModeConfigW();
        mCallbacks.onStateChanged(mState);
    }

    private boolean updateStreamRoutedToBluetoothW(int stream, boolean routedToBluetooth) {
        final StreamState ss = streamStateW(stream);
        if (ss.routedToBluetooth == routedToBluetooth) return false;
        ss.routedToBluetooth = routedToBluetooth;
        if (D.BUG) Log.d(TAG, "updateStreamRoutedToBluetoothW stream=" + stream
                + " routedToBluetooth=" + routedToBluetooth);
        return true;
    }

    private boolean updateStreamLevelW(int stream, int level) {
        final StreamState ss = streamStateW(stream);
        if (ss.level == level) return false;
        ss.level = level;
        if (isLogWorthy(stream)) {
            Events.writeEvent(mContext, Events.EVENT_LEVEL_CHANGED, stream, level);
        }
        return true;
    }

    private static boolean isLogWorthy(int stream) {
        switch (stream) {
            case AudioSystem.STREAM_ALARM:
            case AudioSystem.STREAM_BLUETOOTH_SCO:
            case AudioSystem.STREAM_MUSIC:
            case AudioSystem.STREAM_RING:
            case AudioSystem.STREAM_SYSTEM:
            case AudioSystem.STREAM_VOICE_CALL:
                return true;
        }
        return false;
    }

    private boolean updateStreamMuteW(int stream, boolean muted) {
        final StreamState ss = streamStateW(stream);
        if (ss.muted == muted) return false;
        ss.muted = muted;
        if (isLogWorthy(stream)) {
            Events.writeEvent(mContext, Events.EVENT_MUTE_CHANGED, stream, muted);
        }
        if (muted && isRinger(stream)) {
            updateRingerModeInternalW(mAudio.getRingerModeInternal());
        }
        return true;
    }

    private static boolean isRinger(int stream) {
        return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION;
    }

    private boolean updateZenModeConfigW() {
        final ZenModeConfig zenModeConfig = getZenModeConfig();
        if (Objects.equals(mState.zenModeConfig, zenModeConfig)) return false;
        mState.zenModeConfig = zenModeConfig;
        return true;
    }

    private boolean updateEffectsSuppressorW(ComponentName effectsSuppressor) {
        if (Objects.equals(mState.effectsSuppressor, effectsSuppressor)) return false;
        mState.effectsSuppressor = effectsSuppressor;
        mState.effectsSuppressorName = getApplicationName(mContext, mState.effectsSuppressor);
        Events.writeEvent(mContext, Events.EVENT_SUPPRESSOR_CHANGED, mState.effectsSuppressor,
                mState.effectsSuppressorName);
        return true;
    }

    private static String getApplicationName(Context context, ComponentName component) {
        if (component == null) return null;
        final PackageManager pm = context.getPackageManager();
        final String pkg = component.getPackageName();
        try {
            final ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
            final String rt = Objects.toString(ai.loadLabel(pm), "").trim();
            if (rt.length() > 0) {
                return rt;
            }
        } catch (NameNotFoundException e) {}
        return pkg;
    }

    private boolean updateZenModeW() {
        final int zen = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
        if (mState.zenMode == zen) return false;
        mState.zenMode = zen;
        Events.writeEvent(mContext, Events.EVENT_ZEN_MODE_CHANGED, zen);
        return true;
    }

    private boolean updateRingerModeExternalW(int rm) {
        if (rm == mState.ringerModeExternal) return false;
        mState.ringerModeExternal = rm;
        Events.writeEvent(mContext, Events.EVENT_EXTERNAL_RINGER_MODE_CHANGED, rm);
        return true;
    }

    private boolean updateRingerModeInternalW(int rm) {
        if (rm == mState.ringerModeInternal) return false;
        mState.ringerModeInternal = rm;
        Events.writeEvent(mContext, Events.EVENT_INTERNAL_RINGER_MODE_CHANGED, rm);
        return true;
    }

    private void onSetRingerModeW(int mode, boolean external) {
        if (external) {
            mAudio.setRingerMode(mode);
        } else {
            mAudio.setRingerModeInternal(mode);
        }
    }

    private void onSetStreamMuteW(int stream, boolean mute) {
        mAudio.adjustStreamVolume(stream, mute ? AudioManager.ADJUST_MUTE
                : AudioManager.ADJUST_UNMUTE, 0);
    }

    private void onSetStreamVolumeW(int stream, int level) {
        if (D.BUG) Log.d(TAG, "onSetStreamVolume " + stream + " level=" + level);
        if (stream >= DYNAMIC_STREAM_START_INDEX) {
            mMediaSessionsCallbacksW.setStreamVolume(stream, level);
            return;
        }
        mAudio.setStreamVolume(stream, level, 0);
    }

    private void onSetActiveStreamW(int stream) {
        boolean changed = updateActiveStreamW(stream);
        if (changed) {
            mCallbacks.onStateChanged(mState);
        }
    }

    private void onSetExitConditionW(Condition condition) {
        mNoMan.setZenMode(mState.zenMode, condition != null ? condition.id : null, TAG);
    }

    private void onSetZenModeW(int mode) {
        if (D.BUG) Log.d(TAG, "onSetZenModeW " + mode);
        mNoMan.setZenMode(mode, null, TAG);
    }

    private void onDismissRequestedW(int reason) {
        mCallbacks.onDismissRequested(reason);
    }

    public void showDndTile(boolean visible) {
        if (D.BUG) Log.d(TAG, "showDndTile");
        DndTile.setVisible(mContext, visible);
    }

    private final class VC extends IVolumeController.Stub {
        private final String TAG = VolumeDialogController.TAG + ".VC";

        @Override
        public void displaySafeVolumeWarning(int flags) throws RemoteException {
            if (D.BUG) Log.d(TAG, "displaySafeVolumeWarning "
                    + Util.audioManagerFlagsToString(flags));
            if (mDestroyed) return;
            mWorker.obtainMessage(W.SHOW_SAFETY_WARNING, flags, 0).sendToTarget();
        }

        @Override
        public void volumeChanged(int streamType, int flags) throws RemoteException {
            if (D.BUG) Log.d(TAG, "volumeChanged " + AudioSystem.streamToString(streamType)
                    + " " + Util.audioManagerFlagsToString(flags));
            if (mDestroyed) return;
            mWorker.obtainMessage(W.VOLUME_CHANGED, streamType, flags).sendToTarget();
        }

        @Override
        public void masterMuteChanged(int flags) throws RemoteException {
            if (D.BUG) Log.d(TAG, "masterMuteChanged");
        }

        @Override
        public void setLayoutDirection(int layoutDirection) throws RemoteException {
            if (D.BUG) Log.d(TAG, "setLayoutDirection");
            if (mDestroyed) return;
            mWorker.obtainMessage(W.LAYOUT_DIRECTION_CHANGED, layoutDirection, 0).sendToTarget();
        }

        @Override
        public void dismiss() throws RemoteException {
            if (D.BUG) Log.d(TAG, "dismiss requested");
            if (mDestroyed) return;
            mWorker.obtainMessage(W.DISMISS_REQUESTED, Events.DISMISS_REASON_VOLUME_CONTROLLER, 0)
                    .sendToTarget();
            mWorker.sendEmptyMessage(W.DISMISS_REQUESTED);
        }
    }

    private final class W extends Handler {
        private static final int VOLUME_CHANGED = 1;
        private static final int DISMISS_REQUESTED = 2;
        private static final int GET_STATE = 3;
        private static final int SET_RINGER_MODE = 4;
        private static final int SET_ZEN_MODE = 5;
        private static final int SET_EXIT_CONDITION = 6;
        private static final int SET_STREAM_MUTE = 7;
        private static final int LAYOUT_DIRECTION_CHANGED = 8;
        private static final int CONFIGURATION_CHANGED = 9;
        private static final int SET_STREAM_VOLUME = 10;
        private static final int SET_ACTIVE_STREAM = 11;
        private static final int NOTIFY_VISIBLE = 12;
        private static final int USER_ACTIVITY = 13;
        private static final int SHOW_SAFETY_WARNING = 14;

        W(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case VOLUME_CHANGED: onVolumeChangedW(msg.arg1, msg.arg2); break;
                case DISMISS_REQUESTED: onDismissRequestedW(msg.arg1); break;
                case GET_STATE: onGetStateW(); break;
                case SET_RINGER_MODE: onSetRingerModeW(msg.arg1, msg.arg2 != 0); break;
                case SET_ZEN_MODE: onSetZenModeW(msg.arg1); break;
                case SET_EXIT_CONDITION: onSetExitConditionW((Condition) msg.obj); break;
                case SET_STREAM_MUTE: onSetStreamMuteW(msg.arg1, msg.arg2 != 0); break;
                case LAYOUT_DIRECTION_CHANGED: mCallbacks.onLayoutDirectionChanged(msg.arg1); break;
                case CONFIGURATION_CHANGED: mCallbacks.onConfigurationChanged(); break;
                case SET_STREAM_VOLUME: onSetStreamVolumeW(msg.arg1, msg.arg2); break;
                case SET_ACTIVE_STREAM: onSetActiveStreamW(msg.arg1); break;
                case NOTIFY_VISIBLE: onNotifyVisibleW(msg.arg1 != 0); break;
                case USER_ACTIVITY: onUserActivityW(); break;
                case SHOW_SAFETY_WARNING: onShowSafetyWarningW(msg.arg1); break;
            }
        }
    }

    private final class C implements Callbacks {
        private final HashMap<Callbacks, Handler> mCallbackMap = new HashMap<>();

        public void add(Callbacks callback, Handler handler) {
            if (callback == null || handler == null) throw new IllegalArgumentException();
            mCallbackMap.put(callback, handler);
        }

        public void remove(Callbacks callback) {
            mCallbackMap.remove(callback);
        }

        @Override
        public void onShowRequested(final int reason) {
            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
                entry.getValue().post(new Runnable() {
                    @Override
                    public void run() {
                        entry.getKey().onShowRequested(reason);
                    }
                });
            }
        }

        @Override
        public void onDismissRequested(final int reason) {
            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
                entry.getValue().post(new Runnable() {
                    @Override
                    public void run() {
                        entry.getKey().onDismissRequested(reason);
                    }
                });
            }
        }

        @Override
        public void onStateChanged(final State state) {
            final long time = System.currentTimeMillis();
            final State copy = state.copy();
            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
                entry.getValue().post(new Runnable() {
                    @Override
                    public void run() {
                        entry.getKey().onStateChanged(copy);
                    }
                });
            }
            Events.writeState(time, copy);
        }

        @Override
        public void onLayoutDirectionChanged(final int layoutDirection) {
            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
                entry.getValue().post(new Runnable() {
                    @Override
                    public void run() {
                        entry.getKey().onLayoutDirectionChanged(layoutDirection);
                    }
                });
            }
        }

        @Override
        public void onConfigurationChanged() {
            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
                entry.getValue().post(new Runnable() {
                    @Override
                    public void run() {
                        entry.getKey().onConfigurationChanged();
                    }
                });
            }
        }

        @Override
        public void onShowVibrateHint() {
            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
                entry.getValue().post(new Runnable() {
                    @Override
                    public void run() {
                        entry.getKey().onShowVibrateHint();
                    }
                });
            }
        }

        @Override
        public void onShowSilentHint() {
            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
                entry.getValue().post(new Runnable() {
                    @Override
                    public void run() {
                        entry.getKey().onShowSilentHint();
                    }
                });
            }
        }

        @Override
        public void onScreenOff() {
            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
                entry.getValue().post(new Runnable() {
                    @Override
                    public void run() {
                        entry.getKey().onScreenOff();
                    }
                });
            }
        }

        @Override
        public void onShowSafetyWarning(final int flags) {
            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
                entry.getValue().post(new Runnable() {
                    @Override
                    public void run() {
                        entry.getKey().onShowSafetyWarning(flags);
                    }
                });
            }
        }
    }


    private final class SettingObserver extends ContentObserver {
        private final Uri SERVICE_URI = Settings.Secure.getUriFor(
                Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT);
        private final Uri ZEN_MODE_URI =
                Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
        private final Uri ZEN_MODE_CONFIG_URI =
                Settings.Global.getUriFor(Settings.Global.ZEN_MODE_CONFIG_ETAG);

        public SettingObserver(Handler handler) {
            super(handler);
        }

        public void init() {
            mContext.getContentResolver().registerContentObserver(SERVICE_URI, false, this);
            mContext.getContentResolver().registerContentObserver(ZEN_MODE_URI, false, this);
            mContext.getContentResolver().registerContentObserver(ZEN_MODE_CONFIG_URI, false, this);
            onChange(true, SERVICE_URI);
        }

        public void destroy() {
            mContext.getContentResolver().unregisterContentObserver(this);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            boolean changed = false;
            if (SERVICE_URI.equals(uri)) {
                final String setting = Settings.Secure.getString(mContext.getContentResolver(),
                        Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT);
                final boolean enabled = setting != null && mComponent != null
                        && mComponent.equals(ComponentName.unflattenFromString(setting));
                if (enabled == mEnabled) return;
                if (enabled) {
                    register();
                }
                mEnabled = enabled;
            }
            if (ZEN_MODE_URI.equals(uri)) {
                changed = updateZenModeW();
            }
            if (ZEN_MODE_CONFIG_URI.equals(uri)) {
                changed = updateZenModeConfigW();
            }
            if (changed) {
                mCallbacks.onStateChanged(mState);
            }
        }
    }

    private final class Receiver extends BroadcastReceiver {

        public void init() {
            final IntentFilter filter = new IntentFilter();
            filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
            filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
            filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
            filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
            filter.addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION);
            filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
            filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
            filter.addAction(Intent.ACTION_SCREEN_OFF);
            mContext.registerReceiver(this, filter, null, mWorker);
        }

        public void destroy() {
            mContext.unregisterReceiver(this);
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            boolean changed = false;
            if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
                final int level = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
                final int oldLevel = intent
                        .getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);
                if (D.BUG) Log.d(TAG, "onReceive VOLUME_CHANGED_ACTION stream=" + stream
                        + " level=" + level + " oldLevel=" + oldLevel);
                changed = updateStreamLevelW(stream, level);
            } else if (action.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION)) {
                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
                final int devices = intent
                        .getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, -1);
                final int oldDevices = intent
                        .getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, -1);
                if (D.BUG) Log.d(TAG, "onReceive STREAM_DEVICES_CHANGED_ACTION stream="
                        + stream + " devices=" + devices + " oldDevices=" + oldDevices);
                changed = checkRoutedToBluetoothW(stream);
            } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
                final int rm = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
                if (D.BUG) Log.d(TAG, "onReceive RINGER_MODE_CHANGED_ACTION rm="
                        + Util.ringerModeToString(rm));
                changed = updateRingerModeExternalW(rm);
            } else if (action.equals(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)) {
                final int rm = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
                if (D.BUG) Log.d(TAG, "onReceive INTERNAL_RINGER_MODE_CHANGED_ACTION rm="
                        + Util.ringerModeToString(rm));
                changed = updateRingerModeInternalW(rm);
            } else if (action.equals(AudioManager.STREAM_MUTE_CHANGED_ACTION)) {
                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
                final boolean muted = intent
                        .getBooleanExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, false);
                if (D.BUG) Log.d(TAG, "onReceive STREAM_MUTE_CHANGED_ACTION stream=" + stream
                        + " muted=" + muted);
                changed = updateStreamMuteW(stream, muted);
            } else if (action.equals(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED)) {
                if (D.BUG) Log.d(TAG, "onReceive ACTION_EFFECTS_SUPPRESSOR_CHANGED");
                changed = updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
            } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
                if (D.BUG) Log.d(TAG, "onReceive ACTION_CONFIGURATION_CHANGED");
                mCallbacks.onConfigurationChanged();
            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
                if (D.BUG) Log.d(TAG, "onReceive ACTION_SCREEN_OFF");
                mCallbacks.onScreenOff();
            }
            if (changed) {
                mCallbacks.onStateChanged(mState);
            }
        }
    }

    private final class MediaSessionsCallbacks implements MediaSessions.Callbacks {
        private final HashMap<Token, Integer> mRemoteStreams = new HashMap<>();

        private int mNextStream = DYNAMIC_STREAM_START_INDEX;

        @Override
        public void onRemoteUpdate(Token token, String name, PlaybackInfo pi) {
            if (!mRemoteStreams.containsKey(token)) {
                mRemoteStreams.put(token, mNextStream);
                if (D.BUG) Log.d(TAG, "onRemoteUpdate: " + name + " is stream " + mNextStream);
                mNextStream++;
            }
            final int stream = mRemoteStreams.get(token);
            boolean changed = mState.states.indexOfKey(stream) < 0;
            final StreamState ss = streamStateW(stream);
            ss.dynamic = true;
            ss.levelMin = 0;
            ss.levelMax = pi.getMaxVolume();
            if (ss.level != pi.getCurrentVolume()) {
                ss.level = pi.getCurrentVolume();
                changed = true;
            }
            if (!Objects.equals(ss.name, name)) {
                ss.name = name;
                changed = true;
            }
            if (changed) {
                if (D.BUG) Log.d(TAG, "onRemoteUpdate: " + name + ": " + ss.level
                        + " of " + ss.levelMax);
                mCallbacks.onStateChanged(mState);
            }
        }

        @Override
        public void onRemoteVolumeChanged(Token token, int flags) {
            final int stream = mRemoteStreams.get(token);
            final boolean showUI = (flags & AudioManager.FLAG_SHOW_UI) != 0;
            boolean changed = updateActiveStreamW(stream);
            if (showUI) {
                changed |= checkRoutedToBluetoothW(AudioManager.STREAM_MUSIC);
            }
            if (changed) {
                mCallbacks.onStateChanged(mState);
            }
            if (showUI) {
                mCallbacks.onShowRequested(Events.SHOW_REASON_REMOTE_VOLUME_CHANGED);
            }
        }

        @Override
        public void onRemoteRemoved(Token token) {
            final int stream = mRemoteStreams.get(token);
            mState.states.remove(stream);
            if (mState.activeStream == stream) {
                updateActiveStreamW(-1);
            }
            mCallbacks.onStateChanged(mState);
        }

        public void setStreamVolume(int stream, int level) {
            final Token t = findToken(stream);
            if (t == null) {
                Log.w(TAG, "setStreamVolume: No token found for stream: " + stream);
                return;
            }
            mMediaSessions.setVolume(t, level);
        }

        private Token findToken(int stream) {
            for (Map.Entry<Token, Integer> entry : mRemoteStreams.entrySet()) {
                if (entry.getValue().equals(stream)) {
                    return entry.getKey();
                }
            }
            return null;
        }
    }

    public static final class StreamState {
        public boolean dynamic;
        public int level;
        public int levelMin;
        public int levelMax;
        public boolean muted;
        public boolean muteSupported;
        public String name;
        public boolean routedToBluetooth;

        public StreamState copy() {
            final StreamState rt = new StreamState();
            rt.dynamic = dynamic;
            rt.level = level;
            rt.levelMin = levelMin;
            rt.levelMax = levelMax;
            rt.muted = muted;
            rt.muteSupported = muteSupported;
            rt.name = name;
            rt.routedToBluetooth = routedToBluetooth;
            return rt;
        }
    }

    public static final class State {
        public static int NO_ACTIVE_STREAM = -1;

        public final SparseArray<StreamState> states = new SparseArray<StreamState>();

        public int ringerModeInternal;
        public int ringerModeExternal;
        public int zenMode;
        public ComponentName effectsSuppressor;
        public String effectsSuppressorName;
        public ZenModeConfig zenModeConfig;
        public int activeStream = NO_ACTIVE_STREAM;

        public State copy() {
            final State rt = new State();
            for (int i = 0; i < states.size(); i++) {
                rt.states.put(states.keyAt(i), states.valueAt(i).copy());
            }
            rt.ringerModeExternal = ringerModeExternal;
            rt.ringerModeInternal = ringerModeInternal;
            rt.zenMode = zenMode;
            if (effectsSuppressor != null) rt.effectsSuppressor = effectsSuppressor.clone();
            rt.effectsSuppressorName = effectsSuppressorName;
            if (zenModeConfig != null) rt.zenModeConfig = zenModeConfig.copy();
            rt.activeStream = activeStream;
            return rt;
        }

        @Override
        public String toString() {
            return toString(0);
        }

        public String toString(int indent) {
            final StringBuilder sb = new StringBuilder("{");
            if (indent > 0) sep(sb, indent);
            for (int i = 0; i < states.size(); i++) {
                if (i > 0) {
                    sep(sb, indent);
                }
                final int stream = states.keyAt(i);
                final StreamState ss = states.valueAt(i);
                sb.append(AudioSystem.streamToString(stream)).append(":").append(ss.level)
                        .append('[').append(ss.levelMin).append("..").append(ss.levelMax)
                        .append(']');
                if (ss.muted) sb.append(" [MUTED]");
            }
            sep(sb, indent); sb.append("ringerModeExternal:").append(ringerModeExternal);
            sep(sb, indent); sb.append("ringerModeInternal:").append(ringerModeInternal);
            sep(sb, indent); sb.append("zenMode:").append(zenMode);
            sep(sb, indent); sb.append("effectsSuppressor:").append(effectsSuppressor);
            sep(sb, indent); sb.append("effectsSuppressorName:").append(effectsSuppressorName);
            sep(sb, indent); sb.append("zenModeConfig:").append(zenModeConfig);
            sep(sb, indent); sb.append("activeStream:").append(activeStream);
            if (indent > 0) sep(sb, indent);
            return sb.append('}').toString();
        }

        private static void sep(StringBuilder sb, int indent) {
            if (indent > 0) {
                sb.append('\n');
                for (int i = 0; i < indent; i++) {
                    sb.append(' ');
                }
            } else {
                sb.append(',');
            }
        }

        public Condition getManualExitCondition() {
            return zenModeConfig != null && zenModeConfig.manualRule != null
                    ? zenModeConfig.manualRule.condition : null;
        }
    }

    public interface Callbacks {
        void onShowRequested(int reason);
        void onDismissRequested(int reason);
        void onStateChanged(State state);
        void onLayoutDirectionChanged(int layoutDirection);
        void onConfigurationChanged();
        void onShowVibrateHint();
        void onShowSilentHint();
        void onScreenOff();
        void onShowSafetyWarning(int flags);
    }
}
