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

Commit 71fb48b2 authored by Hall Liu's avatar Hall Liu
Browse files

Modify BT behavior when connecting to active device

When we try to connect to a device that's already recognized as active
by the BT stack, don't just ignore it -- do some resolution logic to
align everything with what's actually going on in the system.

This change is needed because we may end up in a weird situation with
hearing aids, where BluetoothRouteManager will report AudioOff while the
hearing aid device is still active. This currently happens because we
don't treat active hearing aids as audio-connected outside a call, and
it's not getting updated when a call starts.

This change doesn't fix the root of the problem, but we're planning on
changing all the bluetooth logic in the next release anyway, so this
patch will be sufficient for now.

Test: manual
Test: atest TelecomUnitTests
Fixes: 152724391
Change-Id: Id49dea147d766f45efd5ef2e719f2814b2769ac6
parent b6e5b396
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -1607,10 +1607,13 @@ public class CallAudioRouteStateMachine extends StateMachine {
            BluetoothDevice connectedDevice =
                    mBluetoothRouteManager.getBluetoothAudioConnectedDevice();
            if (address == null && connectedDevice != null) {
                // null means connect to any device, so don't bother reconnecting. Also, send a
                // message to ourselves telling us that BT audio is already connected.
                Log.i(this, "HFP audio already on. Skipping connecting.");
                // null means connect to any device, so if we're already connected to some device,
                // that means we can just tell ourselves that it's connected.
                // Do still try to connect audio though, so that BluetoothRouteManager knows that
                // there's an active call.
                Log.i(this, "Bluetooth audio already on.");
                sendInternalMessage(BT_AUDIO_CONNECTED);
                mBluetoothRouteManager.connectBluetoothAudio(connectedDevice.getAddress());
                return;
            }
            if (connectedDevice == null || !Objects.equals(address, connectedDevice.getAddress())) {
+10 −0
Original line number Diff line number Diff line
@@ -645,6 +645,16 @@ public class BluetoothRouteManager extends StateMachine {
            Log.i(this, "No device with address %s available. Using %s instead.",
                    address, actualAddress);
        }

        BluetoothDevice alreadyConnectedDevice = getBluetoothAudioConnectedDevice();
        if (alreadyConnectedDevice != null && alreadyConnectedDevice.getAddress().equals(
                actualAddress)) {
            Log.i(this, "trying to connect to already connected device -- skipping connection"
                    + " and going into the actual connected state.");
            transitionToActualState();
            return null;
        }

        if (!mDeviceManager.connectAudio(actualAddress)) {
            boolean shouldRetry = retryCount < MAX_CONNECTION_RETRIES;
            Log.w(LOG_TAG, "Could not connect to %s. Will %s", actualAddress,
+18 −0
Original line number Diff line number Diff line
@@ -346,6 +346,8 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
        when(mDeviceManager.getConnectedDevices()).thenReturn(Arrays.asList(devices));
        when(mHeadsetProxy.getConnectedDevices()).thenReturn(Arrays.asList(devices));
        when(mHeadsetProxy.getActiveDevice()).thenReturn(activeDevice);
        when(mHeadsetProxy.getAudioState(nullable(BluetoothDevice.class)))
                .thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
        if (audioOnDevice != null) {
            when(mHeadsetProxy.getActiveDevice()).thenReturn(audioOnDevice);
            when(mHeadsetProxy.getAudioState(audioOnDevice))
@@ -634,6 +636,22 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
                .setExpectedBluetoothInteraction(NONE)
                .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
                .build());

        result.add(new BluetoothRouteTestParametersBuilder()
                .setName("connect BT to an already active device when in audio off.")
                .setInitialBluetoothState(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
                .setAudioOnDevice(DEVICE2)
                .setActiveDevice(DEVICE2)
                .setConnectedDevices(DEVICE2, DEVICE3)
                .setHearingAidBtDevices(Collections.singletonList(DEVICE2))
                .setMessageType(BluetoothRouteManager.CONNECT_HFP)
                .setMessageDevice(DEVICE2)
                .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED)
                .setExpectedBluetoothInteraction(NONE)
                .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX
                        + ":" + DEVICE2)
                .build());

        return result;
    }
}
+6 −3
Original line number Diff line number Diff line
@@ -54,9 +54,11 @@ import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
@@ -486,9 +488,10 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase {
                CallAudioRouteStateMachine.ACTIVE_FOCUS);
        waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);

        // Make sure that we've successfully switched to the active BT route without actually
        // calling connectAudio.
        verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(nullable(String.class));
        // Make sure that we've successfully switched to the active BT route and that we've
        // called connectAudio on the right device.
        verify(mockBluetoothRouteManager, atLeastOnce())
                .connectBluetoothAudio(eq(bluetoothDevice1.getAddress()));
        assertTrue(stateMachine.isInActiveState());
    }