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

Commit 8bb24469 authored by jasonwshsu's avatar jasonwshsu
Browse files

Fix did not show connected status icon when active to other bluetooth device

Root Cause: mIsActiveDeviceLeAudio did not change to false when non-active on main device

Solution: propagate active status to all sub and member CachedBluetoothDevices

Bug: 383202440
Test: atest BluetoothEventManagerTest
Flag: EXEMPT bugfix
Change-Id: I88558e15730acff6aca57c686d6cfd59d7819b74
parent 8ddbaf6a
Loading
Loading
Loading
Loading
+25 −16
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.collection.ArraySet;

import com.android.settingslib.R;
import com.android.settingslib.flags.Flags;
@@ -274,29 +275,37 @@ public class BluetoothEventManager {
    @VisibleForTesting
    void dispatchActiveDeviceChanged(
            @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
        CachedBluetoothDevice targetDevice = activeDevice;
        CachedBluetoothDevice mainActiveDevice = activeDevice;
        for (CachedBluetoothDevice cachedDevice : mDeviceManager.getCachedDevicesCopy()) {
            // should report isActive from main device or it will cause trouble to other callers.
            CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
            CachedBluetoothDevice finalTargetDevice = targetDevice;
            if (targetDevice != null
                    && ((subDevice != null && subDevice.equals(targetDevice))
                    || cachedDevice.getMemberDevice().stream().anyMatch(
                            memberDevice -> memberDevice.equals(finalTargetDevice)))) {
                Log.d(TAG,
                        "The active device is the sub/member device "
                                + targetDevice.getDevice().getAnonymizedAddress()
                                + ". change targetDevice as main device "
                                + cachedDevice.getDevice().getAnonymizedAddress());
                targetDevice = cachedDevice;
            Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice();
            final Set<CachedBluetoothDevice> cachedDevices = new ArraySet<>();
            cachedDevices.add(cachedDevice);
            if (!memberDevices.isEmpty()) {
                cachedDevices.addAll(memberDevices);
            } else if (subDevice != null) {
                cachedDevices.add(subDevice);
            }
            boolean isActiveDevice = cachedDevice.equals(targetDevice);
            cachedDevice.onActiveDeviceChanged(isActiveDevice, bluetoothProfile);

            // should report isActive from main device or it will cause trouble to other callers.
            if (activeDevice != null
                    && (cachedDevices.stream().anyMatch(
                            device -> device.equals(activeDevice)))) {
                Log.d(TAG, "The active device is in the set, report main device as active device:"
                        + cachedDevice.getDevice() + ", active device:" + activeDevice.getDevice());
                mainActiveDevice = cachedDevice;
            }
            boolean isActiveDevice = cachedDevice.equals(mainActiveDevice);
            cachedDevices.forEach(
                    device -> device.onActiveDeviceChanged(isActiveDevice, bluetoothProfile));
            //TODO: b/400440223 - Check if we can call DeviceManager.onActiveDeviceChanged &
            // Callback.onActiveDeviceChanged for cachedDevices Set also, so we don't need to report
            // isActive from main device.
            mDeviceManager.onActiveDeviceChanged(cachedDevice);
        }

        for (BluetoothCallback callback : mCallbacks) {
            callback.onActiveDeviceChanged(targetDevice, bluetoothProfile);
            callback.onActiveDeviceChanged(mainActiveDevice, bluetoothProfile);
        }
    }

+24 −5
Original line number Diff line number Diff line
@@ -70,6 +70,9 @@ public class BluetoothEventManagerTest {
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();

    private static final String DEVICE_NAME = "test_device_name";
    private static final String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
    private static final String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
    private static final String DEVICE_ADDRESS_3 = "AA:BB:CC:DD:EE:33";

    @Mock
    private LocalBluetoothAdapter mLocalAdapter;
@@ -132,6 +135,9 @@ public class BluetoothEventManagerTest {
        when(mA2dpProfile.isProfileReady()).thenReturn(true);
        when(mHearingAidProfile.isProfileReady()).thenReturn(true);
        when(mLeAudioProfile.isProfileReady()).thenReturn(true);
        when(mDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1);
        when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
        when(mDevice3.getAddress()).thenReturn(DEVICE_ADDRESS_3);
        mCachedDevice1 = new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice1);
        mCachedDevice2 = new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice2);
        mCachedDevice3 = new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice3);
@@ -515,7 +521,6 @@ public class BluetoothEventManagerTest {
        cachedDevices.add(mCachedDevice2);

        int group1 = 1;
        when(mDevice3.getAddress()).thenReturn("testAddress3");
        mCachedDevice1.setGroupId(group1);
        mCachedDevice3.setGroupId(group1);
        mCachedDevice1.addMemberDevice(mCachedDevice3);
@@ -620,18 +625,32 @@ public class BluetoothEventManagerTest {
    }

    @Test
    public void dispatchActiveDeviceChanged_activeFromSubDevice_mainCachedDeviceActive() {
    public void dispatchActiveDeviceChanged_activeFromSubDevice_bothCachedDevicesActive() {
        CachedBluetoothDevice subDevice = new CachedBluetoothDevice(mContext, mLocalProfileManager,
                mDevice3);
        mCachedDevice1.setSubDevice(subDevice);
        when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(
                Collections.singletonList(mCachedDevice1));
        mCachedDevice1.onProfileStateChanged(mHearingAidProfile,
                BluetoothProfile.STATE_CONNECTED);
        mCachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);

        assertThat(mCachedDevice1.isActiveDevice(BluetoothProfile.HEARING_AID)).isFalse();
        mBluetoothEventManager.dispatchActiveDeviceChanged(subDevice, BluetoothProfile.HEARING_AID);

        assertThat(mCachedDevice1.isActiveDevice(BluetoothProfile.HEARING_AID)).isTrue();
        assertThat(subDevice.isActiveDevice(BluetoothProfile.HEARING_AID)).isTrue();
    }

    @Test
    public void dispatchActiveDeviceChanged_activeFromMemberDevice_allCachedDevicesActive() {
        mCachedDevice1.addMemberDevice(mCachedDevice2);
        when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(
                Collections.singletonList(mCachedDevice1));
        mCachedDevice1.onProfileStateChanged(mLeAudioProfile, BluetoothProfile.STATE_CONNECTED);

        mBluetoothEventManager.dispatchActiveDeviceChanged(mCachedDevice2,
                BluetoothProfile.LE_AUDIO);

        assertThat(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).isTrue();
        assertThat(mCachedDevice2.isActiveDevice(BluetoothProfile.LE_AUDIO)).isTrue();
    }

    @Test