Loading src/com/android/server/telecom/AudioRoute.java +35 −17 Original line number Original line Diff line number Diff line Loading @@ -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, Loading @@ -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 {} Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -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); Loading src/com/android/server/telecom/CallAudioRouteController.java +52 −20 Original line number Original line Diff line number Diff line Loading @@ -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 { Loading @@ -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); Loading Loading @@ -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"); } } } } Loading Loading @@ -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"); Loading @@ -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 Loading Loading @@ -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() Loading @@ -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, Loading tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java +31 −2 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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"); Loading @@ -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); } } }; }; Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading
src/com/android/server/telecom/AudioRoute.java +35 −17 Original line number Original line Diff line number Diff line Loading @@ -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, Loading @@ -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 {} Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -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); Loading
src/com/android/server/telecom/CallAudioRouteController.java +52 −20 Original line number Original line Diff line number Diff line Loading @@ -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 { Loading @@ -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); Loading Loading @@ -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"); } } } } Loading Loading @@ -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"); Loading @@ -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 Loading Loading @@ -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() Loading @@ -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, Loading
tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java +31 −2 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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"); Loading @@ -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); } } }; }; Loading Loading @@ -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); Loading Loading @@ -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); Loading