Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 63705494 authored by Pranav Madapurmath's avatar Pranav Madapurmath Committed by Android (Google) Code Review
Browse files

Merge "Support TYPE_BUS for call audio routing." into main

parents e20864c0 c6d92242
Loading
Loading
Loading
Loading
+35 −17
Original line number Original line Diff line number Diff line
@@ -117,6 +117,8 @@ public class AudioRoute {
    public static final int TYPE_BLUETOOTH_HA = 6;
    public static final int TYPE_BLUETOOTH_HA = 6;
    public static final int TYPE_BLUETOOTH_LE = 7;
    public static final int TYPE_BLUETOOTH_LE = 7;
    public static final int TYPE_STREAMING = 8;
    public static final int TYPE_STREAMING = 8;
    // Used by auto
    public static final int TYPE_BUS = 9;
    @IntDef(prefix = "TYPE", value = {
    @IntDef(prefix = "TYPE", value = {
            TYPE_INVALID,
            TYPE_INVALID,
            TYPE_EARPIECE,
            TYPE_EARPIECE,
@@ -126,7 +128,8 @@ public class AudioRoute {
            TYPE_BLUETOOTH_SCO,
            TYPE_BLUETOOTH_SCO,
            TYPE_BLUETOOTH_HA,
            TYPE_BLUETOOTH_HA,
            TYPE_BLUETOOTH_LE,
            TYPE_BLUETOOTH_LE,
            TYPE_STREAMING
            TYPE_STREAMING,
            TYPE_BUS
    })
    })
    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    public @interface AudioRouteType {}
    public @interface AudioRouteType {}
@@ -155,35 +158,38 @@ public class AudioRoute {
        DEVICE_TYPE_STRINGS.put(TYPE_WIRED, "TYPE_WIRED_HEADSET");
        DEVICE_TYPE_STRINGS.put(TYPE_WIRED, "TYPE_WIRED_HEADSET");
        DEVICE_TYPE_STRINGS.put(TYPE_SPEAKER, "TYPE_SPEAKER");
        DEVICE_TYPE_STRINGS.put(TYPE_SPEAKER, "TYPE_SPEAKER");
        DEVICE_TYPE_STRINGS.put(TYPE_DOCK, "TYPE_DOCK");
        DEVICE_TYPE_STRINGS.put(TYPE_DOCK, "TYPE_DOCK");
        DEVICE_TYPE_STRINGS.put(TYPE_BUS, "TYPE_BUS");
        DEVICE_TYPE_STRINGS.put(TYPE_BLUETOOTH_SCO, "TYPE_BLUETOOTH_SCO");
        DEVICE_TYPE_STRINGS.put(TYPE_BLUETOOTH_SCO, "TYPE_BLUETOOTH_SCO");
        DEVICE_TYPE_STRINGS.put(TYPE_BLUETOOTH_HA, "TYPE_BLUETOOTH_HA");
        DEVICE_TYPE_STRINGS.put(TYPE_BLUETOOTH_HA, "TYPE_BLUETOOTH_HA");
        DEVICE_TYPE_STRINGS.put(TYPE_BLUETOOTH_LE, "TYPE_BLUETOOTH_LE");
        DEVICE_TYPE_STRINGS.put(TYPE_BLUETOOTH_LE, "TYPE_BLUETOOTH_LE");
        DEVICE_TYPE_STRINGS.put(TYPE_STREAMING, "TYPE_STREAMING");
        DEVICE_TYPE_STRINGS.put(TYPE_STREAMING, "TYPE_STREAMING");
    }
    }


    public static final HashMap<Integer, Integer> DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE;
    public static final HashMap<Integer, Integer> DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE;
    static {
    static {
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE = new HashMap<>();
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE = new HashMap<>();
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
                TYPE_EARPIECE);
                TYPE_EARPIECE);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, TYPE_SPEAKER);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_WIRED_HEADSET, TYPE_WIRED);
                TYPE_SPEAKER);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, TYPE_WIRED);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_WIRED_HEADSET, TYPE_WIRED);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, TYPE_WIRED);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
                TYPE_BLUETOOTH_SCO);
                TYPE_BLUETOOTH_SCO);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_DEVICE, TYPE_WIRED);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_DEVICE, TYPE_WIRED);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_ACCESSORY, TYPE_WIRED);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_ACCESSORY, TYPE_WIRED);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_DOCK, TYPE_DOCK);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_DOCK, TYPE_DOCK);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_HEADSET, TYPE_WIRED);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_USB_HEADSET, TYPE_WIRED);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_HEARING_AID,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_HEARING_AID,
                TYPE_BLUETOOTH_HA);
                TYPE_BLUETOOTH_HA);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_HEADSET,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_HEADSET,
                TYPE_BLUETOOTH_LE);
                TYPE_BLUETOOTH_LE);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_SPEAKER,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_SPEAKER,
                TYPE_BLUETOOTH_LE);
                TYPE_BLUETOOTH_LE);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_BROADCAST,
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BLE_BROADCAST,
                TYPE_BLUETOOTH_LE);
                TYPE_BLUETOOTH_LE);
        DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_DOCK_ANALOG, TYPE_DOCK);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_DOCK_ANALOG, TYPE_DOCK);
        DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.put(AudioDeviceInfo.TYPE_BUS, TYPE_BUS);
    }
    }


    private static final HashMap<Integer, List<Integer>> AUDIO_ROUTE_TYPE_TO_DEVICE_INFO_TYPE;
    private static final HashMap<Integer, List<Integer>> AUDIO_ROUTE_TYPE_TO_DEVICE_INFO_TYPE;
@@ -210,6 +216,10 @@ public class AudioRoute {
        dockDeviceInfoTypes.add(AudioDeviceInfo.TYPE_DOCK_ANALOG);
        dockDeviceInfoTypes.add(AudioDeviceInfo.TYPE_DOCK_ANALOG);
        AUDIO_ROUTE_TYPE_TO_DEVICE_INFO_TYPE.put(TYPE_DOCK, dockDeviceInfoTypes);
        AUDIO_ROUTE_TYPE_TO_DEVICE_INFO_TYPE.put(TYPE_DOCK, dockDeviceInfoTypes);


        List<Integer> busDeviceInfoTypes = new ArrayList<>();
        busDeviceInfoTypes.add(AudioDeviceInfo.TYPE_BUS);
        AUDIO_ROUTE_TYPE_TO_DEVICE_INFO_TYPE.put(TYPE_BUS, busDeviceInfoTypes);

        List<Integer> bluetoothScoDeviceInfoTypes = new ArrayList<>();
        List<Integer> bluetoothScoDeviceInfoTypes = new ArrayList<>();
        bluetoothScoDeviceInfoTypes.add(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP);
        bluetoothScoDeviceInfoTypes.add(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP);
        bluetoothScoDeviceInfoTypes.add(AudioDeviceInfo.TYPE_BLUETOOTH_SCO);
        bluetoothScoDeviceInfoTypes.add(AudioDeviceInfo.TYPE_BLUETOOTH_SCO);
@@ -241,6 +251,10 @@ public class AudioRoute {
            BluetoothRouteManager bluetoothRouteManager, boolean isScoAudioConnected) {
            BluetoothRouteManager bluetoothRouteManager, boolean isScoAudioConnected) {
        Log.i(this, "onDestRouteAsPendingRoute: active (%b), type (%s)", active,
        Log.i(this, "onDestRouteAsPendingRoute: active (%b), type (%s)", active,
                DEVICE_TYPE_STRINGS.get(mAudioRouteType));
                DEVICE_TYPE_STRINGS.get(mAudioRouteType));
        if (mAudioRouteType == TYPE_BUS) {
            Log.i(this, "onDestRouteAsPendingRoute: Ignore processing dest route for TYPE_BUS");
            return;
        }
        if (pendingAudioRoute.isActive() && !active) {
        if (pendingAudioRoute.isActive() && !active) {
            clearCommunicationDevice(pendingAudioRoute, bluetoothRouteManager, audioManager);
            clearCommunicationDevice(pendingAudioRoute, bluetoothRouteManager, audioManager);
        } else if (active) {
        } else if (active) {
@@ -302,6 +316,10 @@ public class AudioRoute {
    void onOrigRouteAsPendingRoute(boolean active, PendingAudioRoute pendingAudioRoute,
    void onOrigRouteAsPendingRoute(boolean active, PendingAudioRoute pendingAudioRoute,
            AudioManager audioManager, BluetoothRouteManager bluetoothRouteManager) {
            AudioManager audioManager, BluetoothRouteManager bluetoothRouteManager) {
        Log.i(this, "onOrigRouteAsPendingRoute: active (%b), type (%d)", active, mAudioRouteType);
        Log.i(this, "onOrigRouteAsPendingRoute: active (%b), type (%d)", active, mAudioRouteType);
        if (mAudioRouteType == TYPE_BUS) {
            Log.i(this, "onOrigRouteAsPendingRoute: Ignore processing dest route for TYPE_BUS");
            return;
        }
        if (active) {
        if (active) {
            if (mAudioRouteType == TYPE_SPEAKER) {
            if (mAudioRouteType == TYPE_SPEAKER) {
                pendingAudioRoute.addMessage(SPEAKER_OFF, null);
                pendingAudioRoute.addMessage(SPEAKER_OFF, null);
+52 −20
Original line number Original line Diff line number Diff line
@@ -63,7 +63,6 @@ import java.util.Objects;
import java.util.Set;
import java.util.Set;


public class CallAudioRouteController implements CallAudioRouteAdapter {
public class CallAudioRouteController implements CallAudioRouteAdapter {
    private static final long TIMEOUT_LIMIT = 2000L;
    private static final AudioRoute DUMMY_ROUTE = new AudioRoute(TYPE_INVALID, null, null);
    private static final AudioRoute DUMMY_ROUTE = new AudioRoute(TYPE_INVALID, null, null);
    private static final Map<Integer, Integer> ROUTE_MAP;
    private static final Map<Integer, Integer> ROUTE_MAP;
    static {
    static {
@@ -73,6 +72,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
        ROUTE_MAP.put(AudioRoute.TYPE_WIRED, CallAudioState.ROUTE_WIRED_HEADSET);
        ROUTE_MAP.put(AudioRoute.TYPE_WIRED, CallAudioState.ROUTE_WIRED_HEADSET);
        ROUTE_MAP.put(AudioRoute.TYPE_SPEAKER, CallAudioState.ROUTE_SPEAKER);
        ROUTE_MAP.put(AudioRoute.TYPE_SPEAKER, CallAudioState.ROUTE_SPEAKER);
        ROUTE_MAP.put(AudioRoute.TYPE_DOCK, CallAudioState.ROUTE_SPEAKER);
        ROUTE_MAP.put(AudioRoute.TYPE_DOCK, CallAudioState.ROUTE_SPEAKER);
        ROUTE_MAP.put(AudioRoute.TYPE_BUS, CallAudioState.ROUTE_SPEAKER);
        ROUTE_MAP.put(AudioRoute.TYPE_BLUETOOTH_SCO, CallAudioState.ROUTE_BLUETOOTH);
        ROUTE_MAP.put(AudioRoute.TYPE_BLUETOOTH_SCO, CallAudioState.ROUTE_BLUETOOTH);
        ROUTE_MAP.put(AudioRoute.TYPE_BLUETOOTH_HA, CallAudioState.ROUTE_BLUETOOTH);
        ROUTE_MAP.put(AudioRoute.TYPE_BLUETOOTH_HA, CallAudioState.ROUTE_BLUETOOTH);
        ROUTE_MAP.put(AudioRoute.TYPE_BLUETOOTH_LE, CallAudioState.ROUTE_BLUETOOTH);
        ROUTE_MAP.put(AudioRoute.TYPE_BLUETOOTH_LE, CallAudioState.ROUTE_BLUETOOTH);
@@ -353,14 +353,22 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {


        int supportMask = calculateSupportedRouteMaskInit();
        int supportMask = calculateSupportedRouteMaskInit();
        if ((supportMask & CallAudioState.ROUTE_SPEAKER) != 0) {
        if ((supportMask & CallAudioState.ROUTE_SPEAKER) != 0) {
            int audioRouteType = AudioRoute.TYPE_SPEAKER;
            // Create speaker routes
            // Create speaker routes
            mSpeakerDockRoute = mAudioRouteFactory.create(AudioRoute.TYPE_SPEAKER, null,
            mSpeakerDockRoute = mAudioRouteFactory.create(AudioRoute.TYPE_SPEAKER, null,
                    mAudioManager);
                    mAudioManager);
            // Todo(b/364562758): Represent TYPE_BUS as CallAudioState.ROUTE_SPEAKER (moving
            // forward, we may rework this if audio fwk team decides to allow list this as a
            // valid communication device.
            if (mSpeakerDockRoute != null || hasBusAudioDevice()) {
                if (mSpeakerDockRoute == null){
                if (mSpeakerDockRoute == null){
                Log.w(this, "Can't find available audio device info for route TYPE_SPEAKER");
                    mSpeakerDockRoute = new AudioRoute(AudioRoute.TYPE_BUS, null, null);
            } else {
                    audioRouteType = AudioRoute.TYPE_BUS;
                mTypeRoutes.put(AudioRoute.TYPE_SPEAKER, mSpeakerDockRoute);
                }
                mTypeRoutes.put(audioRouteType, mSpeakerDockRoute);
                updateAvailableRoutes(mSpeakerDockRoute, true);
                updateAvailableRoutes(mSpeakerDockRoute, true);
            } else {
                Log.w(this, "Can't find available audio device info for route TYPE_SPEAKER");
            }
            }
        }
        }


@@ -905,7 +913,8 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
    }
    }


    private void handleSwitchSpeaker() {
    private void handleSwitchSpeaker() {
        if (mSpeakerDockRoute != null && getCallSupportedRoutes().contains(mSpeakerDockRoute)) {
        if (mSpeakerDockRoute != null && getCallSupportedRoutes().contains(mSpeakerDockRoute)
                && mSpeakerDockRoute.getType() == AudioRoute.TYPE_SPEAKER) {
            routeTo(mIsActive, mSpeakerDockRoute);
            routeTo(mIsActive, mSpeakerDockRoute);
        } else {
        } else {
            Log.i(this, "ignore switch speaker request");
            Log.i(this, "ignore switch speaker request");
@@ -923,8 +932,8 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
            // Update status bar notification if we are in a call.
            // Update status bar notification if we are in a call.
            mStatusBarNotifier.notifySpeakerphone(mCallsManager.hasAnyCalls());
            mStatusBarNotifier.notifySpeakerphone(mCallsManager.hasAnyCalls());
        } else {
        } else {
            if (mSpeakerDockRoute != null && getCallSupportedRoutes()
            if (mSpeakerDockRoute != null && getCallSupportedRoutes().contains(mSpeakerDockRoute)
                    .contains(mSpeakerDockRoute)) {
                    && mSpeakerDockRoute.getType() == AudioRoute.TYPE_SPEAKER) {
                routeTo(mIsActive, mSpeakerDockRoute);
                routeTo(mIsActive, mSpeakerDockRoute);
                // Since the route switching triggered by this message, we need to manually send it
                // Since the route switching triggered by this message, we need to manually send it
                // again so that we won't stuck in the pending route
                // again so that we won't stuck in the pending route
@@ -1084,6 +1093,24 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
    }
    }


    private AudioRoute getPreferredAudioRouteFromStrategy() {
    private AudioRoute getPreferredAudioRouteFromStrategy() {
        // Get preferred device
        AudioDeviceAttributes deviceAttr = getPreferredDeviceForStrategy();
        Log.i(this, "getPreferredAudioRouteFromStrategy: preferred device is %s", deviceAttr);
        if (deviceAttr == null) {
            return null;
        }

        // Get corresponding audio route
        @AudioRoute.AudioRouteType int type = AudioRoute.DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.get(
                deviceAttr.getType());
        if (BT_AUDIO_ROUTE_TYPES.contains(type)) {
            return getBluetoothRoute(type, deviceAttr.getAddress());
        } else {
            return mTypeRoutes.get(type);
        }
    }

    private AudioDeviceAttributes getPreferredDeviceForStrategy() {
        // Get audio produce strategy
        // Get audio produce strategy
        AudioProductStrategy strategy = null;
        AudioProductStrategy strategy = null;
        final AudioAttributes attr = new AudioAttributes.Builder()
        final AudioAttributes attr = new AudioAttributes.Builder()
@@ -1099,21 +1126,26 @@ public class CallAudioRouteController implements CallAudioRouteAdapter {
            return null;
            return null;
        }
        }


        // Get preferred device
        return mAudioManager.getPreferredDeviceForStrategy(strategy);
        AudioDeviceAttributes deviceAttr = mAudioManager.getPreferredDeviceForStrategy(strategy);
        Log.i(this, "getPreferredAudioRouteFromStrategy: preferred device is %s", deviceAttr);
        if (deviceAttr == null) {
            return null;
    }
    }


        // Get corresponding audio route
    /**
        @AudioRoute.AudioRouteType int type = AudioRoute.DEVICE_INFO_TYPETO_AUDIO_ROUTE_TYPE.get(
     * For auto, there is no earpiece or speakerphone routes available. The audio is routed to the
                deviceAttr.getType());
     * bus but because this isn't a valid communication device,
        if (BT_AUDIO_ROUTE_TYPES.contains(type)) {
     * {@link AudioManager#getCommunicationDevice()} will not provide this device even if audio fwk
            return getBluetoothRoute(type, deviceAttr.getAddress());
     * reports it as the active communication device (refer to
        } else {
     * AudioDeviceBroker#getCommunicationDeviceInt()}. Check if the device is the preferred device
            return mTypeRoutes.get(type);
     * for strategy instead.
     */
    private boolean hasBusAudioDevice() {
        AudioDeviceAttributes deviceAttr = getPreferredDeviceForStrategy();
        if (deviceAttr == null) {
            return false;
        }
        }
        // Get corresponding audio route mapping
        @AudioRoute.AudioRouteType int type = AudioRoute.DEVICE_INFO_TYPE_TO_AUDIO_ROUTE_TYPE.get(
                deviceAttr.getType());
        return type == AudioRoute.TYPE_BUS;
    }
    }


    private AudioRoute getPreferredAudioRouteFromDefault(boolean includeBluetooth,
    private AudioRoute getPreferredAudioRouteFromDefault(boolean includeBluetooth,
+31 −2
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ import static com.android.server.telecom.CallAudioRouteAdapter.USER_SWITCH_SPEAK
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.ArgumentMatchers.nullable;
@@ -63,7 +64,6 @@ import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.media.AudioDeviceInfo;
import android.media.AudioDeviceInfo;
import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.media.AudioManager;
import android.media.IAudioService;
import android.media.IAudioService;
import android.media.audiopolicy.AudioProductStrategy;
import android.media.audiopolicy.AudioProductStrategy;
@@ -86,7 +86,6 @@ import com.android.server.telecom.WiredHeadsetManager;
import com.android.server.telecom.bluetooth.BluetoothDeviceManager;
import com.android.server.telecom.bluetooth.BluetoothDeviceManager;
import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import com.android.server.telecom.bluetooth.BluetoothRouteManager;


import dalvik.annotation.TestTarget;
import org.junit.After;
import org.junit.After;
import org.junit.Before;
import org.junit.Before;
import org.junit.Test;
import org.junit.Test;
@@ -119,6 +118,7 @@ public class CallAudioRouteControllerTest extends TelecomTestCase {
    @Mock private TelecomSystem.SyncRoot mLock;
    @Mock private TelecomSystem.SyncRoot mLock;
    private AudioRoute mEarpieceRoute;
    private AudioRoute mEarpieceRoute;
    private AudioRoute mSpeakerRoute;
    private AudioRoute mSpeakerRoute;
    private boolean mOverrideSpeakerToBus;
    private static final String BT_ADDRESS_1 = "00:00:00:00:00:01";
    private static final String BT_ADDRESS_1 = "00:00:00:00:00:01";
    private static final BluetoothDevice BLUETOOTH_DEVICE_1 =
    private static final BluetoothDevice BLUETOOTH_DEVICE_1 =
            BluetoothRouteManagerTest.makeBluetoothDevice("00:00:00:00:00:01");
            BluetoothRouteManagerTest.makeBluetoothDevice("00:00:00:00:00:01");
@@ -132,6 +132,9 @@ public class CallAudioRouteControllerTest extends TelecomTestCase {
        @Override
        @Override
        public AudioRoute create(@AudioRoute.AudioRouteType int type, String bluetoothAddress,
        public AudioRoute create(@AudioRoute.AudioRouteType int type, String bluetoothAddress,
                                 AudioManager audioManager) {
                                 AudioManager audioManager) {
            if (mOverrideSpeakerToBus && type == AudioRoute.TYPE_SPEAKER) {
                type = AudioRoute.TYPE_BUS;
            }
            return new AudioRoute(type, bluetoothAddress, mAudioDeviceInfo);
            return new AudioRoute(type, bluetoothAddress, mAudioDeviceInfo);
        }
        }
    };
    };
@@ -177,6 +180,7 @@ public class CallAudioRouteControllerTest extends TelecomTestCase {
        mController.setAudioManager(mAudioManager);
        mController.setAudioManager(mAudioManager);
        mEarpieceRoute = new AudioRoute(AudioRoute.TYPE_EARPIECE, null, null);
        mEarpieceRoute = new AudioRoute(AudioRoute.TYPE_EARPIECE, null, null);
        mSpeakerRoute = new AudioRoute(AudioRoute.TYPE_SPEAKER, null, null);
        mSpeakerRoute = new AudioRoute(AudioRoute.TYPE_SPEAKER, null, null);
        mOverrideSpeakerToBus = false;
        mController.setCallAudioManager(mCallAudioManager);
        mController.setCallAudioManager(mCallAudioManager);
        when(mCallAudioManager.getForegroundCall()).thenReturn(mCall);
        when(mCallAudioManager.getForegroundCall()).thenReturn(mCall);
        when(mCall.getVideoState()).thenReturn(VideoProfile.STATE_AUDIO_ONLY);
        when(mCall.getVideoState()).thenReturn(VideoProfile.STATE_AUDIO_ONLY);
@@ -877,6 +881,31 @@ public class CallAudioRouteControllerTest extends TelecomTestCase {
        assertEquals(1, mController.getCallSupportedRoutes().size());
        assertEquals(1, mController.getCallSupportedRoutes().size());
    }
    }


    @SmallTest
    @Test
    public void testRouteToBusForAuto() {
        when(mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS))
                .thenReturn(new AudioDeviceInfo[0]);
        mOverrideSpeakerToBus = true;
        mController.initialize();

        mController.sendMessageWithSessionInfo(SWITCH_FOCUS, ACTIVE_FOCUS, 0);
        waitForHandlerAction(mController.getAdapterHandler(), TEST_TIMEOUT);
        PendingAudioRoute pendingRoute = mController.getPendingAudioRoute();
        assertEquals(AudioRoute.TYPE_BUS, pendingRoute.getDestRoute().getType());

        CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_SPEAKER,
                CallAudioState.ROUTE_SPEAKER, null, new HashSet<>());
        verify(mCallsManager, timeout(TEST_TIMEOUT)).onCallAudioStateChanged(
                any(CallAudioState.class), eq(expectedState));

        // Ensure that turning speaker phone on doesn't get triggered when speaker isn't available.
        mController.sendMessageWithSessionInfo(USER_SWITCH_SPEAKER);
        mController.sendMessageWithSessionInfo(SPEAKER_ON);
        verify(mockStatusBarNotifier, times(0)).notifySpeakerphone(anyBoolean());

    }

    private void verifyConnectBluetoothDevice(int audioType) {
    private void verifyConnectBluetoothDevice(int audioType) {
        mController.initialize();
        mController.initialize();
        mController.setActive(true);
        mController.setActive(true);