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

Commit f7c970e4 authored by Grace Jia's avatar Grace Jia
Browse files

Avoid entering to the connected state of an inactive device in

BluetoothRouteManager

Currently telecom will re-evaluate the correct BT device state after we
request to clear the communication device of a BT device. However,
during the re-evaluate, device state returned from BT stack may not
update in time. Treat the requested device as an already inactive device
to avoid mistakenly enter to the connected state of the inactive device.

Bug: b/300236761
Test: atest BluetoothRouteManagerTest
Change-Id: Ib13b2d9f7146b4254e32ee5f055fee23b0171754
parent 9188be02
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -20,8 +20,8 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.media.AudioDeviceInfo;
import android.os.Message;
@@ -38,12 +38,10 @@ import com.android.server.telecom.CallAudioCommunicationDeviceTracker;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -138,7 +136,7 @@ public class BluetoothRouteManager extends StateMachine {
                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
                transitionToActualState();
                transitionToActualState(null /* excludeAddress */);
            }
            cleanupStatesForDisconnectedDevices();
            if (mListener != null) {
@@ -261,7 +259,7 @@ public class BluetoothRouteManager extends StateMachine {
                    case LOST_DEVICE:
                        removeDevice((String) args.arg2);
                        if (Objects.equals(address, mDeviceAddress)) {
                            transitionToActualState();
                            transitionToActualState(null /* excludeAddress */);
                        }
                        break;
                    case CONNECT_BT:
@@ -301,7 +299,7 @@ public class BluetoothRouteManager extends StateMachine {
                    case CONNECTION_TIMEOUT:
                        Log.i(LOG_TAG, "Connection with device %s timed out.",
                                mDeviceAddress);
                        transitionToActualState();
                        transitionToActualState(null /* excludeAddress */);
                        break;
                    case BT_AUDIO_IS_ON:
                        if (Objects.equals(mDeviceAddress, address)) {
@@ -318,7 +316,7 @@ public class BluetoothRouteManager extends StateMachine {
                        if (Objects.equals(mDeviceAddress, address) || address == null) {
                            Log.i(LOG_TAG, "Connection with device %s failed.",
                                    mDeviceAddress);
                            transitionToActualState();
                            transitionToActualState(address);
                        } else {
                            Log.w(LOG_TAG, "Got BT lost message for device %s while" +
                                    " connecting to %s.", address, mDeviceAddress);
@@ -378,7 +376,7 @@ public class BluetoothRouteManager extends StateMachine {
                    case LOST_DEVICE:
                        removeDevice((String) args.arg2);
                        if (Objects.equals(address, mDeviceAddress)) {
                            transitionToActualState();
                            transitionToActualState(null /* excludeAddress */);
                        }
                        break;
                    case CONNECT_BT:
@@ -435,7 +433,7 @@ public class BluetoothRouteManager extends StateMachine {
                    case BT_AUDIO_LOST:
                        if (Objects.equals(mDeviceAddress, address) || address == null) {
                            Log.i(LOG_TAG, "BT connection with device %s lost.", mDeviceAddress);
                            transitionToActualState();
                            transitionToActualState(address);
                        } else {
                            Log.w(LOG_TAG, "Got BT lost message for device %s while" +
                                    " connected to %s.", address, mDeviceAddress);
@@ -721,7 +719,7 @@ public class BluetoothRouteManager extends StateMachine {
                actualAddress)) {
            Log.i(this, "trying to connect to already connected device -- skipping connection"
                    + " and going into the actual connected state.");
            transitionToActualState();
            transitionToActualState(null /* excludeAddress */);
            return null;
        }

@@ -757,9 +755,10 @@ public class BluetoothRouteManager extends StateMachine {
        return null;
    }

    private void transitionToActualState() {
    private void transitionToActualState(String excludeAddress) {
        BluetoothDevice possiblyAlreadyConnectedDevice = getBluetoothAudioConnectedDevice();
        if (possiblyAlreadyConnectedDevice != null) {
        if (possiblyAlreadyConnectedDevice != null
                && !possiblyAlreadyConnectedDevice.getAddress().equals(excludeAddress)) {
            Log.i(LOG_TAG, "Device %s is already connected; going to AudioConnected.",
                    possiblyAlreadyConnectedDevice);
            transitionTo(getConnectedStateForAddress(
+22 −10
Original line number Diff line number Diff line
@@ -16,6 +16,15 @@

package com.android.server.telecom.tests;

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.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
@@ -47,16 +56,6 @@ import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(JUnit4.class)
public class BluetoothRouteManagerTest extends TelecomTestCase {
    private static final int TEST_TIMEOUT = 1000;
@@ -173,6 +172,19 @@ public class BluetoothRouteManagerTest extends TelecomTestCase {
        sm.quitNow();
    }

    @SmallTest
    @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);
        executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST,
                HEARING_AID_DEVICE.getAddress());
        assertEquals(BluetoothRouteManager.AUDIO_OFF_STATE_NAME, sm.getCurrentState().getName());
        sm.quitNow();
    }

    private BluetoothRouteManager setupStateMachine(String initialState,
            BluetoothDevice initialDevice) {
        resetMocks();