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

Commit 8f8a30fd authored by Sungsoo Lim's avatar Sungsoo Lim Committed by Gerrit Code Review
Browse files

Merge "Handle hearing aid device group in ActiveDeviceManager"

parents 4862bc06 0d072f50
Loading
Loading
Loading
Loading
+48 −10
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.ArraySet;
import android.util.Log;

import com.android.bluetooth.a2dp.A2dpService;
@@ -50,6 +51,7 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * The active device manager is responsible for keeping track of the
@@ -140,7 +142,7 @@ class ActiveDeviceManager {
    private List<BluetoothDevice> mPendingLeHearingAidActiveDevice = new ArrayList<>();
    private BluetoothDevice mA2dpActiveDevice = null;
    private BluetoothDevice mHfpActiveDevice = null;
    private BluetoothDevice mHearingAidActiveDevice = null;
    private final Set<BluetoothDevice> mHearingAidActiveDevices = new ArraySet<>();
    private BluetoothDevice mLeAudioActiveDevice = null;
    private BluetoothDevice mLeHearingAidActiveDevice = null;

@@ -247,7 +249,8 @@ class ActiveDeviceManager {
                            break;      // The device is already connected
                        }
                        mA2dpConnectedDevices.add(device);
                        if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null) {
                        if (mHearingAidActiveDevices.isEmpty()
                                && mLeHearingAidActiveDevice == null) {
                            // New connected device: select it as active
                            setA2dpActiveDevice(device);
                            setLeAudioActiveDevice(null);
@@ -313,7 +316,8 @@ class ActiveDeviceManager {
                            break;      // The device is already connected
                        }
                        mHfpConnectedDevices.add(device);
                        if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null) {
                        if (mHearingAidActiveDevices.isEmpty()
                                && mLeHearingAidActiveDevice == null) {
                            // New connected device: select it as active
                            setHfpActiveDevice(device);
                            setLeAudioActiveDevice(null);
@@ -392,7 +396,8 @@ class ActiveDeviceManager {
                                    + "_CHANGED): device " + device + " disconnected");
                        }
                        mHearingAidConnectedDevices.remove(device);
                        if (Objects.equals(mHearingAidActiveDevice, device)) {
                        if (mHearingAidActiveDevices.remove(device)
                                && mHearingAidActiveDevices.isEmpty()) {
                            if (mHearingAidConnectedDevices.isEmpty()) {
                                setHearingAidActiveDevice(null);
                            }
@@ -411,7 +416,17 @@ class ActiveDeviceManager {
                                + "device= " + device);
                    }
                    // Just assign locally the new value
                    mHearingAidActiveDevice = device;
                    final HearingAidService hearingAidService = mFactory.getHearingAidService();
                    if (hearingAidService != null) {
                        long hiSyncId = hearingAidService.getHiSyncId(device);
                        if (getHearingAidActiveHiSyncId() == hiSyncId) {
                            mHearingAidActiveDevices.add(device);
                        } else {
                            mHearingAidActiveDevices.clear();
                            mHearingAidActiveDevices.addAll(
                                    hearingAidService.getConnectedPeerDevices(hiSyncId));
                        }
                    }
                    if (device != null) {
                        setA2dpActiveDevice(null);
                        setHfpActiveDevice(null);
@@ -440,7 +455,8 @@ class ActiveDeviceManager {
                            break;      // The device is already connected
                        }
                        mLeAudioConnectedDevices.add(device);
                        if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null
                        if (mHearingAidActiveDevices.isEmpty()
                                && mLeHearingAidActiveDevice == null
                                && mPendingLeHearingAidActiveDevice.isEmpty()) {
                            // New connected device: select it as active
                            setLeAudioActiveDevice(device);
@@ -708,10 +724,24 @@ class ActiveDeviceManager {
        if (hearingAidService == null) {
            return;
        }

        if (device == null) {
            hearingAidService.setActiveDevice(null);
            mHearingAidActiveDevices.clear();
            return;
        }

        long hiSyncId = hearingAidService.getHiSyncId(device);
        if (getHearingAidActiveHiSyncId() == hiSyncId) {
            mHearingAidActiveDevices.add(device);
            return;
        }

        if (!hearingAidService.setActiveDevice(device)) {
            return;
        }
        mHearingAidActiveDevice = device;
        mHearingAidActiveDevices.clear();
        mHearingAidActiveDevices.addAll(hearingAidService.getConnectedPeerDevices(hiSyncId));
    }

    private void setLeAudioActiveDevice(BluetoothDevice device) {
@@ -863,7 +893,7 @@ class ActiveDeviceManager {
        mHfpActiveDevice = null;

        mHearingAidConnectedDevices.clear();
        mHearingAidActiveDevice = null;
        mHearingAidActiveDevices.clear();

        mLeAudioConnectedDevices.clear();
        mLeAudioActiveDevice = null;
@@ -889,8 +919,8 @@ class ActiveDeviceManager {
    }

    @VisibleForTesting
    BluetoothDevice getHearingAidActiveDevice() {
        return mHearingAidActiveDevice;
    Set<BluetoothDevice> getHearingAidActiveDevices() {
        return mHearingAidActiveDevices;
    }

    @VisibleForTesting
@@ -898,6 +928,14 @@ class ActiveDeviceManager {
        return mLeAudioActiveDevice;
    }

    long getHearingAidActiveHiSyncId() {
        final HearingAidService hearingAidService = mFactory.getHearingAidService();
        if (hearingAidService != null && !mHearingAidActiveDevices.isEmpty()) {
            return hearingAidService.getHiSyncId(mHearingAidActiveDevices.iterator().next());
        }
        return BluetoothHearingAid.HI_SYNC_ID_INVALID;
    }

    /**
     * Called when a wired audio device is connected.
     * It might be called multiple times each time a wired audio device is connected.
+2 −2
Original line number Diff line number Diff line
@@ -567,7 +567,7 @@ public class HearingAidService extends ProfileService {
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
    long getHiSyncId(BluetoothDevice device) {
    public long getHiSyncId(BluetoothDevice device) {
        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
                "Need BLUETOOTH_PRIVILEGED permission");
        if (device == null) {
@@ -857,7 +857,7 @@ public class HearingAidService extends ProfileService {
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
    private List<BluetoothDevice> getConnectedPeerDevices(long hiSyncId) {
    public List<BluetoothDevice> getConnectedPeerDevices(long hiSyncId) {
        List<BluetoothDevice> result = new ArrayList<>();
        for (BluetoothDevice peerDevice : getConnectedDevices()) {
            if (getHiSyncId(peerDevice) == hiSyncId) {
+36 −2
Original line number Diff line number Diff line
@@ -77,6 +77,8 @@ public class ActiveDeviceManagerTest {
    private ArrayList<BluetoothDevice> mDeviceConnectionStack;
    private BluetoothDevice mMostRecentDevice;
    private ActiveDeviceManager mActiveDeviceManager;
    private long mHearingAidHiSyncId = 1010;

    private static final int TIMEOUT_MS = 1000;

    @Mock private AdapterService mAdapterService;
@@ -130,6 +132,12 @@ public class ActiveDeviceManagerTest {
        when(mHearingAidService.setActiveDevice(any())).thenReturn(true);
        when(mLeAudioService.setActiveDevice(any())).thenReturn(true);

        List<BluetoothDevice> connectedHearingAidDevices = new ArrayList<>();
        connectedHearingAidDevices.add(mHearingAidDevice);
        when(mHearingAidService.getHiSyncId(mHearingAidDevice)).thenReturn(mHearingAidHiSyncId);
        when(mHearingAidService.getConnectedPeerDevices(mHearingAidHiSyncId))
                .thenReturn(connectedHearingAidDevices);

        when(mA2dpService.getFallbackDevice()).thenAnswer(invocation -> {
            if (!mDeviceConnectionStack.isEmpty() && Objects.equals(mA2dpDevice,
                    mDeviceConnectionStack.get(mDeviceConnectionStack.size() - 1))) {
@@ -329,6 +337,25 @@ public class ActiveDeviceManagerTest {
        verify(mHeadsetService, never()).setActiveDevice(mHeadsetDevice);
    }

    @Test
    public void twoHearingAidDevicesConnected_WithTheSameHiSyncId() {
        Assume.assumeTrue("Ignore test when HearingAidService is not enabled",
                HearingAidService.isEnabled());

        List<BluetoothDevice> connectedHearingAidDevices = new ArrayList<>();
        connectedHearingAidDevices.add(mHearingAidDevice);
        connectedHearingAidDevices.add(mSecondaryAudioDevice);
        when(mHearingAidService.getHiSyncId(mSecondaryAudioDevice))
                .thenReturn(mHearingAidHiSyncId);
        when(mHearingAidService.getConnectedPeerDevices(mHearingAidHiSyncId))
                .thenReturn(connectedHearingAidDevices);

        hearingAidConnected(mHearingAidDevice);
        hearingAidConnected(mSecondaryAudioDevice);
        verify(mHearingAidService, timeout(TIMEOUT_MS)).setActiveDevice(mHearingAidDevice);
        verify(mHearingAidService, never()).setActiveDevice(mSecondaryAudioDevice);
    }

    /**
     * A combo (A2DP + Headset) device is connected. Then a Hearing Aid is connected.
     */
@@ -381,7 +408,7 @@ public class ActiveDeviceManagerTest {
        // Don't call mA2dpService.setActiveDevice()
        verify(mA2dpService, never()).setActiveDevice(mA2dpHeadsetDevice);
        Assert.assertEquals(mA2dpHeadsetDevice, mActiveDeviceManager.getA2dpActiveDevice());
        Assert.assertEquals(null, mActiveDeviceManager.getHearingAidActiveDevice());
        Assert.assertTrue(mActiveDeviceManager.getHearingAidActiveDevices().isEmpty());
    }

    /**
@@ -401,7 +428,7 @@ public class ActiveDeviceManagerTest {
        // Don't call mHeadsetService.setActiveDevice()
        verify(mHeadsetService, never()).setActiveDevice(mA2dpHeadsetDevice);
        Assert.assertEquals(mA2dpHeadsetDevice, mActiveDeviceManager.getHfpActiveDevice());
        Assert.assertEquals(null, mActiveDeviceManager.getHearingAidActiveDevice());
        Assert.assertTrue(mActiveDeviceManager.getHearingAidActiveDevices().isEmpty());
    }

    /**
@@ -594,6 +621,13 @@ public class ActiveDeviceManagerTest {
        hearingAidConnected(mHearingAidDevice);
        verify(mHearingAidService, timeout(TIMEOUT_MS)).setActiveDevice(mHearingAidDevice);

        List<BluetoothDevice> connectedHearingAidDevices = new ArrayList<>();
        connectedHearingAidDevices.add(mSecondaryAudioDevice);
        when(mHearingAidService.getHiSyncId(mSecondaryAudioDevice))
                .thenReturn(mHearingAidHiSyncId + 1);
        when(mHearingAidService.getConnectedPeerDevices(mHearingAidHiSyncId + 1))
                .thenReturn(connectedHearingAidDevices);

        hearingAidConnected(mSecondaryAudioDevice);
        verify(mHearingAidService, timeout(TIMEOUT_MS)).setActiveDevice(mSecondaryAudioDevice);