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

Commit a1b9acc4 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Track LE hearing aid connected devices" into tm-qpr-dev am: 08b9ee36

parents a7c5f62b 08b9ee36
Loading
Loading
Loading
Loading
+94 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.SuppressLint;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHapClient;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothLeAudio;
@@ -116,6 +117,8 @@ class ActiveDeviceManager {
    private static final int MESSAGE_HEARING_AID_ACTION_ACTIVE_DEVICE_CHANGED = 6;
    private static final int MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE_CHANGED = 8;
    private static final int MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED = 9;
    private static final int MESSAGE_HAP_ACTION_CONNECTION_STATE_CHANGED = 10;
    private static final int MESSAGE_HAP_ACTION_ACTIVE_DEVICE_CHANGED = 11;

    private final AdapterService mAdapterService;
    private final ServiceFactory mFactory;
@@ -127,10 +130,12 @@ class ActiveDeviceManager {
    private final List<BluetoothDevice> mA2dpConnectedDevices = new LinkedList<>();
    private final List<BluetoothDevice> mHfpConnectedDevices = new LinkedList<>();
    private final List<BluetoothDevice> mLeAudioConnectedDevices = new LinkedList<>();
    private final List<BluetoothDevice> mLeHearingAidConnectedDevices = new LinkedList<>();
    private BluetoothDevice mA2dpActiveDevice = null;
    private BluetoothDevice mHfpActiveDevice = null;
    private BluetoothDevice mHearingAidActiveDevice = null;
    private BluetoothDevice mLeAudioActiveDevice = null;
    private BluetoothDevice mLeHearingAidActiveDevice = null;

    // Broadcast receiver for all changes
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -174,6 +179,14 @@ class ActiveDeviceManager {
                    mHandler.obtainMessage(MESSAGE_LE_AUDIO_ACTION_ACTIVE_DEVICE_CHANGED,
                            intent).sendToTarget();
                    break;
                case BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED:
                    mHandler.obtainMessage(MESSAGE_HAP_ACTION_CONNECTION_STATE_CHANGED,
                            intent).sendToTarget();
                    break;
                case BluetoothHapClient.ACTION_HAP_DEVICE_AVAILABLE:
                    mHandler.obtainMessage(MESSAGE_HAP_ACTION_ACTIVE_DEVICE_CHANGED,
                            intent).sendToTarget();
                    break;
                default:
                    Log.e(TAG, "Received unexpected intent, action=" + action);
                    break;
@@ -223,7 +236,7 @@ class ActiveDeviceManager {
                            break;      // The device is already connected
                        }
                        mA2dpConnectedDevices.add(device);
                        if (mHearingAidActiveDevice == null) {
                        if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null) {
                            // New connected device: select it as active
                            setA2dpActiveDevice(device);
                            setLeAudioActiveDevice(null);
@@ -285,7 +298,7 @@ class ActiveDeviceManager {
                            break;      // The device is already connected
                        }
                        mHfpConnectedDevices.add(device);
                        if (mHearingAidActiveDevice == null) {
                        if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null) {
                            // New connected device: select it as active
                            setHfpActiveDevice(device);
                            setLeAudioActiveDevice(null);
@@ -364,7 +377,7 @@ class ActiveDeviceManager {
                            break;      // The device is already connected
                        }
                        mLeAudioConnectedDevices.add(device);
                        if (mHearingAidActiveDevice == null) {
                        if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null) {
                            // New connected device: select it as active
                            setLeAudioActiveDevice(device);
                            setA2dpActiveDevice(null);
@@ -407,6 +420,79 @@ class ActiveDeviceManager {
                    mLeAudioActiveDevice = device;
                }
                break;

                case MESSAGE_HAP_ACTION_CONNECTION_STATE_CHANGED: {
                    Intent intent = (Intent) msg.obj;
                    BluetoothDevice device =
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    int prevState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
                    int nextState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
                    if (prevState == nextState) {
                        // Nothing has changed
                        break;
                    }
                    if (nextState == BluetoothProfile.STATE_CONNECTED) {
                        // Device connected
                        if (DBG) {
                            Log.d(TAG, "handleMessage(MESSAGE_HAP_ACTION_CONNECTION_STATE"
                                    + "_CHANGED): device " + device + " connected");
                        }
                        if (mLeHearingAidConnectedDevices.contains(device)) {
                            break;      // The device is already connected
                        }
                        mLeHearingAidConnectedDevices.add(device);
                        if (!mLeAudioConnectedDevices.contains(device)) {
                            mLeAudioConnectedDevices.add(device);
                        }
                        // New connected device: select it as active
                        setLeAudioActiveDevice(device);
                        if (mLeAudioActiveDevice == device) {
                            // setLeAudioActiveDevice succeed
                            mLeHearingAidActiveDevice = device;
                        }
                        setA2dpActiveDevice(null);
                        setHfpActiveDevice(null);
                        break;
                    }
                    if (prevState == BluetoothProfile.STATE_CONNECTED) {
                        // Device disconnected
                        if (DBG) {
                            Log.d(TAG, "handleMessage(MESSAGE_HAP_ACTION_CONNECTION_STATE"
                                    + "_CHANGED): device " + device + " disconnected");
                        }
                        mLeHearingAidConnectedDevices.remove(device);
                        mLeAudioConnectedDevices.remove(device);
                        // mLeAudioConnectedDevices should contain all of
                        // mLeHearingAidConnectedDevices. Call setLeAudioActiveDevice(null)
                        // only if there are no LE audio devices.
                        if (mLeAudioConnectedDevices.isEmpty()
                                && Objects.equals(mLeHearingAidConnectedDevices, device)) {
                            setLeAudioActiveDevice(null);
                        }
                    }
                }
                break;

                case MESSAGE_HAP_ACTION_ACTIVE_DEVICE_CHANGED: {
                    Intent intent = (Intent) msg.obj;
                    BluetoothDevice device =
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    if (device != null && !mLeAudioConnectedDevices.contains(device)) {
                        mLeAudioConnectedDevices.add(device);
                    }
                    if (DBG) {
                        Log.d(TAG, "handleMessage(MESSAGE_HAP_ACTION_ACTIVE_DEVICE_CHANGED): "
                                + "device= " + device);
                    }
                    // Just assign locally the new value
                    if (device != null && !Objects.equals(mLeHearingAidActiveDevice, device)) {
                        setA2dpActiveDevice(null);
                        setHfpActiveDevice(null);
                        setHearingAidActiveDevice(null);
                    }
                    mLeHearingAidActiveDevice = mLeAudioActiveDevice = device;
                }
                break;
            }
        }
    }
@@ -477,6 +563,8 @@ class ActiveDeviceManager {
        filter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
        filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
        filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
        filter.addAction(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED);
        filter.addAction(BluetoothHapClient.ACTION_HAP_DEVICE_AVAILABLE);
        mAdapterService.registerReceiver(mReceiver, filter);

        mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler);
@@ -565,6 +653,9 @@ class ActiveDeviceManager {
            return;
        }
        mLeAudioActiveDevice = device;
        if (device == null) {
            mLeHearingAidActiveDevice = null;
        }
    }

    private void resetState() {
+55 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static org.mockito.Mockito.*;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHapClient;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothLeAudio;
@@ -107,7 +108,7 @@ public class ActiveDeviceManagerTest {
        mA2dpHeadsetDevice = TestUtils.getTestDevice(mAdapter, 2);
        mHearingAidDevice = TestUtils.getTestDevice(mAdapter, 3);
        mLeAudioDevice = TestUtils.getTestDevice(mAdapter, 4);
        mSecondaryAudioDevice = TestUtils.getTestDevice(mAdapter, 4);
        mSecondaryAudioDevice = TestUtils.getTestDevice(mAdapter, 5);
    }

    @After
@@ -472,6 +473,29 @@ public class ActiveDeviceManagerTest {
        Assert.assertEquals(null, mActiveDeviceManager.getLeAudioActiveDevice());
    }

    /**
     * One LE Hearing Aid is connected.
     */
    @Test
    public void onlyLeHearingAIdConnected_setHeadsetActive() {
        leAudioConnected(mLeAudioDevice);
        verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mLeAudioDevice);
    }

    /**
     * LE audio is connected after LE Hearing Aid device.
     * Keep LE hearing Aid active.
     */
    @Test
    public void leAudioConnectedAfterLeHearingAid_setLeAudioActiveShouldNotBeCalled() {
        leHearingAidConnected(mSecondaryAudioDevice);
        verify(mLeAudioService, timeout(TIMEOUT_MS)).setActiveDevice(mSecondaryAudioDevice);

        leAudioConnected(mLeAudioDevice);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        verify(mLeAudioService, never()).setActiveDevice(mLeAudioDevice);
    }

    /**
     * A wired audio device is connected. Then all active devices are set to null.
     */
@@ -590,4 +614,34 @@ public class ActiveDeviceManagerTest {
        mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent);
    }

    /**
     * Helper to indicate LE Hearing Aid connected for a device.
     */
    private void leHearingAidConnected(BluetoothDevice device) {
        Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_DISCONNECTED);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
        mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent);
    }

    /**
     * Helper to indicate LE Hearing Aid disconnected for a device.
     */
    private void leHearingAidDisconnected(BluetoothDevice device) {
        Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTED);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED);
        mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent);
    }

    /**
     * Helper to indicate LE Audio Hearing Aid device changed for a device.
     */
    private void leHearingAidActiveDeviceChanged(BluetoothDevice device) {
        Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_DEVICE_AVAILABLE);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent);
    }
}