Loading src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java +36 −7 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; Loading Loading @@ -134,7 +135,8 @@ public class BluetoothRouteManager extends StateMachine { @Override public void enter() { BluetoothDevice erroneouslyConnectedDevice = getBluetoothAudioConnectedDevice(); if (erroneouslyConnectedDevice != null) { if (erroneouslyConnectedDevice != null && !erroneouslyConnectedDevice.equals(mHearingAidActiveDeviceCache)) { Log.w(LOG_TAG, "Entering AudioOff state but device %s appears to be connected. " + "Switching to audio-on state for that device.", erroneouslyConnectedDevice); // change this to just transition to the new audio on state Loading Loading @@ -252,6 +254,27 @@ public class BluetoothRouteManager extends StateMachine { SomeArgs args = (SomeArgs) msg.obj; String address = (String) args.arg2; boolean switchingBtDevices = !Objects.equals(mDeviceAddress, address); if (switchingBtDevices == true) { // check if it is an hearing aid pair BluetoothAdapter bluetoothAdapter = mDeviceManager.getBluetoothAdapter(); if (bluetoothAdapter != null) { List<BluetoothDevice> activeHearingAids = bluetoothAdapter.getActiveDevices(BluetoothProfile.HEARING_AID); for (BluetoothDevice hearingAid : activeHearingAids) { if (hearingAid != null) { String hearingAidAddress = hearingAid.getAddress(); if (hearingAidAddress != null) { if (hearingAidAddress.equals(address) || hearingAidAddress.equals(mDeviceAddress)) { switchingBtDevices = false; break; } } } } } } try { switch (msg.what) { case NEW_DEVICE_CONNECTED: Loading Loading @@ -868,8 +891,13 @@ public class BluetoothRouteManager extends StateMachine { : mDeviceManager.isHearingAidSetAsCommunicationDevice(); if (bluetoothHearingAid != null) { if (isHearingAidSetForCommunication) { for (BluetoothDevice device : bluetoothAdapter.getActiveDevices( BluetoothProfile.HEARING_AID)) { List<BluetoothDevice> hearingAidsActiveDevices = bluetoothAdapter.getActiveDevices( BluetoothProfile.HEARING_AID); if (hearingAidsActiveDevices.contains(mHearingAidActiveDeviceCache)) { hearingAidActiveDevice = mHearingAidActiveDeviceCache; activeDevices++; } else { for (BluetoothDevice device : hearingAidsActiveDevices) { if (device != null) { hearingAidActiveDevice = device; activeDevices++; Loading @@ -878,6 +906,7 @@ public class BluetoothRouteManager extends StateMachine { } } } } boolean isLeAudioSetForCommunication = mFeatureFlags.callAudioCommunicationDeviceRefactor() Loading tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java +75 −11 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; Loading @@ -37,6 +38,8 @@ import android.os.Parcel; import android.telecom.Log; import android.test.suitebuilder.annotation.SmallTest; import android.media.AudioDeviceInfo; import com.android.internal.os.SomeArgs; import com.android.server.telecom.CallAudioCommunicationDeviceTracker; import com.android.server.telecom.TelecomSystem; Loading @@ -62,7 +65,14 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { static final BluetoothDevice DEVICE1 = makeBluetoothDevice("00:00:00:00:00:01"); static final BluetoothDevice DEVICE2 = makeBluetoothDevice("00:00:00:00:00:02"); static final BluetoothDevice DEVICE3 = makeBluetoothDevice("00:00:00:00:00:03"); static final BluetoothDevice HEARING_AID_DEVICE = makeBluetoothDevice("00:00:00:00:00:04"); static final BluetoothDevice HEARING_AID_DEVICE_LEFT = makeBluetoothDevice("CA:FE:DE:CA:00:01"); static final BluetoothDevice HEARING_AID_DEVICE_RIGHT = makeBluetoothDevice("CA:FE:DE:CA:00:02"); // See HearingAidService#getActiveDevices // Note: It is really important that the left HA is the first one. The left HA is always // in the first index (0) and the right one in the second index (1). static final BluetoothDevice[] HEARING_AIDS = new BluetoothDevice[]{HEARING_AID_DEVICE_LEFT, HEARING_AID_DEVICE_RIGHT}; @Mock private BluetoothAdapter mBluetoothAdapter; @Mock private BluetoothDeviceManager mDeviceManager; Loading @@ -85,6 +95,59 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { super.tearDown(); } @SmallTest @Test public void testConnectLeftHearingAidWhenLeftIsActive() { BluetoothRouteManager sm = setupStateMachine( BluetoothRouteManager.AUDIO_OFF_STATE_NAME, HEARING_AID_DEVICE_LEFT); sm.onActiveDeviceChanged(HEARING_AID_DEVICE_LEFT, BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID); when(mDeviceManager.connectAudio(anyString(), anyBoolean())).thenReturn(true); when(mDeviceManager.isHearingAidSetAsCommunicationDevice()).thenReturn(true); setupConnectedDevices(null, HEARING_AIDS, null, null, HEARING_AIDS, null); when(mBluetoothHeadset.getAudioState(nullable(BluetoothDevice.class))) .thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED); executeRoutingAction(sm, BluetoothRouteManager.NEW_DEVICE_CONNECTED, HEARING_AID_DEVICE_LEFT.getAddress()); executeRoutingAction(sm, BluetoothRouteManager.CONNECT_BT, HEARING_AID_DEVICE_LEFT.getAddress()); assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX + ":" + HEARING_AID_DEVICE_LEFT.getAddress(), sm.getCurrentState().getName()); sm.quitNow(); } @SmallTest @Test public void testConnectRightHearingAidWhenLeftIsActive() { BluetoothRouteManager sm = setupStateMachine( BluetoothRouteManager.AUDIO_OFF_STATE_NAME, HEARING_AID_DEVICE_RIGHT); sm.onActiveDeviceChanged(HEARING_AID_DEVICE_LEFT, BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID); when(mDeviceManager.connectAudio(anyString(), anyBoolean())).thenReturn(true); when(mDeviceManager.isHearingAidSetAsCommunicationDevice()).thenReturn(true); setupConnectedDevices(null, HEARING_AIDS, null, null, HEARING_AIDS, null); when(mBluetoothHeadset.getAudioState(nullable(BluetoothDevice.class))) .thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED); executeRoutingAction(sm, BluetoothRouteManager.NEW_DEVICE_CONNECTED, HEARING_AID_DEVICE_LEFT.getAddress()); executeRoutingAction(sm, BluetoothRouteManager.CONNECT_BT, HEARING_AID_DEVICE_LEFT.getAddress()); assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX + ":" + HEARING_AID_DEVICE_LEFT.getAddress(), sm.getCurrentState().getName()); sm.quitNow(); } @SmallTest @Test public void testConnectBtRetryWhileNotConnected() { Loading Loading @@ -113,15 +176,15 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { BluetoothRouteManager sm = setupStateMachine( BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, DEVICE1); setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, new BluetoothDevice[]{HEARING_AID_DEVICE}, new BluetoothDevice[]{DEVICE2}, DEVICE1, HEARING_AID_DEVICE, DEVICE2); HEARING_AIDS, new BluetoothDevice[]{DEVICE2}, DEVICE1, HEARING_AIDS, DEVICE2); sm.onActiveDeviceChanged(DEVICE1, BluetoothDeviceManager.DEVICE_TYPE_HEADSET); sm.onActiveDeviceChanged(DEVICE2, BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO); sm.onActiveDeviceChanged(HEARING_AID_DEVICE, sm.onActiveDeviceChanged(HEARING_AID_DEVICE_LEFT, BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID); executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST, DEVICE1.getAddress()); verifyConnectionAttempt(HEARING_AID_DEVICE, 0); verifyConnectionAttempt(HEARING_AID_DEVICE_LEFT, 0); verifyConnectionAttempt(DEVICE1, 0); verifyConnectionAttempt(DEVICE2, 0); assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX Loading Loading @@ -176,11 +239,11 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { @Test public void testSkipInactiveBtDeviceWhenEvaluateActualState() { BluetoothRouteManager sm = setupStateMachine( BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, HEARING_AID_DEVICE); setupConnectedDevices(null, new BluetoothDevice[]{HEARING_AID_DEVICE}, null, null, HEARING_AID_DEVICE, null); BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, HEARING_AID_DEVICE_LEFT); setupConnectedDevices(null, HEARING_AIDS, null, null, HEARING_AIDS, null); executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST, HEARING_AID_DEVICE.getAddress()); HEARING_AID_DEVICE_LEFT.getAddress()); assertEquals(BluetoothRouteManager.AUDIO_OFF_STATE_NAME, sm.getCurrentState().getName()); sm.quitNow(); } Loading Loading @@ -227,10 +290,11 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { private void setupConnectedDevices(BluetoothDevice[] hfpDevices, BluetoothDevice[] hearingAidDevices, BluetoothDevice[] leAudioDevices, BluetoothDevice hfpActiveDevice, BluetoothDevice hearingAidActiveDevice, BluetoothDevice hfpActiveDevice, BluetoothDevice[] hearingAidActiveDevices, BluetoothDevice leAudioDevice) { if (hfpDevices == null) hfpDevices = new BluetoothDevice[]{}; if (hearingAidDevices == null) hearingAidDevices = new BluetoothDevice[]{}; if (hearingAidActiveDevices == null) hearingAidActiveDevices = new BluetoothDevice[]{}; if (leAudioDevice == null) leAudioDevices = new BluetoothDevice[]{}; when(mDeviceManager.getNumConnectedDevices()).thenReturn( Loading @@ -249,7 +313,7 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { when(mBluetoothHearingAid.getConnectedDevices()) .thenReturn(Arrays.asList(hearingAidDevices)); when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEARING_AID))) .thenReturn(Arrays.asList(hearingAidActiveDevice, null)); .thenReturn(Arrays.asList(hearingAidActiveDevices)); when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.LE_AUDIO))) .thenReturn(Arrays.asList(leAudioDevice, null)); } Loading Loading
src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java +36 −7 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; Loading Loading @@ -134,7 +135,8 @@ public class BluetoothRouteManager extends StateMachine { @Override public void enter() { BluetoothDevice erroneouslyConnectedDevice = getBluetoothAudioConnectedDevice(); if (erroneouslyConnectedDevice != null) { if (erroneouslyConnectedDevice != null && !erroneouslyConnectedDevice.equals(mHearingAidActiveDeviceCache)) { Log.w(LOG_TAG, "Entering AudioOff state but device %s appears to be connected. " + "Switching to audio-on state for that device.", erroneouslyConnectedDevice); // change this to just transition to the new audio on state Loading Loading @@ -252,6 +254,27 @@ public class BluetoothRouteManager extends StateMachine { SomeArgs args = (SomeArgs) msg.obj; String address = (String) args.arg2; boolean switchingBtDevices = !Objects.equals(mDeviceAddress, address); if (switchingBtDevices == true) { // check if it is an hearing aid pair BluetoothAdapter bluetoothAdapter = mDeviceManager.getBluetoothAdapter(); if (bluetoothAdapter != null) { List<BluetoothDevice> activeHearingAids = bluetoothAdapter.getActiveDevices(BluetoothProfile.HEARING_AID); for (BluetoothDevice hearingAid : activeHearingAids) { if (hearingAid != null) { String hearingAidAddress = hearingAid.getAddress(); if (hearingAidAddress != null) { if (hearingAidAddress.equals(address) || hearingAidAddress.equals(mDeviceAddress)) { switchingBtDevices = false; break; } } } } } } try { switch (msg.what) { case NEW_DEVICE_CONNECTED: Loading Loading @@ -868,8 +891,13 @@ public class BluetoothRouteManager extends StateMachine { : mDeviceManager.isHearingAidSetAsCommunicationDevice(); if (bluetoothHearingAid != null) { if (isHearingAidSetForCommunication) { for (BluetoothDevice device : bluetoothAdapter.getActiveDevices( BluetoothProfile.HEARING_AID)) { List<BluetoothDevice> hearingAidsActiveDevices = bluetoothAdapter.getActiveDevices( BluetoothProfile.HEARING_AID); if (hearingAidsActiveDevices.contains(mHearingAidActiveDeviceCache)) { hearingAidActiveDevice = mHearingAidActiveDeviceCache; activeDevices++; } else { for (BluetoothDevice device : hearingAidsActiveDevices) { if (device != null) { hearingAidActiveDevice = device; activeDevices++; Loading @@ -878,6 +906,7 @@ public class BluetoothRouteManager extends StateMachine { } } } } boolean isLeAudioSetForCommunication = mFeatureFlags.callAudioCommunicationDeviceRefactor() Loading
tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java +75 −11 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; Loading @@ -37,6 +38,8 @@ import android.os.Parcel; import android.telecom.Log; import android.test.suitebuilder.annotation.SmallTest; import android.media.AudioDeviceInfo; import com.android.internal.os.SomeArgs; import com.android.server.telecom.CallAudioCommunicationDeviceTracker; import com.android.server.telecom.TelecomSystem; Loading @@ -62,7 +65,14 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { static final BluetoothDevice DEVICE1 = makeBluetoothDevice("00:00:00:00:00:01"); static final BluetoothDevice DEVICE2 = makeBluetoothDevice("00:00:00:00:00:02"); static final BluetoothDevice DEVICE3 = makeBluetoothDevice("00:00:00:00:00:03"); static final BluetoothDevice HEARING_AID_DEVICE = makeBluetoothDevice("00:00:00:00:00:04"); static final BluetoothDevice HEARING_AID_DEVICE_LEFT = makeBluetoothDevice("CA:FE:DE:CA:00:01"); static final BluetoothDevice HEARING_AID_DEVICE_RIGHT = makeBluetoothDevice("CA:FE:DE:CA:00:02"); // See HearingAidService#getActiveDevices // Note: It is really important that the left HA is the first one. The left HA is always // in the first index (0) and the right one in the second index (1). static final BluetoothDevice[] HEARING_AIDS = new BluetoothDevice[]{HEARING_AID_DEVICE_LEFT, HEARING_AID_DEVICE_RIGHT}; @Mock private BluetoothAdapter mBluetoothAdapter; @Mock private BluetoothDeviceManager mDeviceManager; Loading @@ -85,6 +95,59 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { super.tearDown(); } @SmallTest @Test public void testConnectLeftHearingAidWhenLeftIsActive() { BluetoothRouteManager sm = setupStateMachine( BluetoothRouteManager.AUDIO_OFF_STATE_NAME, HEARING_AID_DEVICE_LEFT); sm.onActiveDeviceChanged(HEARING_AID_DEVICE_LEFT, BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID); when(mDeviceManager.connectAudio(anyString(), anyBoolean())).thenReturn(true); when(mDeviceManager.isHearingAidSetAsCommunicationDevice()).thenReturn(true); setupConnectedDevices(null, HEARING_AIDS, null, null, HEARING_AIDS, null); when(mBluetoothHeadset.getAudioState(nullable(BluetoothDevice.class))) .thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED); executeRoutingAction(sm, BluetoothRouteManager.NEW_DEVICE_CONNECTED, HEARING_AID_DEVICE_LEFT.getAddress()); executeRoutingAction(sm, BluetoothRouteManager.CONNECT_BT, HEARING_AID_DEVICE_LEFT.getAddress()); assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX + ":" + HEARING_AID_DEVICE_LEFT.getAddress(), sm.getCurrentState().getName()); sm.quitNow(); } @SmallTest @Test public void testConnectRightHearingAidWhenLeftIsActive() { BluetoothRouteManager sm = setupStateMachine( BluetoothRouteManager.AUDIO_OFF_STATE_NAME, HEARING_AID_DEVICE_RIGHT); sm.onActiveDeviceChanged(HEARING_AID_DEVICE_LEFT, BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID); when(mDeviceManager.connectAudio(anyString(), anyBoolean())).thenReturn(true); when(mDeviceManager.isHearingAidSetAsCommunicationDevice()).thenReturn(true); setupConnectedDevices(null, HEARING_AIDS, null, null, HEARING_AIDS, null); when(mBluetoothHeadset.getAudioState(nullable(BluetoothDevice.class))) .thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED); executeRoutingAction(sm, BluetoothRouteManager.NEW_DEVICE_CONNECTED, HEARING_AID_DEVICE_LEFT.getAddress()); executeRoutingAction(sm, BluetoothRouteManager.CONNECT_BT, HEARING_AID_DEVICE_LEFT.getAddress()); assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX + ":" + HEARING_AID_DEVICE_LEFT.getAddress(), sm.getCurrentState().getName()); sm.quitNow(); } @SmallTest @Test public void testConnectBtRetryWhileNotConnected() { Loading Loading @@ -113,15 +176,15 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { BluetoothRouteManager sm = setupStateMachine( BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, DEVICE1); setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, new BluetoothDevice[]{HEARING_AID_DEVICE}, new BluetoothDevice[]{DEVICE2}, DEVICE1, HEARING_AID_DEVICE, DEVICE2); HEARING_AIDS, new BluetoothDevice[]{DEVICE2}, DEVICE1, HEARING_AIDS, DEVICE2); sm.onActiveDeviceChanged(DEVICE1, BluetoothDeviceManager.DEVICE_TYPE_HEADSET); sm.onActiveDeviceChanged(DEVICE2, BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO); sm.onActiveDeviceChanged(HEARING_AID_DEVICE, sm.onActiveDeviceChanged(HEARING_AID_DEVICE_LEFT, BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID); executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST, DEVICE1.getAddress()); verifyConnectionAttempt(HEARING_AID_DEVICE, 0); verifyConnectionAttempt(HEARING_AID_DEVICE_LEFT, 0); verifyConnectionAttempt(DEVICE1, 0); verifyConnectionAttempt(DEVICE2, 0); assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX Loading Loading @@ -176,11 +239,11 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { @Test public void testSkipInactiveBtDeviceWhenEvaluateActualState() { BluetoothRouteManager sm = setupStateMachine( BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, HEARING_AID_DEVICE); setupConnectedDevices(null, new BluetoothDevice[]{HEARING_AID_DEVICE}, null, null, HEARING_AID_DEVICE, null); BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, HEARING_AID_DEVICE_LEFT); setupConnectedDevices(null, HEARING_AIDS, null, null, HEARING_AIDS, null); executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST, HEARING_AID_DEVICE.getAddress()); HEARING_AID_DEVICE_LEFT.getAddress()); assertEquals(BluetoothRouteManager.AUDIO_OFF_STATE_NAME, sm.getCurrentState().getName()); sm.quitNow(); } Loading Loading @@ -227,10 +290,11 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { private void setupConnectedDevices(BluetoothDevice[] hfpDevices, BluetoothDevice[] hearingAidDevices, BluetoothDevice[] leAudioDevices, BluetoothDevice hfpActiveDevice, BluetoothDevice hearingAidActiveDevice, BluetoothDevice hfpActiveDevice, BluetoothDevice[] hearingAidActiveDevices, BluetoothDevice leAudioDevice) { if (hfpDevices == null) hfpDevices = new BluetoothDevice[]{}; if (hearingAidDevices == null) hearingAidDevices = new BluetoothDevice[]{}; if (hearingAidActiveDevices == null) hearingAidActiveDevices = new BluetoothDevice[]{}; if (leAudioDevice == null) leAudioDevices = new BluetoothDevice[]{}; when(mDeviceManager.getNumConnectedDevices()).thenReturn( Loading @@ -249,7 +313,7 @@ public class BluetoothRouteManagerTest extends TelecomTestCase { when(mBluetoothHearingAid.getConnectedDevices()) .thenReturn(Arrays.asList(hearingAidDevices)); when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEARING_AID))) .thenReturn(Arrays.asList(hearingAidActiveDevice, null)); .thenReturn(Arrays.asList(hearingAidActiveDevices)); when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.LE_AUDIO))) .thenReturn(Arrays.asList(leAudioDevice, null)); } Loading