Loading android/app/src/com/android/bluetooth/btservice/AudioRoutingManager.java +61 −43 Original line number Diff line number Diff line Loading @@ -51,10 +51,13 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.SynchronousResultReceiver; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.Set; public class AudioRoutingManager extends ActiveDeviceManager { Loading Loading @@ -309,8 +312,8 @@ public class AudioRoutingManager extends ActiveDeviceManager { List<BluetoothDevice> activeDevices = mActiveDevices.get(profile); if (activeDevices != null && activeDevices.contains(device)) { activeDevices.remove(device); if (activeDevices.size() == 0) { if (!setFallbackDeviceActive()) { if (activeDevices.isEmpty()) { if (!setFallbackDeviceActive(profile)) { removeActiveDevice(profile, false); } } Loading @@ -329,54 +332,70 @@ public class AudioRoutingManager extends ActiveDeviceManager { + device); } private boolean setFallbackDeviceActive() { if (DBG) { Log.d(TAG, "setFallbackDeviceActive"); } List<BluetoothDevice> candidates = new ArrayList<>(); int audioMode = mAudioManager.getMode(); for (AudioRoutingDevice routingDevice : mConnectedDevices.values()) { for (int profile : routingDevice.connectedProfiles) { if (audioMode == AudioManager.MODE_NORMAL) { if (profile != BluetoothProfile.HEADSET) { candidates.add(routingDevice.device); private Optional<BluetoothDevice> getFallbackDevice( Collection<AudioRoutingDevice> candidates) { List<BluetoothDevice> activatableDevices = new ArrayList<>(); for (AudioRoutingDevice d : candidates) { if (d.isA2dpOnly() || d.isHfpOnly()) continue; boolean canActivate = true; for (int p : d.connectedProfiles) { if (!d.canActivateNow(p)) { canActivate = false; break; } else if (p != BluetoothProfile.A2DP && p != BluetoothProfile.HEADSET) { break; } } if (canActivate) { activatableDevices.add(d.device); } } return Optional.ofNullable( mDbManager.getMostRecentlyConnectedDevicesInList(activatableDevices)); } private boolean setFallbackDeviceActive(int profile) { if (DBG) { Log.d(TAG, "setFallbackDeviceActive: " + BluetoothProfile.getProfileName(profile)); } // 1. Activate the lastly activated device among currently activated devices. Set<AudioRoutingDevice> candidates = new HashSet<>(); for (int i = 0; i < mActiveDevices.size(); ++i) { for (BluetoothDevice d : mActiveDevices.valueAt(i)) { candidates.add(getAudioRoutingDevice(d)); } } try { // 2. Activate the lastly activated device for the profile Optional<BluetoothDevice> fallbackDevice = getFallbackDevice(candidates) .or(() -> getFallbackDevice(mConnectedDevices.values())); AudioRoutingDevice fallbackRoutingDevice = getAudioRoutingDevice(fallbackDevice.get()); int profileToActivate = profile; if (!fallbackRoutingDevice.canActivateNow(profile)) { // if it can't activate the given profile, try LE_AUDIO if (fallbackRoutingDevice.canActivateNow(BluetoothProfile.LE_AUDIO)) { profileToActivate = BluetoothProfile.LE_AUDIO; } else { if (profile != BluetoothProfile.A2DP) { candidates.add(routingDevice.device); // if it can't activate both the given profile and LE_AUDIO, select any for (int p : fallbackRoutingDevice.connectedProfiles) { if (fallbackRoutingDevice.canActivateNow(p)) { profileToActivate = p; break; } } } } AudioRoutingDevice deviceToActivate = null; BluetoothDevice device = mDbManager.getMostRecentlyConnectedDevicesInList(candidates); if (device != null) { deviceToActivate = getAudioRoutingDevice(device); } if (deviceToActivate != null) { return activateDeviceProfile(fallbackRoutingDevice, profileToActivate); } catch (NoSuchElementException e) { // Thrown when no available fallback devices found if (DBG) { Log.d(TAG, "activateDevice: device=" + deviceToActivate.device); } // Try to activate hearing aid and LE audio first if (deviceToActivate.connectedProfiles.contains(BluetoothProfile.HEARING_AID)) { return activateDeviceProfile(deviceToActivate, BluetoothProfile.HEARING_AID); } else if (deviceToActivate.connectedProfiles.contains(BluetoothProfile.LE_AUDIO)) { return activateDeviceProfile(deviceToActivate, BluetoothProfile.LE_AUDIO); } else if (deviceToActivate.connectedProfiles.contains(BluetoothProfile.A2DP)) { return activateDeviceProfile(deviceToActivate, BluetoothProfile.A2DP); } else if (deviceToActivate.connectedProfiles.contains(BluetoothProfile.HEADSET)) { return activateDeviceProfile(deviceToActivate, BluetoothProfile.HEADSET); } Log.w( TAG, "Fail to activate the device: " + deviceToActivate.device + ", no connected audio profiles"); Log.d(TAG, "Found no available BT fallback devices."); } return false; } } // TODO: handle the connection policy change events. private AudioRoutingDevice getAudioRoutingDevice(@NonNull BluetoothDevice device) { Loading Loading @@ -660,7 +679,7 @@ public class AudioRoutingManager extends ActiveDeviceManager { for (int p : connectedDevice.supportedProfiles) { if (!getActiveDevices(p).isEmpty()) { BluetoothMethodProxy mp = BluetoothMethodProxy.getInstance(); if (mp.mediaSessionManagerGetActiveSessions(mSessionManager).size() > 0 if (!mp.mediaSessionManagerGetActiveSessions(mSessionManager).isEmpty() || mAudioManager.getMode() == AudioManager.MODE_IN_CALL) { Log.i( TAG, Loading Loading @@ -733,7 +752,6 @@ public class AudioRoutingManager extends ActiveDeviceManager { public boolean canActivateNow(int profile) { if (!connectedProfiles.contains(profile)) return false; // TODO: Return false if there are another active remote streaming an audio. return switch (profile) { case BluetoothProfile.HEADSET -> !supportedProfiles.contains( BluetoothProfile.A2DP) Loading android/app/tests/unit/src/com/android/bluetooth/btservice/AudioRoutingManagerTest.java +55 −27 Original line number Diff line number Diff line Loading @@ -250,25 +250,26 @@ public class AudioRoutingManagerTest { } /** * Two A2DP devices are connected and the current active is then disconnected. Should then set * active device to fallback device. * A2DP Headset and A2DP only devices are connected and the current activated A2DP only is then * disconnected. Should then set active device to fallback device. */ @Test public void a2dpSecondDeviceDisconnected_fallbackDeviceActive() { public void a2dpDeviceDisconnected_fallbackA2dpHeadset() { a2dpConnected(mA2dpHeadsetDevice, true); headsetConnected(mA2dpHeadsetDevice, true); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mA2dpHeadsetDevice); verify(mHeadsetService).setActiveDevice(mA2dpHeadsetDevice); a2dpConnected(mA2dpDevice, false); switchA2dpActiveDevice(mA2dpDevice); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mA2dpDevice); a2dpConnected(mSecondaryAudioDevice, false); switchA2dpActiveDevice(mSecondaryAudioDevice); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mSecondaryAudioDevice); Mockito.clearInvocations(mA2dpService); a2dpDisconnected(mSecondaryAudioDevice); Mockito.clearInvocations(mA2dpService, mHeadsetService); a2dpDisconnected(mA2dpDevice); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mA2dpDevice); verify(mA2dpService).setActiveDevice(mA2dpHeadsetDevice); } /** One Headset is connected. */ Loading Loading @@ -323,11 +324,11 @@ public class AudioRoutingManagerTest { } /** * Two Headsets are connected and the current active is then disconnected. Should then set * active device to fallback device. * Two Headset only devices are connected and the current active is then disconnected. Then it * should be fallback to phone. */ @Test public void headsetSecondDeviceDisconnected_fallbackDeviceActive() { public void headsetSecondDeviceDisconnected_fallbackToPhone() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); headsetConnected(mHeadsetDevice, false); Loading @@ -343,27 +344,28 @@ public class AudioRoutingManagerTest { Mockito.clearInvocations(mHeadsetService); headsetDisconnected(mSecondaryAudioDevice); mTestLooper.dispatchAll(); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); verify(mHeadsetService, never()).setActiveDevice(mHeadsetDevice); } @Test public void headsetSecondDeviceDisconnected_fallbackDeviceActiveWhileRinging() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE); headsetConnected(mA2dpHeadsetDevice, true); a2dpConnected(mA2dpHeadsetDevice, true); mTestLooper.dispatchAll(); verify(mHeadsetService).setActiveDevice(mA2dpHeadsetDevice); verify(mA2dpService).setActiveDevice(mA2dpHeadsetDevice); headsetConnected(mHeadsetDevice, false); switchHeadsetActiveDevice(mHeadsetDevice); mTestLooper.dispatchAll(); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); headsetConnected(mSecondaryAudioDevice, false); switchHeadsetActiveDevice(mSecondaryAudioDevice); mTestLooper.dispatchAll(); verify(mHeadsetService).setActiveDevice(mSecondaryAudioDevice); Mockito.clearInvocations(mHeadsetService); headsetDisconnected(mSecondaryAudioDevice); headsetDisconnected(mHeadsetDevice); mTestLooper.dispatchAll(); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); verify(mHeadsetService).setActiveDevice(mA2dpHeadsetDevice); } @Test Loading Loading @@ -842,11 +844,11 @@ public class AudioRoutingManagerTest { } /** * An A2DP connected. An LE Audio connected. The LE Audio disconnected. Then the A2DP should be * the active one. * An A2DP only device connected. An LE Audio connected. The LE Audio disconnected. Then it * should be fallback to phone instead of the A2DP only device. */ @Test public void a2dpAndLeAudioConnectedThenLeAudioDisconnected_fallbackToA2dp() { public void a2dpAndLeAudioConnectedThenLeAudioDisconnected_fallbackToPhone() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL); a2dpConnected(mA2dpDevice, false); Loading @@ -861,8 +863,34 @@ public class AudioRoutingManagerTest { Mockito.clearInvocations(mA2dpService); leAudioDisconnected(mLeAudioDevice); mTestLooper.dispatchAll(); verify(mLeAudioService).removeActiveDevice(false); verify(mA2dpService, never()).setActiveDevice(mA2dpDevice); } /** * An A2DP headset connected. An LE Audio connected. The LE Audio disconnected. Then the A2DP * headset should be the active one. */ @Test public void a2dpHeadsetAndLeAudioConnectedThenLeAudioDisconnected_fallbackToA2dpHeadset() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL); a2dpConnected(mHeadsetDevice, true); headsetConnected(mHeadsetDevice, true); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mHeadsetDevice); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); leAudioConnected(mLeAudioDevice); mTestLooper.dispatchAll(); verify(mLeAudioService).setActiveDevice(mLeAudioDevice); Mockito.clearInvocations(mA2dpService, mHeadsetService); leAudioDisconnected(mLeAudioDevice); mTestLooper.dispatchAll(); verify(mLeAudioService).removeActiveDevice(true); verify(mA2dpService).setActiveDevice(mA2dpDevice); verify(mA2dpService).setActiveDevice(mHeadsetDevice); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); } /** Loading Loading @@ -920,7 +948,7 @@ public class AudioRoutingManagerTest { Mockito.clearInvocations(mHearingAidService, mA2dpService, mLeAudioService); leAudioDisconnected(mLeAudioDevice); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mA2dpDevice); verify(mHearingAidService).setActiveDevice(mHearingAidDevice); verify(mLeAudioService).removeActiveDevice(true); } Loading Loading
android/app/src/com/android/bluetooth/btservice/AudioRoutingManager.java +61 −43 Original line number Diff line number Diff line Loading @@ -51,10 +51,13 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.SynchronousResultReceiver; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.Set; public class AudioRoutingManager extends ActiveDeviceManager { Loading Loading @@ -309,8 +312,8 @@ public class AudioRoutingManager extends ActiveDeviceManager { List<BluetoothDevice> activeDevices = mActiveDevices.get(profile); if (activeDevices != null && activeDevices.contains(device)) { activeDevices.remove(device); if (activeDevices.size() == 0) { if (!setFallbackDeviceActive()) { if (activeDevices.isEmpty()) { if (!setFallbackDeviceActive(profile)) { removeActiveDevice(profile, false); } } Loading @@ -329,54 +332,70 @@ public class AudioRoutingManager extends ActiveDeviceManager { + device); } private boolean setFallbackDeviceActive() { if (DBG) { Log.d(TAG, "setFallbackDeviceActive"); } List<BluetoothDevice> candidates = new ArrayList<>(); int audioMode = mAudioManager.getMode(); for (AudioRoutingDevice routingDevice : mConnectedDevices.values()) { for (int profile : routingDevice.connectedProfiles) { if (audioMode == AudioManager.MODE_NORMAL) { if (profile != BluetoothProfile.HEADSET) { candidates.add(routingDevice.device); private Optional<BluetoothDevice> getFallbackDevice( Collection<AudioRoutingDevice> candidates) { List<BluetoothDevice> activatableDevices = new ArrayList<>(); for (AudioRoutingDevice d : candidates) { if (d.isA2dpOnly() || d.isHfpOnly()) continue; boolean canActivate = true; for (int p : d.connectedProfiles) { if (!d.canActivateNow(p)) { canActivate = false; break; } else if (p != BluetoothProfile.A2DP && p != BluetoothProfile.HEADSET) { break; } } if (canActivate) { activatableDevices.add(d.device); } } return Optional.ofNullable( mDbManager.getMostRecentlyConnectedDevicesInList(activatableDevices)); } private boolean setFallbackDeviceActive(int profile) { if (DBG) { Log.d(TAG, "setFallbackDeviceActive: " + BluetoothProfile.getProfileName(profile)); } // 1. Activate the lastly activated device among currently activated devices. Set<AudioRoutingDevice> candidates = new HashSet<>(); for (int i = 0; i < mActiveDevices.size(); ++i) { for (BluetoothDevice d : mActiveDevices.valueAt(i)) { candidates.add(getAudioRoutingDevice(d)); } } try { // 2. Activate the lastly activated device for the profile Optional<BluetoothDevice> fallbackDevice = getFallbackDevice(candidates) .or(() -> getFallbackDevice(mConnectedDevices.values())); AudioRoutingDevice fallbackRoutingDevice = getAudioRoutingDevice(fallbackDevice.get()); int profileToActivate = profile; if (!fallbackRoutingDevice.canActivateNow(profile)) { // if it can't activate the given profile, try LE_AUDIO if (fallbackRoutingDevice.canActivateNow(BluetoothProfile.LE_AUDIO)) { profileToActivate = BluetoothProfile.LE_AUDIO; } else { if (profile != BluetoothProfile.A2DP) { candidates.add(routingDevice.device); // if it can't activate both the given profile and LE_AUDIO, select any for (int p : fallbackRoutingDevice.connectedProfiles) { if (fallbackRoutingDevice.canActivateNow(p)) { profileToActivate = p; break; } } } } AudioRoutingDevice deviceToActivate = null; BluetoothDevice device = mDbManager.getMostRecentlyConnectedDevicesInList(candidates); if (device != null) { deviceToActivate = getAudioRoutingDevice(device); } if (deviceToActivate != null) { return activateDeviceProfile(fallbackRoutingDevice, profileToActivate); } catch (NoSuchElementException e) { // Thrown when no available fallback devices found if (DBG) { Log.d(TAG, "activateDevice: device=" + deviceToActivate.device); } // Try to activate hearing aid and LE audio first if (deviceToActivate.connectedProfiles.contains(BluetoothProfile.HEARING_AID)) { return activateDeviceProfile(deviceToActivate, BluetoothProfile.HEARING_AID); } else if (deviceToActivate.connectedProfiles.contains(BluetoothProfile.LE_AUDIO)) { return activateDeviceProfile(deviceToActivate, BluetoothProfile.LE_AUDIO); } else if (deviceToActivate.connectedProfiles.contains(BluetoothProfile.A2DP)) { return activateDeviceProfile(deviceToActivate, BluetoothProfile.A2DP); } else if (deviceToActivate.connectedProfiles.contains(BluetoothProfile.HEADSET)) { return activateDeviceProfile(deviceToActivate, BluetoothProfile.HEADSET); } Log.w( TAG, "Fail to activate the device: " + deviceToActivate.device + ", no connected audio profiles"); Log.d(TAG, "Found no available BT fallback devices."); } return false; } } // TODO: handle the connection policy change events. private AudioRoutingDevice getAudioRoutingDevice(@NonNull BluetoothDevice device) { Loading Loading @@ -660,7 +679,7 @@ public class AudioRoutingManager extends ActiveDeviceManager { for (int p : connectedDevice.supportedProfiles) { if (!getActiveDevices(p).isEmpty()) { BluetoothMethodProxy mp = BluetoothMethodProxy.getInstance(); if (mp.mediaSessionManagerGetActiveSessions(mSessionManager).size() > 0 if (!mp.mediaSessionManagerGetActiveSessions(mSessionManager).isEmpty() || mAudioManager.getMode() == AudioManager.MODE_IN_CALL) { Log.i( TAG, Loading Loading @@ -733,7 +752,6 @@ public class AudioRoutingManager extends ActiveDeviceManager { public boolean canActivateNow(int profile) { if (!connectedProfiles.contains(profile)) return false; // TODO: Return false if there are another active remote streaming an audio. return switch (profile) { case BluetoothProfile.HEADSET -> !supportedProfiles.contains( BluetoothProfile.A2DP) Loading
android/app/tests/unit/src/com/android/bluetooth/btservice/AudioRoutingManagerTest.java +55 −27 Original line number Diff line number Diff line Loading @@ -250,25 +250,26 @@ public class AudioRoutingManagerTest { } /** * Two A2DP devices are connected and the current active is then disconnected. Should then set * active device to fallback device. * A2DP Headset and A2DP only devices are connected and the current activated A2DP only is then * disconnected. Should then set active device to fallback device. */ @Test public void a2dpSecondDeviceDisconnected_fallbackDeviceActive() { public void a2dpDeviceDisconnected_fallbackA2dpHeadset() { a2dpConnected(mA2dpHeadsetDevice, true); headsetConnected(mA2dpHeadsetDevice, true); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mA2dpHeadsetDevice); verify(mHeadsetService).setActiveDevice(mA2dpHeadsetDevice); a2dpConnected(mA2dpDevice, false); switchA2dpActiveDevice(mA2dpDevice); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mA2dpDevice); a2dpConnected(mSecondaryAudioDevice, false); switchA2dpActiveDevice(mSecondaryAudioDevice); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mSecondaryAudioDevice); Mockito.clearInvocations(mA2dpService); a2dpDisconnected(mSecondaryAudioDevice); Mockito.clearInvocations(mA2dpService, mHeadsetService); a2dpDisconnected(mA2dpDevice); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mA2dpDevice); verify(mA2dpService).setActiveDevice(mA2dpHeadsetDevice); } /** One Headset is connected. */ Loading Loading @@ -323,11 +324,11 @@ public class AudioRoutingManagerTest { } /** * Two Headsets are connected and the current active is then disconnected. Should then set * active device to fallback device. * Two Headset only devices are connected and the current active is then disconnected. Then it * should be fallback to phone. */ @Test public void headsetSecondDeviceDisconnected_fallbackDeviceActive() { public void headsetSecondDeviceDisconnected_fallbackToPhone() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); headsetConnected(mHeadsetDevice, false); Loading @@ -343,27 +344,28 @@ public class AudioRoutingManagerTest { Mockito.clearInvocations(mHeadsetService); headsetDisconnected(mSecondaryAudioDevice); mTestLooper.dispatchAll(); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); verify(mHeadsetService, never()).setActiveDevice(mHeadsetDevice); } @Test public void headsetSecondDeviceDisconnected_fallbackDeviceActiveWhileRinging() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE); headsetConnected(mA2dpHeadsetDevice, true); a2dpConnected(mA2dpHeadsetDevice, true); mTestLooper.dispatchAll(); verify(mHeadsetService).setActiveDevice(mA2dpHeadsetDevice); verify(mA2dpService).setActiveDevice(mA2dpHeadsetDevice); headsetConnected(mHeadsetDevice, false); switchHeadsetActiveDevice(mHeadsetDevice); mTestLooper.dispatchAll(); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); headsetConnected(mSecondaryAudioDevice, false); switchHeadsetActiveDevice(mSecondaryAudioDevice); mTestLooper.dispatchAll(); verify(mHeadsetService).setActiveDevice(mSecondaryAudioDevice); Mockito.clearInvocations(mHeadsetService); headsetDisconnected(mSecondaryAudioDevice); headsetDisconnected(mHeadsetDevice); mTestLooper.dispatchAll(); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); verify(mHeadsetService).setActiveDevice(mA2dpHeadsetDevice); } @Test Loading Loading @@ -842,11 +844,11 @@ public class AudioRoutingManagerTest { } /** * An A2DP connected. An LE Audio connected. The LE Audio disconnected. Then the A2DP should be * the active one. * An A2DP only device connected. An LE Audio connected. The LE Audio disconnected. Then it * should be fallback to phone instead of the A2DP only device. */ @Test public void a2dpAndLeAudioConnectedThenLeAudioDisconnected_fallbackToA2dp() { public void a2dpAndLeAudioConnectedThenLeAudioDisconnected_fallbackToPhone() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL); a2dpConnected(mA2dpDevice, false); Loading @@ -861,8 +863,34 @@ public class AudioRoutingManagerTest { Mockito.clearInvocations(mA2dpService); leAudioDisconnected(mLeAudioDevice); mTestLooper.dispatchAll(); verify(mLeAudioService).removeActiveDevice(false); verify(mA2dpService, never()).setActiveDevice(mA2dpDevice); } /** * An A2DP headset connected. An LE Audio connected. The LE Audio disconnected. Then the A2DP * headset should be the active one. */ @Test public void a2dpHeadsetAndLeAudioConnectedThenLeAudioDisconnected_fallbackToA2dpHeadset() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL); a2dpConnected(mHeadsetDevice, true); headsetConnected(mHeadsetDevice, true); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mHeadsetDevice); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); leAudioConnected(mLeAudioDevice); mTestLooper.dispatchAll(); verify(mLeAudioService).setActiveDevice(mLeAudioDevice); Mockito.clearInvocations(mA2dpService, mHeadsetService); leAudioDisconnected(mLeAudioDevice); mTestLooper.dispatchAll(); verify(mLeAudioService).removeActiveDevice(true); verify(mA2dpService).setActiveDevice(mA2dpDevice); verify(mA2dpService).setActiveDevice(mHeadsetDevice); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); } /** Loading Loading @@ -920,7 +948,7 @@ public class AudioRoutingManagerTest { Mockito.clearInvocations(mHearingAidService, mA2dpService, mLeAudioService); leAudioDisconnected(mLeAudioDevice); mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mA2dpDevice); verify(mHearingAidService).setActiveDevice(mHearingAidDevice); verify(mLeAudioService).removeActiveDevice(true); } Loading