/*
 * Copyright (C) 2014 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.server.telecom;

import android.app.ActivityManagerNative;
import android.content.Context;
import android.content.pm.UserInfo;
import android.media.AudioManager;
import android.media.IAudioService;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.telecom.CallAudioState;

import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;

import java.util.Objects;

/**
 * This class manages audio modes, streams and other properties.
 */
final class CallAudioManager extends CallsManagerListenerBase
        implements WiredHeadsetManager.Listener, DockManager.Listener {
    private static final int STREAM_NONE = -1;

    private static final String STREAM_DESCRIPTION_NONE = "STEAM_NONE";
    private static final String STREAM_DESCRIPTION_ALARM = "STEAM_ALARM";
    private static final String STREAM_DESCRIPTION_BLUETOOTH_SCO = "STREAM_BLUETOOTH_SCO";
    private static final String STREAM_DESCRIPTION_DTMF = "STREAM_DTMF";
    private static final String STREAM_DESCRIPTION_MUSIC = "STREAM_MUSIC";
    private static final String STREAM_DESCRIPTION_NOTIFICATION = "STREAM_NOTIFICATION";
    private static final String STREAM_DESCRIPTION_RING = "STREAM_RING";
    private static final String STREAM_DESCRIPTION_SYSTEM = "STREAM_SYSTEM";
    private static final String STREAM_DESCRIPTION_VOICE_CALL = "STREAM_VOICE_CALL";

    private static final String MODE_DESCRIPTION_INVALID = "MODE_INVALID";
    private static final String MODE_DESCRIPTION_CURRENT = "MODE_CURRENT";
    private static final String MODE_DESCRIPTION_NORMAL = "MODE_NORMAL";
    private static final String MODE_DESCRIPTION_RINGTONE = "MODE_RINGTONE";
    private static final String MODE_DESCRIPTION_IN_CALL = "MODE_IN_CALL";
    private static final String MODE_DESCRIPTION_IN_COMMUNICATION = "MODE_IN_COMMUNICATION";

    private static final int MSG_AUDIO_MANAGER_INITIALIZE = 0;
    private static final int MSG_AUDIO_MANAGER_TURN_ON_SPEAKER = 1;
    private static final int MSG_AUDIO_MANAGER_ABANDON_AUDIO_FOCUS_FOR_CALL = 2;
    private static final int MSG_AUDIO_MANAGER_SET_MICROPHONE_MUTE = 3;
    private static final int MSG_AUDIO_MANAGER_REQUEST_AUDIO_FOCUS_FOR_CALL = 4;
    private static final int MSG_AUDIO_MANAGER_SET_MODE = 5;

    private final Handler mAudioManagerHandler = new Handler(Looper.getMainLooper()) {

        private AudioManager mAudioManager;

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_AUDIO_MANAGER_INITIALIZE: {
                    mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
                    break;
                }
                case MSG_AUDIO_MANAGER_TURN_ON_SPEAKER: {
                    boolean on = (msg.arg1 != 0);
                    // Wired headset and earpiece work the same way
                    if (mAudioManager.isSpeakerphoneOn() != on) {
                        Log.i(this, "turning speaker phone %s", on);
                        mAudioManager.setSpeakerphoneOn(on);
                    }
                    break;
                }
                case MSG_AUDIO_MANAGER_ABANDON_AUDIO_FOCUS_FOR_CALL: {
                    mAudioManager.abandonAudioFocusForCall();
                    break;
                }
                case MSG_AUDIO_MANAGER_SET_MICROPHONE_MUTE: {
                    boolean mute = (msg.arg1 != 0);
                    if (mute != mAudioManager.isMicrophoneMute()) {
                        IAudioService audio = getAudioService();
                        Log.i(this, "changing microphone mute state to: %b [serviceIsNull=%b]",
                                mute, audio == null);
                        if (audio != null) {
                            try {
                                // We use the audio service directly here so that we can specify
                                // the current user. Telecom runs in the system_server process which
                                // may run as a separate user from the foreground user. If we
                                // used AudioManager directly, we would change mute for the system's
                                // user and not the current foreground, which we want to avoid.
                                audio.setMicrophoneMute(
                                        mute, mContext.getOpPackageName(), getCurrentUserId());

                            } catch (RemoteException e) {
                                Log.e(this, e, "Remote exception while toggling mute.");
                            }
                            // TODO: Check microphone state after attempting to set to ensure that
                            // our state corroborates AudioManager's state.
                        }
                    }

                    break;
                }
                case MSG_AUDIO_MANAGER_REQUEST_AUDIO_FOCUS_FOR_CALL: {
                    int stream = msg.arg1;
                    mAudioManager.requestAudioFocusForCall(
                            stream,
                            AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
                    break;
                }
                case MSG_AUDIO_MANAGER_SET_MODE: {
                    int newMode = msg.arg1;
                    int oldMode = mAudioManager.getMode();
                    Log.v(this, "Request to change audio mode from %s to %s", modeToString(oldMode),
                            modeToString(newMode));

                    if (oldMode != newMode) {
                        if (oldMode == AudioManager.MODE_IN_CALL &&
                                newMode == AudioManager.MODE_RINGTONE) {
                            Log.i(this, "Transition from IN_CALL -> RINGTONE."
                                    + "  Resetting to NORMAL first.");
                            mAudioManager.setMode(AudioManager.MODE_NORMAL);
                        }
                        mAudioManager.setMode(newMode);
                        synchronized (mLock) {
                            mMostRecentlyUsedMode = newMode;
                        }
                    }
                    break;
                }
                default:
                    break;
            }
        }
    };

    private final Context mContext;
    private final TelecomSystem.SyncRoot mLock;
    private final StatusBarNotifier mStatusBarNotifier;
    private final BluetoothManager mBluetoothManager;
    private final WiredHeadsetManager mWiredHeadsetManager;
    private final DockManager mDockManager;
    private final CallsManager mCallsManager;

    private CallAudioState mCallAudioState;
    private int mAudioFocusStreamType;
    private boolean mIsRinging;
    private boolean mIsTonePlaying;
    private boolean mWasSpeakerOn;
    private int mMostRecentlyUsedMode = AudioManager.MODE_IN_CALL;
    private Call mCallToSpeedUpMTAudio = null;

    CallAudioManager(
            Context context,
            TelecomSystem.SyncRoot lock,
            StatusBarNotifier statusBarNotifier,
            WiredHeadsetManager wiredHeadsetManager,
            DockManager dockManager,
            CallsManager callsManager) {
        mContext = context;
        mLock = lock;
        mAudioManagerHandler.obtainMessage(MSG_AUDIO_MANAGER_INITIALIZE, 0, 0).sendToTarget();
        mStatusBarNotifier = statusBarNotifier;
        mBluetoothManager = new BluetoothManager(context, this);
        mWiredHeadsetManager = wiredHeadsetManager;
        mCallsManager = callsManager;

        mWiredHeadsetManager.addListener(this);
        mDockManager = dockManager;
        mDockManager.addListener(this);

        saveAudioState(getInitialAudioState(null));
        mAudioFocusStreamType = STREAM_NONE;
    }

    CallAudioState getCallAudioState() {
        return mCallAudioState;
    }

    @Override
    public void onCallAdded(Call call) {
        Log.v(this, "onCallAdded");
        onCallUpdated(call);

        if (hasFocus() && getForegroundCall() == call) {
            if (!call.isIncoming()) {
                // Unmute new outgoing call.
                setSystemAudioState(false, mCallAudioState.getRoute(),
                        mCallAudioState.getSupportedRouteMask());
            }
        }
    }

    @Override
    public void onCallRemoved(Call call) {
        Log.v(this, "onCallRemoved");
        // If we didn't already have focus, there's nothing to do.
        if (hasFocus()) {
            if (mCallsManager.getCalls().isEmpty()) {
                Log.v(this, "all calls removed, resetting system audio to default state");
                setInitialAudioState(null, false /* force */);
                mWasSpeakerOn = false;
            }
            updateAudioStreamAndMode(call);
        }
    }

    @Override
    public void onCallStateChanged(Call call, int oldState, int newState) {
        Log.v(this, "onCallStateChanged : oldState = %d, newState = %d", oldState, newState);
        onCallUpdated(call);
    }

    @Override
    public void onIncomingCallAnswered(Call call) {
        Log.v(this, "onIncomingCallAnswered");
        int route = mCallAudioState.getRoute();

        // We do two things:
        // (1) If this is the first call, then we can to turn on bluetooth if available.
        // (2) Unmute the audio for the new incoming call.
        boolean isOnlyCall = mCallsManager.getCalls().size() == 1;
        if (isOnlyCall && mBluetoothManager.isBluetoothAvailable()) {
            mBluetoothManager.connectBluetoothAudio();
            route = CallAudioState.ROUTE_BLUETOOTH;
        }

        setSystemAudioState(false /* isMute */, route, mCallAudioState.getSupportedRouteMask());

        if (call.can(android.telecom.Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO)) {
            Log.v(this, "Speed up audio setup for IMS MT call.");
            mCallToSpeedUpMTAudio = call;
            updateAudioStreamAndMode(call);
        }
    }

    @Override
    public void onForegroundCallChanged(Call oldForegroundCall, Call newForegroundCall) {
        onCallUpdated(newForegroundCall);
        // Ensure that the foreground call knows about the latest audio state.
        updateAudioForForegroundCall();
    }

    @Override
    public void onIsVoipAudioModeChanged(Call call) {
        updateAudioStreamAndMode(call);
    }

    /**
      * Updates the audio route when the headset plugged in state changes. For example, if audio is
      * being routed over speakerphone and a headset is plugged in then switch to wired headset.
      */
    @Override
    public void onWiredHeadsetPluggedInChanged(boolean oldIsPluggedIn, boolean newIsPluggedIn) {
        // This can happen even when there are no calls and we don't have focus.
        if (!hasFocus()) {
            return;
        }

        boolean isCurrentlyWiredHeadset = mCallAudioState.getRoute()
                == CallAudioState.ROUTE_WIRED_HEADSET;

        int newRoute = mCallAudioState.getRoute();  // start out with existing route
        if (newIsPluggedIn) {
            newRoute = CallAudioState.ROUTE_WIRED_HEADSET;
        } else if (isCurrentlyWiredHeadset) {
            Call call = getForegroundCall();
            boolean hasLiveCall = call != null && call.isAlive();

            if (hasLiveCall) {
                // In order of preference when a wireless headset is unplugged.
                if (mWasSpeakerOn) {
                    newRoute = CallAudioState.ROUTE_SPEAKER;
                } else {
                    newRoute = CallAudioState.ROUTE_EARPIECE;
                }

                // We don't automatically connect to bluetooth when user unplugs their wired headset
                // and they were previously using the wired. Wired and earpiece are effectively the
                // same choice in that they replace each other as an option when wired headsets
                // are plugged in and out. This means that keeping it earpiece is a bit more
                // consistent with the status quo.  Bluetooth also has more danger associated with
                // choosing it in the wrong curcumstance because bluetooth devices can be
                // semi-public (like in a very-occupied car) where earpiece doesn't carry that risk.
            }
        }

        // We need to call this every time even if we do not change the route because the supported
        // routes changed either to include or not include WIRED_HEADSET.
        setSystemAudioState(mCallAudioState.isMuted(), newRoute, calculateSupportedRoutes());
    }

    @Override
    public void onDockChanged(boolean isDocked) {
        // This can happen even when there are no calls and we don't have focus.
        if (!hasFocus()) {
            return;
        }

        if (isDocked) {
            // Device just docked, turn to speakerphone. Only do so if the route is currently
            // earpiece so that we dont switch out of a BT headset or a wired headset.
            if (mCallAudioState.getRoute() == CallAudioState.ROUTE_EARPIECE) {
                setAudioRoute(CallAudioState.ROUTE_SPEAKER);
            }
        } else {
            // Device just undocked, remove from speakerphone if possible.
            if (mCallAudioState.getRoute() == CallAudioState.ROUTE_SPEAKER) {
                setAudioRoute(CallAudioState.ROUTE_WIRED_OR_EARPIECE);
            }
        }
    }

    void toggleMute() {
        mute(!mCallAudioState.isMuted());
    }

    void mute(boolean shouldMute) {
        if (!hasFocus()) {
            return;
        }

        Log.v(this, "mute, shouldMute: %b", shouldMute);

        // Don't mute if there are any emergency calls.
        if (mCallsManager.hasEmergencyCall()) {
            shouldMute = false;
            Log.v(this, "ignoring mute for emergency call");
        }

        if (mCallAudioState.isMuted() != shouldMute) {
            // We user CallsManager's foreground call so that we dont ignore ringing calls
            // for logging purposes
            Log.event(mCallsManager.getForegroundCall(), Log.Events.MUTE,
                    shouldMute ? "on" : "off");

            setSystemAudioState(shouldMute, mCallAudioState.getRoute(),
                    mCallAudioState.getSupportedRouteMask());
        }
    }

    /**
     * Changed the audio route, for example from earpiece to speaker phone.
     *
     * @param route The new audio route to use. See {@link CallAudioState}.
     */
    void setAudioRoute(int route) {
        // This can happen even when there are no calls and we don't have focus.
        if (!hasFocus()) {
            return;
        }

        Log.v(this, "setAudioRoute, route: %s", CallAudioState.audioRouteToString(route));

        // Change ROUTE_WIRED_OR_EARPIECE to a single entry.
        int newRoute = selectWiredOrEarpiece(route, mCallAudioState.getSupportedRouteMask());

        // If route is unsupported, do nothing.
        if ((mCallAudioState.getSupportedRouteMask() | newRoute) == 0) {
            Log.wtf(this, "Asking to set to a route that is unsupported: %d", newRoute);
            return;
        }

        if (mCallAudioState.getRoute() != newRoute) {
            // Remember the new speaker state so it can be restored when the user plugs and unplugs
            // a headset.
            mWasSpeakerOn = newRoute == CallAudioState.ROUTE_SPEAKER;
            setSystemAudioState(mCallAudioState.isMuted(), newRoute,
                    mCallAudioState.getSupportedRouteMask());
        }
    }

    /**
     * Sets the audio stream and mode based on whether a call is ringing.
     *
     * @param call The call which changed ringing state.
     * @param isRinging {@code true} if the call is ringing, {@code false} otherwise.
     */
    void setIsRinging(Call call, boolean isRinging) {
        if (mIsRinging != isRinging) {
            Log.i(this, "setIsRinging %b -> %b (call = %s)", mIsRinging, isRinging, call);
            mIsRinging = isRinging;
            updateAudioStreamAndMode(call);
        }
    }

    /**
     * Sets the tone playing status. Some tones can play even when there are no live calls and this
     * status indicates that we should keep audio focus even for tones that play beyond the life of
     * calls.
     *
     * @param isPlayingNew The status to set.
     */
    void setIsTonePlaying(boolean isPlayingNew) {
        if (mIsTonePlaying != isPlayingNew) {
            Log.v(this, "mIsTonePlaying %b -> %b.", mIsTonePlaying, isPlayingNew);
            mIsTonePlaying = isPlayingNew;
            updateAudioStreamAndMode();
        }
    }

    /**
     * Updates the audio routing according to the bluetooth state.
     */
    void onBluetoothStateChange(BluetoothManager bluetoothManager) {
        // This can happen even when there are no calls and we don't have focus.
        if (!hasFocus()) {
            return;
        }

        int supportedRoutes = calculateSupportedRoutes();
        int newRoute = mCallAudioState.getRoute();
        if (bluetoothManager.isBluetoothAudioConnectedOrPending()) {
            newRoute = CallAudioState.ROUTE_BLUETOOTH;
        } else if (mCallAudioState.getRoute() == CallAudioState.ROUTE_BLUETOOTH) {
            newRoute = selectWiredOrEarpiece(CallAudioState.ROUTE_WIRED_OR_EARPIECE,
                    supportedRoutes);
            // Do not switch to speaker when bluetooth disconnects.
            mWasSpeakerOn = false;
        }

        setSystemAudioState(mCallAudioState.isMuted(), newRoute, supportedRoutes);
    }

    boolean isBluetoothAudioOn() {
        return mBluetoothManager.isBluetoothAudioConnected();
    }

    boolean isBluetoothDeviceAvailable() {
        return mBluetoothManager.isBluetoothAvailable();
    }

    private void saveAudioState(CallAudioState callAudioState) {
        mCallAudioState = callAudioState;
        mStatusBarNotifier.notifyMute(mCallAudioState.isMuted());
        mStatusBarNotifier.notifySpeakerphone(mCallAudioState.getRoute()
                == CallAudioState.ROUTE_SPEAKER);
    }

    private void onCallUpdated(Call call) {
        updateAudioStreamAndMode(call);
        if (call != null && call.getState() == CallState.ACTIVE &&
                            call == mCallToSpeedUpMTAudio) {
            mCallToSpeedUpMTAudio = null;
        }
    }

    private void setSystemAudioState(boolean isMuted, int route, int supportedRouteMask) {
        setSystemAudioState(false /* force */, isMuted, route, supportedRouteMask);
    }

    private void setSystemAudioState(
            boolean force, boolean isMuted, int route, int supportedRouteMask) {
        if (!hasFocus()) {
            return;
        }

        CallAudioState oldAudioState = mCallAudioState;
        saveAudioState(new CallAudioState(isMuted, route, supportedRouteMask));
        if (!force && Objects.equals(oldAudioState, mCallAudioState)) {
            return;
        }

        Log.i(this, "setSystemAudioState: changing from %s to %s", oldAudioState, mCallAudioState);
        Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE,
                CallAudioState.audioRouteToString(mCallAudioState.getRoute()));

        mAudioManagerHandler.obtainMessage(
                MSG_AUDIO_MANAGER_SET_MICROPHONE_MUTE,
                mCallAudioState.isMuted() ? 1 : 0,
                0)
                .sendToTarget();

        // Audio route.
        if (mCallAudioState.getRoute() == CallAudioState.ROUTE_BLUETOOTH) {
            turnOnSpeaker(false);
            turnOnBluetooth(true);
        } else if (mCallAudioState.getRoute() == CallAudioState.ROUTE_SPEAKER) {
            turnOnBluetooth(false);
            turnOnSpeaker(true);
        } else if (mCallAudioState.getRoute() == CallAudioState.ROUTE_EARPIECE ||
                mCallAudioState.getRoute() == CallAudioState.ROUTE_WIRED_HEADSET) {
            turnOnBluetooth(false);
            turnOnSpeaker(false);
        }

        if (!oldAudioState.equals(mCallAudioState)) {
            mCallsManager.onCallAudioStateChanged(oldAudioState, mCallAudioState);
            updateAudioForForegroundCall();
        }
    }

    private void turnOnSpeaker(boolean on) {
        mAudioManagerHandler.obtainMessage(MSG_AUDIO_MANAGER_TURN_ON_SPEAKER, on ? 1 : 0, 0)
                .sendToTarget();
    }

    private void turnOnBluetooth(boolean on) {
        if (mBluetoothManager.isBluetoothAvailable()) {
            boolean isAlreadyOn = mBluetoothManager.isBluetoothAudioConnectedOrPending();
            if (on != isAlreadyOn) {
                Log.i(this, "connecting bluetooth %s", on);
                if (on) {
                    mBluetoothManager.connectBluetoothAudio();
                } else {
                    mBluetoothManager.disconnectBluetoothAudio();
                }
            }
        }
    }

    private void updateAudioStreamAndMode() {
        updateAudioStreamAndMode(null /* call */);
    }

    private void updateAudioStreamAndMode(Call callToUpdate) {
        Log.i(this, "updateAudioStreamAndMode :  mIsRinging: %b, mIsTonePlaying: %b, call: %s",
                mIsRinging, mIsTonePlaying, callToUpdate);

        boolean wasVoiceCall = mAudioFocusStreamType == AudioManager.STREAM_VOICE_CALL;
        if (mIsRinging) {
            Log.i(this, "updateAudioStreamAndMode : ringing");
            requestAudioFocusAndSetMode(AudioManager.STREAM_RING, AudioManager.MODE_RINGTONE);
        } else {
            Call foregroundCall = getForegroundCall();
            Call waitingForAccountSelectionCall = mCallsManager
                    .getFirstCallWithState(CallState.SELECT_PHONE_ACCOUNT);
            Call call = mCallsManager.getForegroundCall();
            if (foregroundCall == null && call != null && call == mCallToSpeedUpMTAudio) {
                Log.v(this, "updateAudioStreamAndMode : no foreground, speeding up MT audio.");
                requestAudioFocusAndSetMode(AudioManager.STREAM_VOICE_CALL,
                                                         AudioManager.MODE_IN_CALL);
            } else if (foregroundCall != null && !foregroundCall.isDisconnected() &&
                    waitingForAccountSelectionCall == null) {
                // In the case where there is a call that is waiting for account selection,
                // this will fall back to abandonAudioFocus() below, which temporarily exits
                // the in-call audio mode. This is to allow TalkBack to speak the "Call with"
                // dialog information at media volume as opposed to through the earpiece.
                // Once exiting the "Call with" dialog, the audio focus will return to an in-call
                // audio mode when this method (updateAudioStreamAndMode) is called again.
                int mode = foregroundCall.getIsVoipAudioMode() ?
                        AudioManager.MODE_IN_COMMUNICATION : AudioManager.MODE_IN_CALL;
                Log.v(this, "updateAudioStreamAndMode : foreground");
                requestAudioFocusAndSetMode(AudioManager.STREAM_VOICE_CALL, mode);
            } else if (mIsTonePlaying) {
                // There is no call, however, we are still playing a tone, so keep focus.
                // Since there is no call from which to determine the mode, use the most
                // recently used mode instead.
                Log.v(this, "updateAudioStreamAndMode : tone playing");
                requestAudioFocusAndSetMode(
                        AudioManager.STREAM_VOICE_CALL, mMostRecentlyUsedMode);
            } else if (!hasRingingForegroundCall() && mCallsManager.hasOnlyDisconnectedCalls()) {
                Log.v(this, "updateAudioStreamAndMode : no ringing call");
                abandonAudioFocus();
            } else {
                // mIsRinging is false, but there is a foreground ringing call present. Don't
                // abandon audio focus immediately to prevent audio focus from getting lost between
                // the time it takes for the foreground call to transition from RINGING to ACTIVE/
                // DISCONNECTED. When the call eventually transitions to the next state, audio
                // focus will be correctly abandoned by the if clause above.
            }
        }

        boolean isVoiceCall = mAudioFocusStreamType == AudioManager.STREAM_VOICE_CALL;

        // If we transition from not a voice call to a voice call, we need to set an initial audio
        // state for the call.
        if (!wasVoiceCall && isVoiceCall) {
            setInitialAudioState(callToUpdate, true /* force */);
        }
    }

    private void requestAudioFocusAndSetMode(int stream, int mode) {
        Log.v(this, "requestAudioFocusAndSetMode : stream: %s -> %s, mode: %s",
                streamTypeToString(mAudioFocusStreamType), streamTypeToString(stream),
                modeToString(mode));
        Preconditions.checkState(stream != STREAM_NONE);

        // Even if we already have focus, if the stream is different we update audio manager to give
        // it a hint about the purpose of our focus.
        if (mAudioFocusStreamType != stream) {
            Log.i(this, "requestAudioFocusAndSetMode : requesting stream: %s -> %s",
                    streamTypeToString(mAudioFocusStreamType), streamTypeToString(stream));
            mAudioManagerHandler.obtainMessage(
                    MSG_AUDIO_MANAGER_REQUEST_AUDIO_FOCUS_FOR_CALL,
                    stream,
                    0)
                    .sendToTarget();
        }
        mAudioFocusStreamType = stream;

        setMode(mode);
    }

    private void abandonAudioFocus() {
        if (hasFocus()) {
            setMode(AudioManager.MODE_NORMAL);
            Log.v(this, "abandoning audio focus");
            mAudioManagerHandler.obtainMessage(MSG_AUDIO_MANAGER_ABANDON_AUDIO_FOCUS_FOR_CALL, 0, 0)
                    .sendToTarget();
            mAudioFocusStreamType = STREAM_NONE;
            mCallToSpeedUpMTAudio = null;
        }
    }

    /**
     * Sets the audio mode.
     *
     * @param newMode Mode constant from AudioManager.MODE_*.
     */
    private void setMode(int newMode) {
        Preconditions.checkState(hasFocus());
        mAudioManagerHandler.obtainMessage(MSG_AUDIO_MANAGER_SET_MODE, newMode, 0).sendToTarget();
    }

    private int selectWiredOrEarpiece(int route, int supportedRouteMask) {
        // Since they are mutually exclusive and one is ALWAYS valid, we allow a special input of
        // ROUTE_WIRED_OR_EARPIECE so that callers dont have to make a call to check which is
        // supported before calling setAudioRoute.
        if (route == CallAudioState.ROUTE_WIRED_OR_EARPIECE) {
            route = CallAudioState.ROUTE_WIRED_OR_EARPIECE & supportedRouteMask;
            if (route == 0) {
                Log.wtf(this, "One of wired headset or earpiece should always be valid.");
                // assume earpiece in this case.
                route = CallAudioState.ROUTE_EARPIECE;
            }
        }
        return route;
    }

    private int calculateSupportedRoutes() {
        int routeMask = CallAudioState.ROUTE_SPEAKER;

        if (mWiredHeadsetManager.isPluggedIn()) {
            routeMask |= CallAudioState.ROUTE_WIRED_HEADSET;
        } else {
            routeMask |= CallAudioState.ROUTE_EARPIECE;
        }

        if (mBluetoothManager.isBluetoothAvailable()) {
            routeMask |=  CallAudioState.ROUTE_BLUETOOTH;
        }

        return routeMask;
    }

    private CallAudioState getInitialAudioState(Call call) {
        int supportedRouteMask = calculateSupportedRoutes();
        int route = selectWiredOrEarpiece(
                CallAudioState.ROUTE_WIRED_OR_EARPIECE, supportedRouteMask);

        // We want the UI to indicate that "bluetooth is in use" in two slightly different cases:
        // (a) The obvious case: if a bluetooth headset is currently in use for an ongoing call.
        // (b) The not-so-obvious case: if an incoming call is ringing, and we expect that audio
        //     *will* be routed to a bluetooth headset once the call is answered. In this case, just
        //     check if the headset is available. Note this only applies when we are dealing with
        //     the first call.
        if (call != null && mBluetoothManager.isBluetoothAvailable()) {
            switch(call.getState()) {
                case CallState.ACTIVE:
                case CallState.ON_HOLD:
                case CallState.DIALING:
                case CallState.CONNECTING:
                case CallState.RINGING:
                    route = CallAudioState.ROUTE_BLUETOOTH;
                    break;
                default:
                    break;
            }
        }

        return new CallAudioState(false, route, supportedRouteMask);
    }

    private void setInitialAudioState(Call call, boolean force) {
        CallAudioState audioState = getInitialAudioState(call);
        Log.i(this, "setInitialAudioState : audioState = %s, call = %s", audioState, call);
        setSystemAudioState(
                force, audioState.isMuted(), audioState.getRoute(),
                audioState.getSupportedRouteMask());
    }

    private void updateAudioForForegroundCall() {
        Call call = mCallsManager.getForegroundCall();
        if (call != null && call.getConnectionService() != null) {
            call.getConnectionService().onCallAudioStateChanged(call, mCallAudioState);
        }
    }

    /**
     * Returns the current foreground call in order to properly set the audio mode.
     */
    private Call getForegroundCall() {
        Call call = mCallsManager.getForegroundCall();

        // We ignore any foreground call that is in the ringing state because we deal with ringing
        // calls exclusively through the mIsRinging variable set by {@link Ringer}.
        if (call != null && call.getState() == CallState.RINGING) {
            return null;
        }

        return call;
    }

    private boolean hasRingingForegroundCall() {
        Call call = mCallsManager.getForegroundCall();
        return call != null && call.getState() == CallState.RINGING;
    }

    private boolean hasFocus() {
        return mAudioFocusStreamType != STREAM_NONE;
    }

    private IAudioService getAudioService() {
        return IAudioService.Stub.asInterface(ServiceManager.getService(Context.AUDIO_SERVICE));
    }

    private int getCurrentUserId() {
        final long ident = Binder.clearCallingIdentity();
        try {
            UserInfo currentUser = ActivityManagerNative.getDefault().getCurrentUser();
            return currentUser.id;
        } catch (RemoteException e) {
            // Activity manager not running, nothing we can do assume user 0.
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
        return UserHandle.USER_OWNER;
    }

    /**
     * Translates an {@link AudioManager} stream type to a human-readable string description.
     *
     * @param streamType The stream type.
     * @return Human readable description.
     */
    private String streamTypeToString(int streamType) {
        switch (streamType) {
            case STREAM_NONE:
                return STREAM_DESCRIPTION_NONE;
            case AudioManager.STREAM_ALARM:
                return STREAM_DESCRIPTION_ALARM;
            case AudioManager.STREAM_BLUETOOTH_SCO:
                return STREAM_DESCRIPTION_BLUETOOTH_SCO;
            case AudioManager.STREAM_DTMF:
                return STREAM_DESCRIPTION_DTMF;
            case AudioManager.STREAM_MUSIC:
                return STREAM_DESCRIPTION_MUSIC;
            case AudioManager.STREAM_NOTIFICATION:
                return STREAM_DESCRIPTION_NOTIFICATION;
            case AudioManager.STREAM_RING:
                return STREAM_DESCRIPTION_RING;
            case AudioManager.STREAM_SYSTEM:
                return STREAM_DESCRIPTION_SYSTEM;
            case AudioManager.STREAM_VOICE_CALL:
                return STREAM_DESCRIPTION_VOICE_CALL;
            default:
                return "STEAM_OTHER_" + streamType;
        }
    }

    /**
     * Translates an {@link AudioManager} mode into a human readable string.
     *
     * @param mode The mode.
     * @return The string.
     */
    private String modeToString(int mode) {
        switch (mode) {
            case AudioManager.MODE_INVALID:
                return MODE_DESCRIPTION_INVALID;
            case AudioManager.MODE_CURRENT:
                return MODE_DESCRIPTION_CURRENT;
            case AudioManager.MODE_NORMAL:
                return MODE_DESCRIPTION_NORMAL;
            case AudioManager.MODE_RINGTONE:
                return MODE_DESCRIPTION_RINGTONE;
            case AudioManager.MODE_IN_CALL:
                return MODE_DESCRIPTION_IN_CALL;
            case AudioManager.MODE_IN_COMMUNICATION:
                return MODE_DESCRIPTION_IN_COMMUNICATION;
            default:
                return "MODE_OTHER_" + mode;
        }
    }

    /**
     * Dumps the state of the {@link CallAudioManager}.
     *
     * @param pw The {@code IndentingPrintWriter} to write the state to.
     */
    public void dump(IndentingPrintWriter pw) {
        pw.println("mAudioState: " + mCallAudioState);
        pw.println("mBluetoothManager:");
        pw.increaseIndent();
        mBluetoothManager.dump(pw);
        pw.decreaseIndent();
        if (mWiredHeadsetManager != null) {
            pw.println("mWiredHeadsetManager:");
            pw.increaseIndent();
            mWiredHeadsetManager.dump(pw);
            pw.decreaseIndent();
        } else {
            pw.println("mWiredHeadsetManager: null");
        }
        pw.println("mAudioFocusStreamType: " + streamTypeToString(mAudioFocusStreamType));
        pw.println("mIsRinging: " + mIsRinging);
        pw.println("mIsTonePlaying: " + mIsTonePlaying);
        pw.println("mWasSpeakerOn: " + mWasSpeakerOn);
        pw.println("mMostRecentlyUsedMode: " + modeToString(mMostRecentlyUsedMode));
    }
}
