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

Commit 667eecfe authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

BluetoothRouteManager: Fix switching between HFP and LeAudio

When switching between devices we need to make sure to close audio
connection in active device before connecting the other one.

Tag: #feature
Bug: 159786353
Sponsor: jpawlowski@
test: switch between HFP and LeAudio during call
Change-Id: Id5adb411557b0437e89775991bf3158fd4fd6ef1
parent 3a62bb68
Loading
Loading
Loading
Loading
+41 −25
Original line number Diff line number Diff line
@@ -160,7 +160,8 @@ public class BluetoothRouteManager extends StateMachine {
                        removeDevice((String) args.arg2);
                        break;
                    case CONNECT_HFP:
                        String actualAddress = connectBtAudio((String) args.arg2);
                        String actualAddress = connectBtAudio((String) args.arg2,
                            false /* switchingBtDevices*/);

                        if (actualAddress != null) {
                            transitionTo(getConnectingStateForAddress(actualAddress,
@@ -175,7 +176,8 @@ public class BluetoothRouteManager extends StateMachine {
                        break;
                    case RETRY_HFP_CONNECTION:
                        Log.i(LOG_TAG, "Retrying HFP connection to %s", (String) args.arg2);
                        String retryAddress = connectBtAudio((String) args.arg2, args.argi1);
                        String retryAddress = connectBtAudio((String) args.arg2, args.argi1,
                            false /* switchingBtDevices*/);

                        if (retryAddress != null) {
                            transitionTo(getConnectingStateForAddress(retryAddress,
@@ -247,6 +249,7 @@ public class BluetoothRouteManager extends StateMachine {

            SomeArgs args = (SomeArgs) msg.obj;
            String address = (String) args.arg2;
            boolean switchingBtDevices = !Objects.equals(mDeviceAddress, address);
            try {
                switch (msg.what) {
                    case NEW_DEVICE_CONNECTED:
@@ -260,12 +263,13 @@ public class BluetoothRouteManager extends StateMachine {
                        }
                        break;
                    case CONNECT_HFP:
                        if (Objects.equals(mDeviceAddress, address)) {
                        if (!switchingBtDevices) {
                            // Ignore repeated connection attempts to the same device
                            break;
                        }
                        String actualAddress = connectBtAudio(address);

                        String actualAddress = connectBtAudio(address,
                            true /* switchingBtDevices*/);
                        if (actualAddress != null) {
                            transitionTo(getConnectingStateForAddress(actualAddress,
                                    "AudioConnecting/CONNECT_HFP"));
@@ -278,17 +282,19 @@ public class BluetoothRouteManager extends StateMachine {
                        mDeviceManager.disconnectAudio();
                        break;
                    case RETRY_HFP_CONNECTION:
                        if (Objects.equals(address, mDeviceAddress)) {
                        if (!switchingBtDevices) {
                            Log.d(LOG_TAG, "Retry message came through while connecting.");
                        } else {
                            String retryAddress = connectBtAudio(address, args.argi1);
                            break;
                        }

                        String retryAddress = connectBtAudio(address, args.argi1,
                            true /* switchingBtDevices*/);
                        if (retryAddress != null) {
                            transitionTo(getConnectingStateForAddress(retryAddress,
                                    "AudioConnecting/RETRY_HFP_CONNECTION"));
                        } else {
                            Log.i(LOG_TAG, "Retry failed.");
                        }
                        }
                        break;
                    case CONNECTION_TIMEOUT:
                        Log.i(LOG_TAG, "Connection with device %s timed out.",
@@ -361,6 +367,7 @@ public class BluetoothRouteManager extends StateMachine {

            SomeArgs args = (SomeArgs) msg.obj;
            String address = (String) args.arg2;
            boolean switchingBtDevices = !Objects.equals(mDeviceAddress, address);
            try {
                switch (msg.what) {
                    case NEW_DEVICE_CONNECTED:
@@ -373,12 +380,13 @@ public class BluetoothRouteManager extends StateMachine {
                        }
                        break;
                    case CONNECT_HFP:
                        if (Objects.equals(mDeviceAddress, address)) {
                        if (!switchingBtDevices) {
                            // Ignore connection to already connected device.
                            break;
                        }
                        String actualAddress = connectBtAudio(address);

                        String actualAddress = connectBtAudio(address,
                            true /* switchingBtDevices*/);
                        if (actualAddress != null) {
                            transitionTo(getConnectingStateForAddress(address,
                                    "AudioConnected/CONNECT_HFP"));
@@ -391,17 +399,19 @@ public class BluetoothRouteManager extends StateMachine {
                        mDeviceManager.disconnectAudio();
                        break;
                    case RETRY_HFP_CONNECTION:
                        if (Objects.equals(address, mDeviceAddress)) {
                        if (!switchingBtDevices) {
                            Log.d(LOG_TAG, "Retry message came through while connected.");
                        } else {
                            String retryAddress = connectBtAudio(address, args.argi1);
                            break;
                        }

                        String retryAddress = connectBtAudio(address, args.argi1,
                            true /* switchingBtDevices*/);
                        if (retryAddress != null) {
                            transitionTo(getConnectingStateForAddress(retryAddress,
                                    "AudioConnected/RETRY_HFP_CONNECTION"));
                        } else {
                            Log.i(LOG_TAG, "Retry failed.");
                        }
                        }
                        break;
                    case CONNECTION_TIMEOUT:
                        Log.w(LOG_TAG, "Received CONNECTION_TIMEOUT while connected.");
@@ -638,8 +648,8 @@ public class BluetoothRouteManager extends StateMachine {
        return mDeviceManager.getUniqueConnectedDevices();
    }

    private String connectBtAudio(String address) {
        return connectBtAudio(address, 0);
    private String connectBtAudio(String address, boolean switchingBtDevices) {
        return connectBtAudio(address, 0, switchingBtDevices);
    }

    /**
@@ -648,15 +658,21 @@ public class BluetoothRouteManager extends StateMachine {
     * Telecom from within it.
     * @param address The address that should be tried first. May be null.
     * @param retryCount The number of times this connection attempt has been retried.
     * @param switchingBtDevices Used when there is existing audio connection to other Bt device.
     * @return The address of the device that's actually being connected to, or null if no
     * connection was successful.
     */
    private String connectBtAudio(String address, int retryCount) {
    private String connectBtAudio(String address, int retryCount, boolean switchingBtDevices) {
        Collection<BluetoothDevice> deviceList = mDeviceManager.getConnectedDevices();
        Optional<BluetoothDevice> matchingDevice = deviceList.stream()
                .filter(d -> Objects.equals(d.getAddress(), address))
                .findAny();

        if (switchingBtDevices) {
            /* When new Bluetooth connects audio, make sure previous one has disconnected audio. */
            mDeviceManager.disconnectAudio();
        }

        String actualAddress = matchingDevice.isPresent()
                ? address : getActiveDeviceAddress();
        if (actualAddress == null) {
+9 −3
Original line number Diff line number Diff line
@@ -191,7 +191,8 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
        public int messageType; // Any of the commands from the state machine
        public BluetoothDevice messageDevice; // The device that should be specified in the message.
        public ListenerUpdate[] expectedListenerUpdates; // what the listener should expect.
        public int expectedBluetoothInteraction; // NONE, CONNECT, or DISCONNECT
        // NONE, CONNECT, CONNECT_SWITCH_DEVICE or DISCONNECT
        public int expectedBluetoothInteraction;
        public BluetoothDevice expectedConnectionDevice; // Expected device to connect to.
        public String expectedFinalStateName; // Expected name of the final state.
        public BluetoothDevice[] connectedDevices; // array of connected devices
@@ -246,6 +247,7 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
    private static final int NONE = 1;
    private static final int CONNECT = 2;
    private static final int DISCONNECT = 3;
    private static final int CONNECT_SWITCH_DEVICE = 4;

    private static final int TEST_TIMEOUT = 1000;

@@ -359,6 +361,10 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
                verify(mDeviceManager).connectAudio(mParams.expectedConnectionDevice.getAddress());
                verify(mDeviceManager, never()).disconnectAudio();
                break;
            case CONNECT_SWITCH_DEVICE:
                verify(mDeviceManager).disconnectAudio();
                verify(mDeviceManager).connectAudio(mParams.expectedConnectionDevice.getAddress());
            break;
            case DISCONNECT:
                verify(mDeviceManager, never()).connectAudio(nullable(String.class));
                verify(mDeviceManager).disconnectAudio();
@@ -491,7 +497,7 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
                .setMessageType(BluetoothRouteManager.CONNECT_HFP)
                .setMessageDevice(DEVICE3)
                .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED)
                .setExpectedBluetoothInteraction(CONNECT)
                .setExpectedBluetoothInteraction(CONNECT_SWITCH_DEVICE)
                .setExpectedConnectionDevice(DEVICE3)
                .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
                        + ":" + DEVICE3)
@@ -505,7 +511,7 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
                .setMessageType(BluetoothRouteManager.CONNECT_HFP)
                .setMessageDevice(DEVICE3)
                .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED)
                .setExpectedBluetoothInteraction(CONNECT)
                .setExpectedBluetoothInteraction(CONNECT_SWITCH_DEVICE)
                .setExpectedConnectionDevice(DEVICE3)
                .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX
                        + ":" + DEVICE3)