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

Commit f34b57a0 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I3dac549c,I7ff35d5e

* changes:
  Set communication audio flag for BT le device and hearing aid device off if the communication device is already set to other devices.
  Use setCommunicationDevice to connect hearing aid BT devices.
parents 6915e63f 80a3a93e
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,18 +412,44 @@ 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() {
        Log.i(this, "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 {
@@ -783,6 +789,7 @@ public class BluetoothRouteManager extends StateMachine {
        }

        if (bluetoothHearingAid != null) {
            if (mDeviceManager.isHearingAidSetAsCommunicationDevice()) {
                for (BluetoothDevice device : bluetoothAdapter.getActiveDevices(
                        BluetoothProfile.HEARING_AID)) {
                    if (device != null) {
@@ -792,6 +799,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);
           }
+31 −26
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.telecom.tests;

import static android.media.AudioDeviceInfo.TYPE_BUILTIN_SPEAKER;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
@@ -42,6 +44,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.nullable;
@@ -65,6 +68,7 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
    @Mock BluetoothHearingAid mBluetoothHearingAid;
    @Mock BluetoothLeAudio mBluetoothLeAudio;
    @Mock AudioManager mockAudioManager;
    @Mock AudioDeviceInfo mSpeakerInfo;

    BluetoothDeviceManager mBluetoothDeviceManager;
    BluetoothProfile.ServiceListener serviceListenerUnderTest;
@@ -116,6 +120,8 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
                         ArgumentCaptor.forClass(BluetoothLeAudio.Callback.class);
        mBluetoothDeviceManager.setLeAudioServiceForTesting(mBluetoothLeAudio);
        verify(mBluetoothLeAudio).registerCallback(any(), leAudioCallbacksTest.capture());

        when(mSpeakerInfo.getType()).thenReturn(TYPE_BUILTIN_SPEAKER);
    }

    @Override
@@ -391,43 +397,22 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
    @SmallTest
    @Test
    public void testConnectDisconnectAudioHearingAid() {
        receiverUnderTest.onReceive(mContext,
                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2,
                        BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
        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);
        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));

        mBluetoothDeviceManager.disconnectAudio();
        verify(mBluetoothHeadset).disconnectAudio();
    }

    @SmallTest
    @Test
    public void testConnectDisconnectAudioLeAudio() {
        receiverUnderTest.setIsInCall(true);
        receiverUnderTest.onReceive(mContext,
                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
                        BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
                        BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID));
        leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1);
        when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
                eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);

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

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

        mBluetoothDeviceManager.connectAudio(device5.getAddress());
@@ -436,6 +421,7 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
        verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class),
                eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL));

        when(mockAudioManager.getCommunicationDevice()).thenReturn(mockAudioDeviceInfo);
        mBluetoothDeviceManager.disconnectAudio();
        verify(mockAudioManager).clearCommunicationDevice();
    }
@@ -471,6 +457,25 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
        verify(mAdapter).setActiveDevice(device6, BluetoothAdapter.ACTIVE_DEVICE_ALL);
    }

    @SmallTest
    @Test
    public void testClearHearingAidCommunicationDevice() {
        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.setHearingAidCommunicationDevice();
        when(mockAudioManager.getCommunicationDevice()).thenReturn(mSpeakerInfo);
        mBluetoothDeviceManager.clearHearingAidCommunicationDevice();
        assertFalse(mBluetoothDeviceManager.isHearingAidSetAsCommunicationDevice());
    }

    private Intent buildConnectionActionIntent(int state, BluetoothDevice device, int deviceType) {
        String intentString;

+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();
    }