Loading src/com/android/server/telecom/CallAudioRouteController.java +86 −19 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { private final Handler mHandler; private final WiredHeadsetManager mWiredHeadsetManager; private Set<AudioRoute> mAvailableRoutes; private Set<AudioRoute> mCallSupportedRoutes; private AudioRoute mCurrentRoute; private AudioRoute mEarpieceWiredRoute; private AudioRoute mSpeakerDockRoute; Loading @@ -104,6 +105,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { private StatusBarNotifier mStatusBarNotifier; private FeatureFlags mFeatureFlags; private int mFocusType; private int mCallSupportedRouteMask = -1; private boolean mIsScoAudioConnected; private final Object mLock = new Object(); private final TelecomSystem.SyncRoot mTelecomLock; Loading Loading @@ -314,6 +316,9 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { handleExitPendingRoute(); break; case UPDATE_SYSTEM_AUDIO_ROUTE: // Based on the available routes for foreground call, adjust routing. updateRouteForForeground(); // Force update to notify all ICS/CS. updateCallAudioState(new CallAudioState(mIsMute, mCallAudioState.getRoute(), mCallAudioState.getSupportedRouteMask(), Loading @@ -330,6 +335,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { @Override public void initialize() { mAvailableRoutes = new HashSet<>(); mCallSupportedRoutes = new HashSet<>(); mBluetoothRoutes = new LinkedHashMap<>(); mActiveDeviceCache = new HashMap<>(); mActiveDeviceCache.put(AudioRoute.TYPE_BLUETOOTH_SCO, null); Loading Loading @@ -485,7 +491,8 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { } private void routeTo(boolean active, AudioRoute destRoute) { if (!destRoute.equals(mStreamingRoute) && !getAvailableRoutes().contains(destRoute)) { if (destRoute == null || (!destRoute.equals(mStreamingRoute) && !getCallSupportedRoutes().contains(destRoute))) { Log.i(this, "Ignore routing to unavailable route: %s", destRoute); return; } Loading @@ -510,7 +517,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { Log.i(this, "Enter pending route, orig%s(active=%b), dest%s(active=%b)", mCurrentRoute, mIsActive, destRoute, active); // route to pending route if (getAvailableRoutes().contains(mCurrentRoute)) { if (getCallSupportedRoutes().contains(mCurrentRoute)) { mPendingAudioRoute.setOrigRoute(mIsActive, mCurrentRoute); } else { // Avoid waiting for pending messages for an unavailable route Loading Loading @@ -841,7 +848,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { public void handleSwitchEarpiece() { AudioRoute earpieceRoute = mTypeRoutes.get(AudioRoute.TYPE_EARPIECE); if (earpieceRoute != null && getAvailableRoutes().contains(earpieceRoute)) { if (earpieceRoute != null && getCallSupportedRoutes().contains(earpieceRoute)) { routeTo(mIsActive, earpieceRoute); } else { Log.i(this, "ignore switch earpiece request"); Loading @@ -856,7 +863,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { bluetoothRoute = getArbitraryBluetoothDevice(); bluetoothDevice = mBluetoothRoutes.get(bluetoothRoute); } else { for (AudioRoute route : getAvailableRoutes()) { for (AudioRoute route : getCallSupportedRoutes()) { if (Objects.equals(address, route.getBluetoothAddress())) { bluetoothRoute = route; bluetoothDevice = mBluetoothRoutes.get(route); Loading Loading @@ -894,7 +901,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { private void handleSwitchHeadset() { AudioRoute headsetRoute = mTypeRoutes.get(AudioRoute.TYPE_WIRED); if (headsetRoute != null && getAvailableRoutes().contains(headsetRoute)) { if (headsetRoute != null && getCallSupportedRoutes().contains(headsetRoute)) { routeTo(mIsActive, headsetRoute); } else { Log.i(this, "ignore switch headset request"); Loading @@ -902,7 +909,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { } private void handleSwitchSpeaker() { if (mSpeakerDockRoute != null && getAvailableRoutes().contains(mSpeakerDockRoute)) { if (mSpeakerDockRoute != null && getCallSupportedRoutes().contains(mSpeakerDockRoute)) { routeTo(mIsActive, mSpeakerDockRoute); } else { Log.i(this, "ignore switch speaker request"); Loading @@ -920,7 +927,8 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { // Update status bar notification if we are in a call. mStatusBarNotifier.notifySpeakerphone(mCallsManager.hasAnyCalls()); } else { if (mSpeakerDockRoute != null && getAvailableRoutes().contains(mSpeakerDockRoute)) { if (mSpeakerDockRoute != null && getCallSupportedRoutes() .contains(mSpeakerDockRoute)) { routeTo(mIsActive, mSpeakerDockRoute); // 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 Loading Loading @@ -984,7 +992,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { synchronized (mLock) { int routeMask = 0; Set<BluetoothDevice> availableBluetoothDevices = new HashSet<>(); for (AudioRoute route : getAvailableRoutes()) { for (AudioRoute route : getCallSupportedRoutes()) { routeMask |= ROUTE_MAP.get(route.getType()); if (BT_AUDIO_ROUTE_TYPES.contains(route.getType())) { BluetoothDevice deviceToAdd = mBluetoothRoutes.get(route); Loading @@ -1004,6 +1012,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { } } } updateCallAudioState(new CallAudioState(mIsMute, mCallAudioState.getRoute(), routeMask, mCallAudioState.getActiveBluetoothDevice(), availableBluetoothDevices)); } Loading @@ -1015,7 +1024,50 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { mCallAudioState.getSupportedBluetoothDevices())); } /** * Retrieves the current call's supported audio route and adjusts the audio routing if the * current route isn't supported. */ private void updateRouteForForeground() { boolean updatedRouteForCall = updateCallSupportedAudioRoutes(); // Ensure that current call audio state has updated routes for current call. if (updatedRouteForCall) { mCallAudioState = new CallAudioState(mIsMute, mCallAudioState.getRoute(), mCallSupportedRouteMask, mCallAudioState.getActiveBluetoothDevice(), mCallAudioState.getSupportedBluetoothDevices()); // Update audio route if foreground call doesn't support the current route. if ((mCallSupportedRouteMask & mCallAudioState.getRoute()) == 0) { routeTo(mIsActive, getBaseRoute(true, null)); } } } /** * Update supported audio routes for the foreground call if present. */ private boolean updateCallSupportedAudioRoutes() { int availableRouteMask = 0; Call foregroundCall = mCallsManager.getForegroundCall(); if (foregroundCall != null) { int foregroundCallSupportedRouteMask = foregroundCall.getSupportedAudioRoutes(); for (AudioRoute route : getAvailableRoutes()) { int routeType = ROUTE_MAP.get(route.getType()); availableRouteMask |= routeType; if ((routeType & foregroundCallSupportedRouteMask) == routeType) { mCallSupportedRoutes.add(route); } } mCallSupportedRouteMask = availableRouteMask & foregroundCallSupportedRouteMask; return true; } else { mCallSupportedRoutes.clear(); mCallSupportedRouteMask = -1; return false; } } private void updateCallAudioState(CallAudioState newCallAudioState) { synchronized (mTelecomLock) { Log.i(this, "updateCallAudioState: updating call audio state to %s", newCallAudioState); CallAudioState oldState = mCallAudioState; mCallAudioState = newCallAudioState; Loading @@ -1024,6 +1076,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { mCallsManager.onCallAudioStateChanged(oldState, mCallAudioState); updateAudioStateForTrackedCalls(mCallAudioState); } } private void updateAudioStateForTrackedCalls(CallAudioState newCallAudioState) { Set<Call> calls = mCallsManager.getTrackedCalls(); Loading Loading @@ -1080,11 +1133,17 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { // are only wearables available. AudioRoute activeWatchOrNonWatchDeviceRoute = getActiveWatchOrNonWatchDeviceRoute(btAddressToExclude); if (mBluetoothRoutes.isEmpty() || !includeBluetooth || activeWatchOrNonWatchDeviceRoute == null) { if ((!mCallSupportedRoutes.isEmpty() && (mCallSupportedRouteMask & CallAudioState.ROUTE_BLUETOOTH) == 0) || mBluetoothRoutes.isEmpty() || !includeBluetooth || activeWatchOrNonWatchDeviceRoute == null) { Log.i(this, "getPreferredAudioRouteFromDefault: Audio routing defaulting to " + "available non-BT route."); AudioRoute defaultRoute = mEarpieceWiredRoute != null boolean callSupportsEarpieceWiredRoute = mCallSupportedRoutes.isEmpty() || mCallSupportedRoutes.contains(mEarpieceWiredRoute); // If call supported route doesn't contain earpiece/wired/BT, it should have speaker // enabled. Otherwise, no routes would be supported for the call which should never be // the case. AudioRoute defaultRoute = mEarpieceWiredRoute != null && callSupportsEarpieceWiredRoute ? mEarpieceWiredRoute : mSpeakerDockRoute; // Ensure that we default to speaker route if we're in a video call, but disregard it if Loading Loading @@ -1136,6 +1195,14 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { } } public Set<AudioRoute> getCallSupportedRoutes() { if (mCurrentRoute.equals(mStreamingRoute)) { return mStreamingRoutes; } else { return mCallSupportedRoutes.isEmpty() ? mAvailableRoutes : mCallSupportedRoutes; } } public AudioRoute getCurrentRoute() { return mCurrentRoute; } Loading @@ -1155,7 +1222,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { if (destRoute == null || (destRoute.getBluetoothAddress() != null && !includeBluetooth)) { destRoute = getPreferredAudioRouteFromDefault(includeBluetooth, btAddressToExclude); } if (destRoute != null && !getAvailableRoutes().contains(destRoute)) { if (destRoute != null && !getCallSupportedRoutes().contains(destRoute)) { destRoute = null; } Log.i(this, "getBaseRoute - audio routing to %s", destRoute); Loading tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java +32 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import com.android.server.telecom.AudioRoute; import com.android.server.telecom.Call; import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.CallAudioRouteController; import com.android.server.telecom.CallAudioRouteStateMachine; import com.android.server.telecom.CallsManager; import com.android.server.telecom.PendingAudioRoute; import com.android.server.telecom.StatusBarNotifier; Loading Loading @@ -152,6 +153,7 @@ public class CallAudioRouteControllerTest extends TelecomTestCase { when(mCallsManager.getCurrentUserHandle()).thenReturn( new UserHandle(UserHandle.USER_SYSTEM)); when(mCallsManager.getLock()).thenReturn(mLock); when(mCallsManager.getForegroundCall()).thenReturn(mCall); when(mBluetoothRouteManager.getDeviceManager()).thenReturn(mBluetoothDeviceManager); when(mBluetoothDeviceManager.connectAudio(any(BluetoothDevice.class), anyInt())) .thenReturn(true); Loading @@ -172,6 +174,7 @@ public class CallAudioRouteControllerTest extends TelecomTestCase { mController.setCallAudioManager(mCallAudioManager); when(mCallAudioManager.getForegroundCall()).thenReturn(mCall); when(mCall.getVideoState()).thenReturn(VideoProfile.STATE_AUDIO_ONLY); when(mCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL); when(mFeatureFlags.ignoreAutoRouteToWatchDevice()).thenReturn(false); when(mFeatureFlags.useRefactoredAudioRouteSwitching()).thenReturn(true); } Loading Loading @@ -799,6 +802,35 @@ public class CallAudioRouteControllerTest extends TelecomTestCase { any(CallAudioState.class), eq(expectedState)); } @SmallTest @Test public void testUpdateRouteForForeground() { mController.initialize(); mController.sendMessageWithSessionInfo(BT_DEVICE_ADDED, AudioRoute.TYPE_BLUETOOTH_SCO, BLUETOOTH_DEVICE_1); CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH, CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_SPEAKER, BLUETOOTH_DEVICE_1, BLUETOOTH_DEVICES); mController.sendMessageWithSessionInfo(BT_ACTIVE_DEVICE_PRESENT, AudioRoute.TYPE_BLUETOOTH_SCO, BT_ADDRESS_1); verify(mCallsManager, timeout(TEST_TIMEOUT)).onCallAudioStateChanged( any(CallAudioState.class), eq(expectedState)); // Ensure that supported routes is updated along with the current route to reflect the // foreground call's supported audio routes. when(mCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_SPEAKER); mController.sendMessageWithSessionInfo( CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE); mController.sendMessageWithSessionInfo(SPEAKER_ON); expectedState = new CallAudioState(false, CallAudioState.ROUTE_SPEAKER, CallAudioState.ROUTE_SPEAKER, null, BLUETOOTH_DEVICES); verify(mCallsManager, timeout(TEST_TIMEOUT)).onCallAudioStateChanged( any(CallAudioState.class), eq(expectedState)); assertEquals(3, mController.getAvailableRoutes().size()); assertEquals(1, mController.getCallSupportedRoutes().size()); } private void verifyConnectBluetoothDevice(int audioType) { mController.initialize(); mController.setActive(true); Loading Loading
src/com/android/server/telecom/CallAudioRouteController.java +86 −19 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { private final Handler mHandler; private final WiredHeadsetManager mWiredHeadsetManager; private Set<AudioRoute> mAvailableRoutes; private Set<AudioRoute> mCallSupportedRoutes; private AudioRoute mCurrentRoute; private AudioRoute mEarpieceWiredRoute; private AudioRoute mSpeakerDockRoute; Loading @@ -104,6 +105,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { private StatusBarNotifier mStatusBarNotifier; private FeatureFlags mFeatureFlags; private int mFocusType; private int mCallSupportedRouteMask = -1; private boolean mIsScoAudioConnected; private final Object mLock = new Object(); private final TelecomSystem.SyncRoot mTelecomLock; Loading Loading @@ -314,6 +316,9 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { handleExitPendingRoute(); break; case UPDATE_SYSTEM_AUDIO_ROUTE: // Based on the available routes for foreground call, adjust routing. updateRouteForForeground(); // Force update to notify all ICS/CS. updateCallAudioState(new CallAudioState(mIsMute, mCallAudioState.getRoute(), mCallAudioState.getSupportedRouteMask(), Loading @@ -330,6 +335,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { @Override public void initialize() { mAvailableRoutes = new HashSet<>(); mCallSupportedRoutes = new HashSet<>(); mBluetoothRoutes = new LinkedHashMap<>(); mActiveDeviceCache = new HashMap<>(); mActiveDeviceCache.put(AudioRoute.TYPE_BLUETOOTH_SCO, null); Loading Loading @@ -485,7 +491,8 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { } private void routeTo(boolean active, AudioRoute destRoute) { if (!destRoute.equals(mStreamingRoute) && !getAvailableRoutes().contains(destRoute)) { if (destRoute == null || (!destRoute.equals(mStreamingRoute) && !getCallSupportedRoutes().contains(destRoute))) { Log.i(this, "Ignore routing to unavailable route: %s", destRoute); return; } Loading @@ -510,7 +517,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { Log.i(this, "Enter pending route, orig%s(active=%b), dest%s(active=%b)", mCurrentRoute, mIsActive, destRoute, active); // route to pending route if (getAvailableRoutes().contains(mCurrentRoute)) { if (getCallSupportedRoutes().contains(mCurrentRoute)) { mPendingAudioRoute.setOrigRoute(mIsActive, mCurrentRoute); } else { // Avoid waiting for pending messages for an unavailable route Loading Loading @@ -841,7 +848,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { public void handleSwitchEarpiece() { AudioRoute earpieceRoute = mTypeRoutes.get(AudioRoute.TYPE_EARPIECE); if (earpieceRoute != null && getAvailableRoutes().contains(earpieceRoute)) { if (earpieceRoute != null && getCallSupportedRoutes().contains(earpieceRoute)) { routeTo(mIsActive, earpieceRoute); } else { Log.i(this, "ignore switch earpiece request"); Loading @@ -856,7 +863,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { bluetoothRoute = getArbitraryBluetoothDevice(); bluetoothDevice = mBluetoothRoutes.get(bluetoothRoute); } else { for (AudioRoute route : getAvailableRoutes()) { for (AudioRoute route : getCallSupportedRoutes()) { if (Objects.equals(address, route.getBluetoothAddress())) { bluetoothRoute = route; bluetoothDevice = mBluetoothRoutes.get(route); Loading Loading @@ -894,7 +901,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { private void handleSwitchHeadset() { AudioRoute headsetRoute = mTypeRoutes.get(AudioRoute.TYPE_WIRED); if (headsetRoute != null && getAvailableRoutes().contains(headsetRoute)) { if (headsetRoute != null && getCallSupportedRoutes().contains(headsetRoute)) { routeTo(mIsActive, headsetRoute); } else { Log.i(this, "ignore switch headset request"); Loading @@ -902,7 +909,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { } private void handleSwitchSpeaker() { if (mSpeakerDockRoute != null && getAvailableRoutes().contains(mSpeakerDockRoute)) { if (mSpeakerDockRoute != null && getCallSupportedRoutes().contains(mSpeakerDockRoute)) { routeTo(mIsActive, mSpeakerDockRoute); } else { Log.i(this, "ignore switch speaker request"); Loading @@ -920,7 +927,8 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { // Update status bar notification if we are in a call. mStatusBarNotifier.notifySpeakerphone(mCallsManager.hasAnyCalls()); } else { if (mSpeakerDockRoute != null && getAvailableRoutes().contains(mSpeakerDockRoute)) { if (mSpeakerDockRoute != null && getCallSupportedRoutes() .contains(mSpeakerDockRoute)) { routeTo(mIsActive, mSpeakerDockRoute); // 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 Loading Loading @@ -984,7 +992,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { synchronized (mLock) { int routeMask = 0; Set<BluetoothDevice> availableBluetoothDevices = new HashSet<>(); for (AudioRoute route : getAvailableRoutes()) { for (AudioRoute route : getCallSupportedRoutes()) { routeMask |= ROUTE_MAP.get(route.getType()); if (BT_AUDIO_ROUTE_TYPES.contains(route.getType())) { BluetoothDevice deviceToAdd = mBluetoothRoutes.get(route); Loading @@ -1004,6 +1012,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { } } } updateCallAudioState(new CallAudioState(mIsMute, mCallAudioState.getRoute(), routeMask, mCallAudioState.getActiveBluetoothDevice(), availableBluetoothDevices)); } Loading @@ -1015,7 +1024,50 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { mCallAudioState.getSupportedBluetoothDevices())); } /** * Retrieves the current call's supported audio route and adjusts the audio routing if the * current route isn't supported. */ private void updateRouteForForeground() { boolean updatedRouteForCall = updateCallSupportedAudioRoutes(); // Ensure that current call audio state has updated routes for current call. if (updatedRouteForCall) { mCallAudioState = new CallAudioState(mIsMute, mCallAudioState.getRoute(), mCallSupportedRouteMask, mCallAudioState.getActiveBluetoothDevice(), mCallAudioState.getSupportedBluetoothDevices()); // Update audio route if foreground call doesn't support the current route. if ((mCallSupportedRouteMask & mCallAudioState.getRoute()) == 0) { routeTo(mIsActive, getBaseRoute(true, null)); } } } /** * Update supported audio routes for the foreground call if present. */ private boolean updateCallSupportedAudioRoutes() { int availableRouteMask = 0; Call foregroundCall = mCallsManager.getForegroundCall(); if (foregroundCall != null) { int foregroundCallSupportedRouteMask = foregroundCall.getSupportedAudioRoutes(); for (AudioRoute route : getAvailableRoutes()) { int routeType = ROUTE_MAP.get(route.getType()); availableRouteMask |= routeType; if ((routeType & foregroundCallSupportedRouteMask) == routeType) { mCallSupportedRoutes.add(route); } } mCallSupportedRouteMask = availableRouteMask & foregroundCallSupportedRouteMask; return true; } else { mCallSupportedRoutes.clear(); mCallSupportedRouteMask = -1; return false; } } private void updateCallAudioState(CallAudioState newCallAudioState) { synchronized (mTelecomLock) { Log.i(this, "updateCallAudioState: updating call audio state to %s", newCallAudioState); CallAudioState oldState = mCallAudioState; mCallAudioState = newCallAudioState; Loading @@ -1024,6 +1076,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { mCallsManager.onCallAudioStateChanged(oldState, mCallAudioState); updateAudioStateForTrackedCalls(mCallAudioState); } } private void updateAudioStateForTrackedCalls(CallAudioState newCallAudioState) { Set<Call> calls = mCallsManager.getTrackedCalls(); Loading Loading @@ -1080,11 +1133,17 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { // are only wearables available. AudioRoute activeWatchOrNonWatchDeviceRoute = getActiveWatchOrNonWatchDeviceRoute(btAddressToExclude); if (mBluetoothRoutes.isEmpty() || !includeBluetooth || activeWatchOrNonWatchDeviceRoute == null) { if ((!mCallSupportedRoutes.isEmpty() && (mCallSupportedRouteMask & CallAudioState.ROUTE_BLUETOOTH) == 0) || mBluetoothRoutes.isEmpty() || !includeBluetooth || activeWatchOrNonWatchDeviceRoute == null) { Log.i(this, "getPreferredAudioRouteFromDefault: Audio routing defaulting to " + "available non-BT route."); AudioRoute defaultRoute = mEarpieceWiredRoute != null boolean callSupportsEarpieceWiredRoute = mCallSupportedRoutes.isEmpty() || mCallSupportedRoutes.contains(mEarpieceWiredRoute); // If call supported route doesn't contain earpiece/wired/BT, it should have speaker // enabled. Otherwise, no routes would be supported for the call which should never be // the case. AudioRoute defaultRoute = mEarpieceWiredRoute != null && callSupportsEarpieceWiredRoute ? mEarpieceWiredRoute : mSpeakerDockRoute; // Ensure that we default to speaker route if we're in a video call, but disregard it if Loading Loading @@ -1136,6 +1195,14 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { } } public Set<AudioRoute> getCallSupportedRoutes() { if (mCurrentRoute.equals(mStreamingRoute)) { return mStreamingRoutes; } else { return mCallSupportedRoutes.isEmpty() ? mAvailableRoutes : mCallSupportedRoutes; } } public AudioRoute getCurrentRoute() { return mCurrentRoute; } Loading @@ -1155,7 +1222,7 @@ public class CallAudioRouteController implements CallAudioRouteAdapter { if (destRoute == null || (destRoute.getBluetoothAddress() != null && !includeBluetooth)) { destRoute = getPreferredAudioRouteFromDefault(includeBluetooth, btAddressToExclude); } if (destRoute != null && !getAvailableRoutes().contains(destRoute)) { if (destRoute != null && !getCallSupportedRoutes().contains(destRoute)) { destRoute = null; } Log.i(this, "getBaseRoute - audio routing to %s", destRoute); Loading
tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java +32 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import com.android.server.telecom.AudioRoute; import com.android.server.telecom.Call; import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.CallAudioRouteController; import com.android.server.telecom.CallAudioRouteStateMachine; import com.android.server.telecom.CallsManager; import com.android.server.telecom.PendingAudioRoute; import com.android.server.telecom.StatusBarNotifier; Loading Loading @@ -152,6 +153,7 @@ public class CallAudioRouteControllerTest extends TelecomTestCase { when(mCallsManager.getCurrentUserHandle()).thenReturn( new UserHandle(UserHandle.USER_SYSTEM)); when(mCallsManager.getLock()).thenReturn(mLock); when(mCallsManager.getForegroundCall()).thenReturn(mCall); when(mBluetoothRouteManager.getDeviceManager()).thenReturn(mBluetoothDeviceManager); when(mBluetoothDeviceManager.connectAudio(any(BluetoothDevice.class), anyInt())) .thenReturn(true); Loading @@ -172,6 +174,7 @@ public class CallAudioRouteControllerTest extends TelecomTestCase { mController.setCallAudioManager(mCallAudioManager); when(mCallAudioManager.getForegroundCall()).thenReturn(mCall); when(mCall.getVideoState()).thenReturn(VideoProfile.STATE_AUDIO_ONLY); when(mCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL); when(mFeatureFlags.ignoreAutoRouteToWatchDevice()).thenReturn(false); when(mFeatureFlags.useRefactoredAudioRouteSwitching()).thenReturn(true); } Loading Loading @@ -799,6 +802,35 @@ public class CallAudioRouteControllerTest extends TelecomTestCase { any(CallAudioState.class), eq(expectedState)); } @SmallTest @Test public void testUpdateRouteForForeground() { mController.initialize(); mController.sendMessageWithSessionInfo(BT_DEVICE_ADDED, AudioRoute.TYPE_BLUETOOTH_SCO, BLUETOOTH_DEVICE_1); CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH, CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_SPEAKER, BLUETOOTH_DEVICE_1, BLUETOOTH_DEVICES); mController.sendMessageWithSessionInfo(BT_ACTIVE_DEVICE_PRESENT, AudioRoute.TYPE_BLUETOOTH_SCO, BT_ADDRESS_1); verify(mCallsManager, timeout(TEST_TIMEOUT)).onCallAudioStateChanged( any(CallAudioState.class), eq(expectedState)); // Ensure that supported routes is updated along with the current route to reflect the // foreground call's supported audio routes. when(mCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_SPEAKER); mController.sendMessageWithSessionInfo( CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE); mController.sendMessageWithSessionInfo(SPEAKER_ON); expectedState = new CallAudioState(false, CallAudioState.ROUTE_SPEAKER, CallAudioState.ROUTE_SPEAKER, null, BLUETOOTH_DEVICES); verify(mCallsManager, timeout(TEST_TIMEOUT)).onCallAudioStateChanged( any(CallAudioState.class), eq(expectedState)); assertEquals(3, mController.getAvailableRoutes().size()); assertEquals(1, mController.getCallSupportedRoutes().size()); } private void verifyConnectBluetoothDevice(int audioType) { mController.initialize(); mController.setActive(true); Loading