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

Commit 0405bd34 authored by Grace Jia's avatar Grace Jia
Browse files

Use setCommunicationDevice to connect hearing aid BT devices.

Currently we can't switch audio routes when connect to a hearing aid BT
device and can't continue playing music via hearing aid BT device
automatically after a call. Use setCommunicationDevice API same as LE
audio device to solve this.
Also fix minor bug for LE audio BT device to make sure these device
won't be disabled unintentionally.

Bug: 229358080
Bug: 232360337
Test: TelecomUnitTestCases, manually test the audio route can switch
properly in a call initially routed via hearing aid BT device and can
play music properly after the call.

Change-Id: I7ff35d5eada34335fafa6f0aeaff019803541b51
parent 7d932a43
Loading
Loading
Loading
Loading
+86 −5
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ public class BluetoothDeviceManager {
    private boolean mLeAudioCallbackRegistered = false;
    private BluetoothLeAudio mBluetoothLeAudioService;
    private boolean mLeAudioSetAsCommunicationDevice = false;
    private boolean mHearingAidSetAsCommunicationDevice = false;
    private BluetoothDevice mBluetoothHearingAidActiveDeviceCache;
    private BluetoothAdapter mBluetoothAdapter;
    private AudioManager mAudioManager;
@@ -396,6 +397,7 @@ public class BluetoothDeviceManager {
    public void disconnectAudio() {
        disconnectSco();
        clearLeAudioCommunicationDevice();
        clearHearingAidCommunicationDevice();
    }

    public void disconnectSco() {
@@ -410,17 +412,43 @@ public class BluetoothDeviceManager {
        return mLeAudioSetAsCommunicationDevice;
    }

    public boolean isHearingAidSetAsCommunicationDevice() {
        return mHearingAidSetAsCommunicationDevice;
    }

    public void clearLeAudioCommunicationDevice() {
        if (!mLeAudioSetAsCommunicationDevice) {
            return;
        }
        mLeAudioSetAsCommunicationDevice = false;

        if (mAudioManager == null) {
            Log.i(this, " mAudioManager is null");
            Log.i(this, "clearLeAudioCommunicationDevice: mAudioManager is null");
            mLeAudioSetAsCommunicationDevice = false;
            return;
        }
        if (mAudioManager.getCommunicationDevice() != null
                && mAudioManager.getCommunicationDevice().getType()
                == AudioDeviceInfo.TYPE_BLE_HEADSET) {
            mAudioManager.clearCommunicationDevice();
            mLeAudioSetAsCommunicationDevice = false;
        }
    }

    public void clearHearingAidCommunicationDevice() {
        if (!mHearingAidSetAsCommunicationDevice) {
            return;
        }

        if (mAudioManager == null) {
            Log.i(this, "clearHearingAidCommunicationDevice: mAudioManager is null");
            mHearingAidSetAsCommunicationDevice = false;
        }
        if (mAudioManager.getCommunicationDevice() != null
                && mAudioManager.getCommunicationDevice().getType()
                == AudioDeviceInfo.TYPE_HEARING_AID) {
            mAudioManager.clearCommunicationDevice();
            mHearingAidSetAsCommunicationDevice = false;
        }
    }

    public boolean setLeAudioCommunicationDevice() {
@@ -456,6 +484,9 @@ public class BluetoothDeviceManager {
            return false;
        }

        // clear hearing aid communication device if set
        clearHearingAidCommunicationDevice();

        // Turn BLE_OUT_HEADSET ON.
        boolean result = mAudioManager.setCommunicationDevice(bleHeadset);
        if (!result) {
@@ -467,6 +498,53 @@ public class BluetoothDeviceManager {
        return result;
    }

    public boolean setHearingAidCommunicationDevice() {
        Log.i(this, "setHearingAidCommunicationDevice");

        if (mHearingAidSetAsCommunicationDevice) {
            Log.i(this, "mHearingAidSetAsCommunicationDevice already set");
            return true;
        }

        if (mAudioManager == null) {
            Log.w(this, " mAudioManager is null");
            return false;
        }

        AudioDeviceInfo hearingAid = null;
        List<AudioDeviceInfo> devices = mAudioManager.getAvailableCommunicationDevices();
        if (devices.size() == 0) {
            Log.w(this, " No communication devices available.");
            return false;
        }

        for (AudioDeviceInfo device : devices) {
            Log.i(this, " Available device type:  " + device.getType());
            if (device.getType() == AudioDeviceInfo.TYPE_HEARING_AID) {
                hearingAid = device;
                break;
            }
        }

        if (hearingAid == null) {
            Log.w(this, " No hearingAid device available");
            return false;
        }

        // clear LE audio communication device if set
        clearLeAudioCommunicationDevice();

        // Turn hearing aid ON.
        boolean result = mAudioManager.setCommunicationDevice(hearingAid);
        if (!result) {
            Log.w(this, " Could not set hearingAid device");
        } else {
            Log.i(this, " hearingAid device set");
            mHearingAidSetAsCommunicationDevice = true;
        }
        return result;
    }

    // Connect audio to the bluetooth device at address, checking to see whether it's
    // le audio, hearing aid or a HFP device, and using the proper BT API.
    public boolean connectAudio(String address) {
@@ -486,9 +564,12 @@ public class BluetoothDeviceManager {
                Log.w(this, "Attempting to turn on audio when the hearing aid service is null");
                return false;
            }
            return mBluetoothAdapter.setActiveDevice(
            if (mBluetoothAdapter.setActiveDevice(
                    mHearingAidDevicesByAddress.get(address),
                    BluetoothAdapter.ACTIVE_DEVICE_ALL);
                    BluetoothAdapter.ACTIVE_DEVICE_ALL)) {
                return setHearingAidCommunicationDevice();
            }
            return false;
        } else if (mHfpDevicesByAddress.containsKey(address)) {
            BluetoothDevice device = mHfpDevicesByAddress.get(address);
            if (mBluetoothHeadset == null) {
+14 −6
Original line number Diff line number Diff line
@@ -381,7 +381,10 @@ public class BluetoothRouteManager extends StateMachine {
                        break;
                    case CONNECT_BT:
                        if (!switchingBtDevices) {
                            // Ignore connection to already connected device.
                            // Ignore connection to already connected device but still notify
                            // CallAudioRouteStateMachine since this might be a switch from other
                            // to this already connected BT audio
                            mListener.onBluetoothAudioConnected();
                            break;
                        }

@@ -621,6 +624,9 @@ public class BluetoothRouteManager extends StateMachine {
            }
        } else if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID) {
            mHearingAidActiveDeviceCache = device;
            if (device == null) {
                mDeviceManager.clearHearingAidCommunicationDevice();
            }
        } else if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEADSET) {
            mHfpActiveDeviceCache = device;
        } else {
@@ -791,6 +797,7 @@ public class BluetoothRouteManager extends StateMachine {
        }

        if (bluetoothHearingAid != null) {
            if (mDeviceManager.isHearingAidSetAsCommunicationDevice()) {
                for (BluetoothDevice device : bluetoothAdapter.getActiveDevices(
                        BluetoothProfile.HEARING_AID)) {
                    if (device != null) {
@@ -800,6 +807,7 @@ public class BluetoothRouteManager extends StateMachine {
                    }
                }
            }
        }

        if (bluetoothLeAudio != null) {
            if (mDeviceManager.isLeAudioCommunicationDevice()) {
+10 −1
Original line number Diff line number Diff line
@@ -185,9 +185,18 @@ public class BluetoothStateReceiver extends BroadcastReceiver {
                     * is set as communication device before we can say that BT_AUDIO_IS_ON
                     */
                    if (!mBluetoothDeviceManager.setLeAudioCommunicationDevice()) {
                        Log.w(LOG_TAG, "Device %s cannot be use as communication device.", device);
                        Log.w(LOG_TAG,
                                "Device %s cannot be use as LE audio communication device.",
                                device);
                        return;
                    }
                } else {
                    /* deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID */
                    if (!mBluetoothDeviceManager.setHearingAidCommunicationDevice()) {
                        Log.w(LOG_TAG,
                                "Device %s cannot be use as hearing aid communication device.",
                                device);
                    }
                }
                mBluetoothRouteManager.sendMessage(BT_AUDIO_IS_ON, args);
           }
+18 −7
Original line number Diff line number Diff line
@@ -391,22 +391,33 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
    @SmallTest
    @Test
    public void testConnectDisconnectAudioHearingAid() {
        receiverUnderTest.setIsInCall(true);
        receiverUnderTest.onReceive(mContext,
                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2,
                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
                        BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
        leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1);
        when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
                eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
        mBluetoothDeviceManager.connectAudio(device2.getAddress());
        verify(mAdapter).setActiveDevice(device2, BluetoothAdapter.ACTIVE_DEVICE_ALL);

        AudioDeviceInfo mockAudioDeviceInfo = mock(AudioDeviceInfo.class);
        when(mockAudioDeviceInfo.getType()).thenReturn(AudioDeviceInfo.TYPE_HEARING_AID);
        List<AudioDeviceInfo> devices = new ArrayList<>();
        devices.add(mockAudioDeviceInfo);

        when(mockAudioManager.getAvailableCommunicationDevices())
                .thenReturn(devices);
        when(mockAudioManager.setCommunicationDevice(eq(mockAudioDeviceInfo)))
                .thenReturn(true);

        mBluetoothDeviceManager.connectAudio(device5.getAddress());
        verify(mAdapter).setActiveDevice(device5, BluetoothAdapter.ACTIVE_DEVICE_ALL);
        verify(mBluetoothHeadset, never()).connectAudio();
        verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class),
                eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL));

        when(mAdapter.getActiveDevices(eq(BluetoothProfile.HEARING_AID)))
                .thenReturn(Arrays.asList(device2, null));

        when(mockAudioManager.getCommunicationDevice()).thenReturn(mockAudioDeviceInfo);
        mBluetoothDeviceManager.disconnectAudio();
        verify(mBluetoothHeadset).disconnectAudio();
        verify(mockAudioManager).clearCommunicationDevice();
    }

    @SmallTest
+1 −1
Original line number Diff line number Diff line
@@ -123,7 +123,7 @@ public class BluetoothRouteManagerTest extends TelecomTestCase {
        verifyConnectionAttempt(DEVICE1, 0);
        verifyConnectionAttempt(DEVICE2, 0);
        assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX
                        + ":" + HEARING_AID_DEVICE.getAddress(),
                        + ":" + DEVICE1.getAddress(),
                sm.getCurrentState().getName());
        sm.quitNow();
    }