/*
 * Copyright (C) 2016 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.car;

import android.content.Context;
import android.media.AudioManager;
import android.media.IAudioService;
import android.media.IVolumeController;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.telecom.TelecomManager;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.view.KeyEvent;

import com.android.car.CarVolumeService.CarVolumeController;
import com.android.car.hal.AudioHalService;
import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;
import java.util.Map;

/**
 * A factory class to create {@link com.android.car.CarVolumeService.CarVolumeController} based
 * on car properties.
 */
public class CarVolumeControllerFactory {
    // STOPSHIP if true.
    private static final boolean DBG = false;

    public static CarVolumeController createCarVolumeController(Context context,
            CarAudioService audioService, AudioHalService audioHal, CarInputService inputService) {
        final boolean volumeSupported = audioHal.isAudioVolumeSupported();

        // Case 1: Car Audio Module does not support volume controls
        if (!volumeSupported) {
            return new SimpleCarVolumeController(context);
        }
        return new CarExternalVolumeController(context, audioService, audioHal, inputService);
    }

    public static boolean interceptVolKeyBeforeDispatching(Context context) {
        Log.d(CarLog.TAG_AUDIO, "interceptVolKeyBeforeDispatching");

        TelecomManager telecomManager = (TelecomManager)
                context.getSystemService(Context.TELECOM_SERVICE);
        if (telecomManager != null && telecomManager.isRinging()) {
            // If an incoming call is ringing, either VOLUME key means
            // "silence ringer".  This is consistent with current android phone's behavior
            Log.i(CarLog.TAG_AUDIO, "interceptKeyBeforeQueueing:"
                    + " VOLUME key-down while ringing: Silence ringer!");

            // Silence the ringer.  (It's safe to call this
            // even if the ringer has already been silenced.)
            telecomManager.silenceRinger();
            return true;
        }
        return false;
    }

    public static boolean isVolumeKey(KeyEvent event) {
        return event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN
                || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP;
    }

    /**
     * To control volumes through {@link android.media.AudioManager} when car audio module does not
     * support volume controls.
     */
    public static final class SimpleCarVolumeController extends CarVolumeController {
        private final AudioManager mAudioManager;
        private final Context mContext;

        public SimpleCarVolumeController(Context context) {
            mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
            mContext = context;
        }

        @Override
        void init() {
        }

        @Override
        public void setStreamVolume(int stream, int index, int flags) {
            if (DBG) {
                Log.d(CarLog.TAG_AUDIO, "setStreamVolume " + stream + " " + index + " " + flags);
            }
            mAudioManager.setStreamVolume(stream, index, flags);
        }

        @Override
        public int getStreamVolume(int stream) {
            return mAudioManager.getStreamVolume(stream);
        }

        @Override
        public void setVolumeController(IVolumeController controller) {
            mAudioManager.setVolumeController(controller);
        }

        @Override
        public int getStreamMaxVolume(int stream) {
            return mAudioManager.getStreamMaxVolume(stream);
        }

        @Override
        public int getStreamMinVolume(int stream) {
            return mAudioManager.getStreamMinVolume(stream);
        }

        @Override
        public boolean onKeyEvent(KeyEvent event) {
            if (!isVolumeKey(event)) {
                return false;
            }
            handleVolumeKeyDefault(event);
            return true;
        }

        @Override
        public void dump(PrintWriter writer) {
            writer.println("Volume controller:" + SimpleCarVolumeController.class.getSimpleName());
            // nothing else to dump
        }

        private void handleVolumeKeyDefault(KeyEvent event) {
            if (event.getAction() != KeyEvent.ACTION_DOWN
                    || interceptVolKeyBeforeDispatching(mContext)) {
                return;
            }

            boolean volUp = event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP;
            int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
                    | AudioManager.FLAG_FROM_KEY;
            IAudioService audioService = getAudioService();
            String pkgName = mContext.getOpPackageName();
            try {
                if (audioService != null) {
                    audioService.adjustSuggestedStreamVolume(
                            volUp ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER,
                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, CarLog.TAG_INPUT);
                }
            } catch (RemoteException e) {
                Log.e(CarLog.TAG_INPUT, "Error calling android audio service.", e);
            }
        }

        private static IAudioService getAudioService() {
            IAudioService audioService = IAudioService.Stub.asInterface(
                    ServiceManager.checkService(Context.AUDIO_SERVICE));
            if (audioService == null) {
                Log.w(CarLog.TAG_INPUT, "Unable to find IAudioService interface.");
            }
            return audioService;
        }
    }

    /**
     * The car volume controller to use when the car audio modules supports volume controls.
     *
     * Depending on whether the car support audio context and has persistent memory, we need to
     * handle per context volume change properly.
     *
     * Regardless whether car supports audio context or not, we need to keep per audio context
     * volume internally. If we only support single channel, then we only send the volume change
     * event when that stream is in focus; Otherwise, we need to adjust the stream volume either on
     * software mixer level or send it the car audio module if the car support audio context
     * and multi channel. TODO: Add support for multi channel.
     *
     * Per context volume should be persisted, so the volumes can stay the same across boots.
     * Depending on the hardware property, this can be persisted on car side (or/and android side).
     * TODO: we need to define one single source of truth if the car has memory.
     */
    public static class CarExternalVolumeController extends CarVolumeController
            implements CarInputService.KeyEventListener, AudioHalService.AudioHalVolumeListener,
            CarAudioService.AudioContextChangeListener {
        private static final String TAG = CarLog.TAG_AUDIO + ".VolCtrl";
        private static final int MSG_UPDATE_VOLUME = 0;
        private static final int MSG_UPDATE_HAL = 1;
        private static final int MSG_SUPPRESS_UI_FOR_VOLUME = 2;
        private static final int MSG_VOLUME_UI_RESTORE = 3;

        // within 5 seconds after a UI invisible volume change (e.g., due to audio context change,
        // or explicitly flag), we will not show UI in respond to that particular volume changes
        // events from HAL (context and volume index must match).
        private static final int HIDE_VOLUME_UI_MILLISECONDS = 5 * 1000; // 5 seconds

        private final Context mContext;
        private final AudioRoutingPolicy mPolicy;
        private final AudioHalService mHal;
        private final CarInputService mInputService;
        private final CarAudioService mAudioService;

        private int mSupportedAudioContext;

        private boolean mHasExternalMemory;
        private boolean mMasterVolumeOnly;

        @GuardedBy("this")
        private int mCurrentContext = CarVolumeService.DEFAULT_CAR_AUDIO_CONTEXT;
        // current logical volume, the key is car audio context
        @GuardedBy("this")
        private final SparseArray<Integer> mCurrentCarContextVolume =
                new SparseArray<>(VolumeUtils.CAR_AUDIO_CONTEXT.length);
        // stream volume limit, the key is car audio context type
        @GuardedBy("this")
        private final SparseArray<Integer> mCarContextVolumeMax =
                new SparseArray<>(VolumeUtils.CAR_AUDIO_CONTEXT.length);
        // stream volume limit, the key is car audio context type
        @GuardedBy("this")
        private final SparseArray<Integer> mCarContextVolumeMin =
                new SparseArray<>(VolumeUtils.CAR_AUDIO_CONTEXT.length);
        @GuardedBy("this")
        private final RemoteCallbackList<IVolumeController> mVolumeControllers =
                new RemoteCallbackList<>();
        @GuardedBy("this")
        private int[] mSuppressUiForVolume = new int[2];
        @GuardedBy("this")
        private boolean mShouldSuppress = false;

        private final Handler mHandler = new VolumeHandler();

        /**
         * Convert an car context to the car stream.
         *
         * @return If car supports audio context, then it returns the car audio context. Otherwise,
         *      it returns the physical stream that maps to this logical stream.
         */
        private int carContextToCarStream(int carContext) {
            if (mSupportedAudioContext == 0) {
                int physicalStream = mPolicy.getPhysicalStreamForLogicalStream(
                        AudioHalService.carContextToCarUsage(carContext));
                return physicalStream;
            } else {
                return carContext;
            }
        }

        private void writeVolumeToSettings(int carContext, int volume) {
            String key = VolumeUtils.CAR_AUDIO_CONTEXT_SETTINGS.get(carContext);
            if (key != null) {
                Settings.Global.putInt(mContext.getContentResolver(), key, volume);
            }
        }

        /**
         * All updates to external components should be posted to this handler to avoid holding
         * the internal lock while sending updates.
         */
        private final class VolumeHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                int stream;
                int volume;
                switch (msg.what) {
                    case MSG_UPDATE_VOLUME:
                        // arg1 is car context
                        stream = msg.arg1;
                        volume = (int) msg.obj;
                        int flag = msg.arg2;
                        synchronized (CarExternalVolumeController.this) {
                            // the suppressed stream is sending us update....
                            if (mShouldSuppress && stream == mSuppressUiForVolume[0]) {
                                // the volume matches, we want to suppress it
                                if (volume == mSuppressUiForVolume[1]) {
                                    if (DBG) {
                                        Log.d(TAG, "Suppress Volume UI for stream "
                                                + stream + " volume: " + volume);
                                    }
                                    flag &= ~AudioManager.FLAG_SHOW_UI;
                                }
                                // No matter if the volume matches or not, we will stop suppressing
                                // UI for this stream now. After an audio context switch, user may
                                // quickly turn the nob, -1 and +1, it ends the same volume,
                                // but we should show the UI for both.
                                removeMessages(MSG_VOLUME_UI_RESTORE);
                                mShouldSuppress = false;
                            }
                        }
                        final int size = mVolumeControllers.beginBroadcast();
                        try {
                            for (int i = 0; i < size; i++) {
                                try {
                                    mVolumeControllers.getBroadcastItem(i).volumeChanged(
                                            VolumeUtils.carContextToAndroidStream(stream), flag);
                                } catch (RemoteException ignored) {
                                }
                            }
                        } finally {
                            mVolumeControllers.finishBroadcast();
                        }
                        break;
                    case MSG_UPDATE_HAL:
                        stream = msg.arg1;
                        volume = msg.arg2;
                        synchronized (CarExternalVolumeController.this) {
                            if (mMasterVolumeOnly) {
                                stream = 0;
                            }
                        }
                        mHal.setStreamVolume(stream, volume);
                        break;
                    case MSG_SUPPRESS_UI_FOR_VOLUME:
                        if (DBG) {
                            Log.d(TAG, "Suppress stream volume " + msg.arg1 + " " + msg.arg2);
                        }
                        synchronized (CarExternalVolumeController.this) {
                            mShouldSuppress = true;
                            mSuppressUiForVolume[0] = msg.arg1;
                            mSuppressUiForVolume[1] = msg.arg2;
                        }
                        removeMessages(MSG_VOLUME_UI_RESTORE);
                        sendMessageDelayed(obtainMessage(MSG_VOLUME_UI_RESTORE),
                                HIDE_VOLUME_UI_MILLISECONDS);
                        break;
                    case MSG_VOLUME_UI_RESTORE:
                        if (DBG) {
                            Log.d(TAG, "Volume Ui suppress expired");
                        }
                        synchronized (CarExternalVolumeController.this) {
                            mShouldSuppress = false;
                        }
                        break;
                    default:
                        break;
                }
            }
        }

        public CarExternalVolumeController(Context context, CarAudioService audioService,
                                           AudioHalService hal, CarInputService inputService) {
            mContext = context;
            mAudioService = audioService;
            mPolicy = audioService.getAudioRoutingPolicy();
            mHal = hal;
            mInputService = inputService;
        }

        @Override
        void init() {
            mSupportedAudioContext = mHal.getSupportedAudioVolumeContexts();
            mHasExternalMemory = mHal.isExternalAudioVolumePersistent();
            mMasterVolumeOnly = mHal.isAudioVolumeMasterOnly();
            synchronized (this) {
                initVolumeLimitLocked();
                initCurrentVolumeLocked();
            }
            mInputService.setVolumeKeyListener(this);
            mHal.setVolumeListener(this);
            mAudioService.setAudioContextChangeListener(Looper.getMainLooper(), this);
        }

        private void initVolumeLimitLocked() {
            for (int i : VolumeUtils.CAR_AUDIO_CONTEXT) {
                int carStream = carContextToCarStream(i);
                Pair<Integer, Integer> volumeMinMax = mHal.getStreamVolumeLimit(carStream);
                int max;
                int min;
                if (volumeMinMax == null) {
                    max = 0;
                    min = 0;
                } else {
                    max = volumeMinMax.second >= 0 ? volumeMinMax.second : 0;
                    min = volumeMinMax.first >=0 ? volumeMinMax.first : 0;
                }
                // get default stream volume limit first.
                mCarContextVolumeMax.put(i, max);
                mCarContextVolumeMin.put(i, min);
            }
        }

        private void initCurrentVolumeLocked() {
            if (mHasExternalMemory) {
                // TODO: read per context volume from audio hal
            } else {
                // when vhal does not work, get call can take long. For that case,
                // for the same physical streams, cache initial get results
                Map<Integer, Integer> volumesPerCarStream =
                        new ArrayMap<>(VolumeUtils.CAR_AUDIO_CONTEXT.length);
                for (int i : VolumeUtils.CAR_AUDIO_CONTEXT) {
                    String key = VolumeUtils.CAR_AUDIO_CONTEXT_SETTINGS.get(i);
                    if (key != null) {
                        int vol = Settings.Global.getInt(mContext.getContentResolver(), key, -1);
                        if (vol >= 0) {
                            // Read valid volume for this car context from settings and continue;
                            mCurrentCarContextVolume.put(i, vol);
                            if (DBG) {
                                Log.d(TAG, "init volume from settings, car audio context: "
                                        + i + " volume: " + vol);
                            }
                            continue;
                        }
                    }

                    // There is no settings for this car context. Use the current physical car
                    // stream volume as initial value instead, and put the volume into settings.
                    int carStream = carContextToCarStream(i);
                    Integer volume = volumesPerCarStream.get(carStream);
                    if (volume == null) {
                        volume = Integer.valueOf(mHal.getStreamVolume(mMasterVolumeOnly ? 0 :
                            carStream));
                        volumesPerCarStream.put(carStream, volume);
                    }
                    mCurrentCarContextVolume.put(i, volume);
                    writeVolumeToSettings(i, volume);
                    if (DBG) {
                        Log.d(TAG, "init volume from physical stream," +
                                " car audio context: " + i + " volume: " + volume);
                    }
                }
            }
        }

        @Override
        public void setStreamVolume(int stream, int index, int flags) {
            synchronized (this) {
                int carContext;
                // Currently car context and android logical stream are not
                // one-to-one mapping. In this API, Android side asks us to change a logical stream
                // volume. If the current car audio context maps to this logical stream, then we
                // change the volume for the current car audio context. Otherwise, we change the
                // volume for the primary mapped car audio context.
                if (VolumeUtils.carContextToAndroidStream(mCurrentContext) == stream) {
                    carContext = mCurrentContext;
                } else {
                    carContext = VolumeUtils.androidStreamToCarContext(stream);
                }
                if (DBG) {
                    Log.d(TAG, "Receive setStreamVolume logical stream: " + stream + " index: "
                            + index + " flags: " + flags + " maps to car context: " + carContext);
                }
                setStreamVolumeInternalLocked(carContext, index, flags);
            }
        }

        private void setStreamVolumeInternalLocked(int carContext, int index, int flags) {
            if (mCarContextVolumeMax.get(carContext) == null) {
                Log.e(TAG, "Stream type not supported " + carContext);
                return;
            }
            int limit = mCarContextVolumeMax.get(carContext);
            if (index > limit) {
                Log.w(TAG, "Volume exceeds volume limit. context: " + carContext
                        + " index: " + index + " limit: " + limit);
                index = limit;
            }

            if (index < 0) {
                index = 0;
            }

            if (mCurrentCarContextVolume.get(carContext) == index) {
                return;
            }

            int carStream = carContextToCarStream(carContext);
            if (DBG) {
                Log.d(TAG, "Change car stream volume, stream: " + carStream + " volume:" + index);
            }
            // For single channel, only adjust the volume when the audio context is the current one.
            if (mCurrentContext == carContext) {
                if (DBG) {
                    Log.d(TAG, "Sending volume change to HAL");
                }
                mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_HAL, carStream, index));
                if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
                    if (mShouldSuppress && mSuppressUiForVolume[0] == carContext) {
                        // In this case, the caller explicitly says "Show_UI" for the same context.
                        // We will respect the flag, and let the UI show.
                        mShouldSuppress = false;
                        mHandler.removeMessages(MSG_VOLUME_UI_RESTORE);
                    }
                } else {
                    mHandler.sendMessage(mHandler.obtainMessage(MSG_SUPPRESS_UI_FOR_VOLUME,
                            carContext, index));
                }
            }
            // Record the current volume internally.
            mCurrentCarContextVolume.put(carContext, index);
            writeVolumeToSettings(mCurrentContext, index);
        }

        @Override
        public int getStreamVolume(int stream) {
            synchronized (this) {
                if (VolumeUtils.carContextToAndroidStream(mCurrentContext) == stream) {
                    return mCurrentCarContextVolume.get(mCurrentContext);
                }
                return mCurrentCarContextVolume.get(VolumeUtils.androidStreamToCarContext(stream));
            }
        }

        @Override
        public void setVolumeController(IVolumeController controller) {
            synchronized (this) {
                mVolumeControllers.register(controller);
            }
        }

        @Override
        public void onVolumeChange(int carStream, int volume, int volumeState) {
            synchronized (this) {
                int flag = getVolumeUpdateFlag(true);
                if (DBG) {
                    Log.d(TAG, "onVolumeChange carStream:" + carStream + " volume: " + volume
                            + " volumeState: " + volumeState
                            + " suppressUI? " + mShouldSuppress
                            + " stream: " + mSuppressUiForVolume[0]
                            + " volume: " + mSuppressUiForVolume[1]);
                }
                int currentCarStream = carContextToCarStream(mCurrentContext);
                if (mMasterVolumeOnly) { //for master volume only H/W, always assume current stream
                    carStream = currentCarStream;
                }
                if (currentCarStream == carStream) {
                    mCurrentCarContextVolume.put(mCurrentContext, volume);
                    writeVolumeToSettings(mCurrentContext, volume);
                    mHandler.sendMessage(
                            mHandler.obtainMessage(MSG_UPDATE_VOLUME, mCurrentContext, flag,
                                    new Integer(volume)));
                } else {
                    // Hal is telling us a car stream volume has changed, but it is not the current
                    // stream.
                    Log.w(TAG, "Car stream" + carStream
                            + " volume changed, but it is not current stream, ignored.");
                }
            }
        }

        private int getVolumeUpdateFlag(boolean showUi) {
            return showUi? AudioManager.FLAG_SHOW_UI : 0;
        }

        @Override
        public void onVolumeLimitChange(int streamNumber, int volume) {
            // TODO: How should this update be sent to SystemUI? maybe send a volume update without
            // showing UI.
            synchronized (this) {
                initVolumeLimitLocked();
            }
        }

        @Override
        public int getStreamMaxVolume(int stream) {
            synchronized (this) {
                if (VolumeUtils.carContextToAndroidStream(mCurrentContext) == stream) {
                    return mCarContextVolumeMax.get(mCurrentContext);
                } else {
                    return mCarContextVolumeMax.get(VolumeUtils.androidStreamToCarContext(stream));
                }
            }
        }

        @Override
        public int getStreamMinVolume(int stream) {
            synchronized (this) {
                if (VolumeUtils.carContextToAndroidStream(mCurrentContext) == stream) {
                    return mCarContextVolumeMin.get(mCurrentContext);
                } else {
                    return mCarContextVolumeMin.get(VolumeUtils.androidStreamToCarContext(stream));
                }
            }
        }

        @Override
        public boolean onKeyEvent(KeyEvent event) {
            if (!isVolumeKey(event)) {
                return false;
            }
            final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
            if (DBG) {
                Log.d(TAG, "Receive volume keyevent " + event.toString());
            }
            // TODO: properly handle long press on volume key
            if (!down || interceptVolKeyBeforeDispatching(mContext)) {
                return true;
            }

            synchronized (this) {
                int currentVolume = mCurrentCarContextVolume.get(mCurrentContext);
                switch (event.getKeyCode()) {
                    case KeyEvent.KEYCODE_VOLUME_UP:
                        setStreamVolumeInternalLocked(mCurrentContext, currentVolume + 1,
                                getVolumeUpdateFlag(true));
                        break;
                    case KeyEvent.KEYCODE_VOLUME_DOWN:
                        setStreamVolumeInternalLocked(mCurrentContext, currentVolume - 1,
                                getVolumeUpdateFlag(true));
                        break;
                }
            }
            return true;
        }

        @Override
        public void onContextChange(int primaryFocusContext, int primaryFocusPhysicalStream) {
            synchronized (this) {
                if(DBG) {
                    Log.d(TAG, "Audio context changed from " + mCurrentContext + " to: "
                            + primaryFocusContext + " physical: " + primaryFocusPhysicalStream);
                }
                // if primaryFocusContext is 0, it means nothing is playing or holding focus,
                // we will keep the last focus context and if the user changes the volume
                // it will go to the last audio context.
                if (primaryFocusContext == mCurrentContext || primaryFocusContext == 0) {
                    return;
                }
                int oldContext = mCurrentContext;
                mCurrentContext = primaryFocusContext;
                // if car supports audio context and has external memory, then we don't need to do
                // anything.
                if(mSupportedAudioContext != 0 && mHasExternalMemory) {
                    if (DBG) {
                        Log.d(TAG, "Car support audio context and has external memory," +
                                " no volume change needed from car service");
                    }
                    return;
                }

                // Otherwise, we need to tell Hal what the correct volume is for the new context.
                int currentVolume = mCurrentCarContextVolume.get(primaryFocusContext);

                int carStreamNumber = (mSupportedAudioContext == 0) ? primaryFocusPhysicalStream :
                        primaryFocusContext;
                if (DBG) {
                    Log.d(TAG, "Change volume from: "
                            + mCurrentCarContextVolume.get(oldContext)
                            + " to: "+ currentVolume);
                }
                mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_HAL, carStreamNumber,
                        currentVolume));
                mHandler.sendMessage(mHandler.obtainMessage(MSG_SUPPRESS_UI_FOR_VOLUME,
                        mCurrentContext, currentVolume));
            }
        }

        @Override
        public void dump(PrintWriter writer) {
            writer.println("Volume controller:" +
                    CarExternalVolumeController.class.getSimpleName());
            synchronized (this) {
                writer.println("mSupportedAudioContext:0x" +
                        Integer.toHexString(mSupportedAudioContext) +
                        ",mHasExternalMemory:" + mHasExternalMemory +
                        ",mMasterVolumeOnly:" + mMasterVolumeOnly);
                writer.println("mCurrentContext:0x" + Integer.toHexString(mCurrentContext));
                writer.println("mCurrentCarContextVolume:");
                dumpVolumes(writer, mCurrentCarContextVolume);
                writer.println("mCarContextVolumeMax:");
                dumpVolumes(writer, mCarContextVolumeMax);
                writer.println("mCarContextVolumeMin:");
                dumpVolumes(writer, mCarContextVolumeMin);
                writer.println("Number of volume controllers:" +
                        mVolumeControllers.getRegisteredCallbackCount());
            }
        }

        private void dumpVolumes(PrintWriter writer, SparseArray<Integer> array) {
            for (int i = 0; i < array.size(); i++) {
                writer.println("0x" + Integer.toHexString(array.keyAt(i)) + ":" + array.valueAt(i));
            }
        }
    }
}
