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

Commit ed669c41 authored by Kyunglyul Hyun's avatar Kyunglyul Hyun
Browse files

Consider LE Audio device in ActiveDeviceManager

When an A2DP or HFP profile is connected,
we set it as active device even when there is
an active LE audio device.
Which resulted in two active devices present.
This CL fixes it and verify it by added tests.

Tag: #stability
Bug: 233710698
Test: atest ActiveDeviceManagerTest && manually
connect BT device while BLE HS is connected.

Change-Id: I11c901da07a9ca6423942cd1702f00d557f1d0b6
parent 9295f0d2
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -217,7 +217,7 @@ class ActiveDeviceManager {
                            break;      // The device is already connected
                        }
                        mA2dpConnectedDevices.add(device);
                        if (mHearingAidActiveDevice == null) {
                        if (mHearingAidActiveDevice == null && mLeAudioActiveDevice == null) {
                            // New connected device: select it as active
                            setA2dpActiveDevice(device);
                            break;
@@ -277,7 +277,7 @@ class ActiveDeviceManager {
                            break;      // The device is already connected
                        }
                        mHfpConnectedDevices.add(device);
                        if (mHearingAidActiveDevice == null) {
                        if (mHearingAidActiveDevice == null && mLeAudioActiveDevice == null) {
                            // New connected device: select it as active
                            setHfpActiveDevice(device);
                            break;
+93 −2
Original line number Diff line number Diff line
@@ -23,21 +23,21 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.sysprop.BluetoothProperties;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.bluetooth.R;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.hearingaid.HearingAidService;
import com.android.bluetooth.hfp.HeadsetService;
import com.android.bluetooth.le_audio.LeAudioService;

import org.junit.After;
import org.junit.Assert;
@@ -57,6 +57,7 @@ public class ActiveDeviceManagerTest {
    private BluetoothDevice mHeadsetDevice;
    private BluetoothDevice mA2dpHeadsetDevice;
    private BluetoothDevice mHearingAidDevice;
    private BluetoothDevice mLeAudioDevice;
    private ActiveDeviceManager mActiveDeviceManager;
    private static final int TIMEOUT_MS = 1000;

@@ -65,6 +66,7 @@ public class ActiveDeviceManagerTest {
    @Mock private A2dpService mA2dpService;
    @Mock private HeadsetService mHeadsetService;
    @Mock private HearingAidService mHearingAidService;
    @Mock private LeAudioService mLeAudioService;
    @Mock private AudioManager mAudioManager;

    @Before
@@ -83,9 +85,11 @@ public class ActiveDeviceManagerTest {
        when(mServiceFactory.getA2dpService()).thenReturn(mA2dpService);
        when(mServiceFactory.getHeadsetService()).thenReturn(mHeadsetService);
        when(mServiceFactory.getHearingAidService()).thenReturn(mHearingAidService);
        when(mServiceFactory.getLeAudioService()).thenReturn(mLeAudioService);
        when(mA2dpService.setActiveDevice(any())).thenReturn(true);
        when(mHeadsetService.setActiveDevice(any())).thenReturn(true);
        when(mHearingAidService.setActiveDevice(any())).thenReturn(true);
        when(mLeAudioService.setActiveDevice(any())).thenReturn(true);

        mActiveDeviceManager = new ActiveDeviceManager(mAdapterService, mServiceFactory);
        mActiveDeviceManager.start();
@@ -96,6 +100,7 @@ public class ActiveDeviceManagerTest {
        mHeadsetDevice = TestUtils.getTestDevice(mAdapter, 1);
        mA2dpHeadsetDevice = TestUtils.getTestDevice(mAdapter, 2);
        mHearingAidDevice = TestUtils.getTestDevice(mAdapter, 3);
        mLeAudioDevice = TestUtils.getTestDevice(mAdapter, 4);
    }

    @After
@@ -212,6 +217,7 @@ public class ActiveDeviceManagerTest {
        Assert.assertEquals(mHeadsetDevice, mActiveDeviceManager.getHfpActiveDevice());
    }


    /**
     * A combo (A2DP + Headset) device is connected. Then a Hearing Aid is connected.
     */
@@ -287,6 +293,81 @@ public class ActiveDeviceManagerTest {
        Assert.assertEquals(null, mActiveDeviceManager.getHearingAidActiveDevice());
    }

    /**
     * A combo (A2DP + Headset) device is connected. Then an LE Audio is connected.
     */
    @Test
    public void leAudioActive_clearA2dpAndHeadsetActive() {
        Assume.assumeTrue("Ignore test when LeAudioService is not enabled",
                LeAudioService.isEnabled());

        a2dpConnected(mA2dpHeadsetDevice);
        headsetConnected(mA2dpHeadsetDevice);
        verify(mA2dpService, timeout(TIMEOUT_MS)).setActiveDevice(mA2dpHeadsetDevice);
        verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(mA2dpHeadsetDevice);

        leAudioActiveDeviceChanged(mLeAudioDevice);
        verify(mA2dpService, timeout(TIMEOUT_MS)).setActiveDevice(isNull());
        verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(isNull());
    }

    /**
     * An LE Audio is connected. Then a combo (A2DP + Headset) device is connected.
     */
    @Test
    public void leAudioActive_dontSetA2dpAndHeadsetActive() {
        Assume.assumeTrue("Ignore test when LeAudioService is not enabled",
                LeAudioService.isEnabled());

        leAudioActiveDeviceChanged(mLeAudioDevice);
        a2dpConnected(mA2dpHeadsetDevice);
        headsetConnected(mA2dpHeadsetDevice);

        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        verify(mA2dpService, never()).setActiveDevice(mA2dpHeadsetDevice);
        verify(mHeadsetService, never()).setActiveDevice(mA2dpHeadsetDevice);
    }

    /**
     * An LE Audio is connected. Then an A2DP active device is explicitly set.
     */
    @Test
    public void leAudioActive_setA2dpActiveExplicitly() {
        Assume.assumeTrue("Ignore test when LeAudioService is not enabled",
                LeAudioService.isEnabled());

        leAudioActiveDeviceChanged(mLeAudioDevice);
        a2dpConnected(mA2dpHeadsetDevice);
        a2dpActiveDeviceChanged(mA2dpHeadsetDevice);

        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        verify(mLeAudioService).setActiveDevice(isNull());
        // Don't call mA2dpService.setActiveDevice()
        verify(mA2dpService, never()).setActiveDevice(mA2dpHeadsetDevice);
        Assert.assertEquals(mA2dpHeadsetDevice, mActiveDeviceManager.getA2dpActiveDevice());
        Assert.assertEquals(null, mActiveDeviceManager.getLeAudioActiveDevice());
    }

    /**
     * An LE Audio is connected. Then a Headset active device is explicitly set.
     */
    @Test
    public void leAudioActive_setHeadsetActiveExplicitly() {
        Assume.assumeTrue("Ignore test when LeAudioService is not enabled",
                LeAudioService.isEnabled());

        leAudioActiveDeviceChanged(mLeAudioDevice);
        headsetConnected(mA2dpHeadsetDevice);
        headsetActiveDeviceChanged(mA2dpHeadsetDevice);

        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        verify(mLeAudioService).setActiveDevice(isNull());
        // Don't call mLeAudioService.setActiveDevice()
        verify(mLeAudioService, never()).setActiveDevice(mA2dpHeadsetDevice);
        Assert.assertEquals(mA2dpHeadsetDevice, mActiveDeviceManager.getHfpActiveDevice());
        Assert.assertEquals(null, mActiveDeviceManager.getLeAudioActiveDevice());
    }

    /**
     * A wired audio device is connected. Then all active devices are set to null.
     */
@@ -373,4 +454,14 @@ public class ActiveDeviceManagerTest {
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent);
    }

    /**
     * Helper to indicate LE Audio active device changed for a device.
     */
    private void leAudioActiveDeviceChanged(BluetoothDevice device) {
        Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent);
    }

}