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

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

Merge "leaudio: Fix switching between LeAudio headsets" into main

parents be370eb6 6126cbf4
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -2108,7 +2108,8 @@ public class LeAudioService extends ProfileService {
                        + (", isSink: " + isSink)
                        + (" isSource: " + isSource)
                        + (", mActiveAudioInDevice: " + mActiveAudioInDevice)
                        + (", mActiveAudioOutDevice: " + mActiveAudioOutDevice));
                        + (", mActiveAudioOutDevice: " + mActiveAudioOutDevice)
                        + (", mExposedActiveDevice: " + mExposedActiveDevice));

        if (!device.equals(mExposedActiveDevice)) {
            return;
@@ -2123,9 +2124,21 @@ public class LeAudioService extends ProfileService {
            return;
        }

        if (device.equals(mActiveAudioInDevice) || device.equals(mActiveAudioOutDevice)) {
            Log.i(TAG, "Audio manager disactivate LeAudio device " + mExposedActiveDevice);
            mExposedActiveDevice = null;
            setActiveDevice(null);
            return;
        }

        Log.i(
                TAG,
                ("LeAudio active device switch: "
                        + mExposedActiveDevice
                        + " -> "
                        + (mActiveAudioInDevice != null
                                ? mActiveAudioInDevice
                                : mActiveAudioOutDevice)));
    }

    /* Notifications of audio device connection/disconn events. */
+68 −19
Original line number Diff line number Diff line
@@ -1643,8 +1643,6 @@ public class LeAudioServiceTest {
        ArgumentCaptor<BluetoothProfileConnectionInfo> connectionInfoArgumentCaptor =
                ArgumentCaptor.forClass(BluetoothProfileConnectionInfo.class);

        /* Expect 2 calles to Audio Manager - one for output  as this is
         * Ringtone use case */
        verify(mAudioManager)
                .handleBluetoothActiveDeviceChanged(
                        eq(mSingleDevice), eq(null), connectionInfoArgumentCaptor.capture());
@@ -1660,39 +1658,90 @@ public class LeAudioServiceTest {
        assertThat(mService.setActiveDevice(mSingleDevice_2)).isTrue();
        verify(mNativeInterface).groupSetActive(groupId_2);

        // First wait for INACTIVE state will be sent from native
        LeAudioStackEvent inactiveGroupState =

        // First wait for ACTIVE state will be sent from native
        LeAudioStackEvent activeGroupState =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED);
        inactiveGroupState.valueInt1 = groupId_1;
        inactiveGroupState.valueInt2 = LeAudioStackEvent.GROUP_STATUS_INACTIVE;
        mService.messageFromNative(inactiveGroupState);
        activeGroupState.valueInt1 = groupId_2;
        activeGroupState.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE;
        activeGroupState.valueInt3 = groupId_1;
        mService.messageFromNative(activeGroupState);

        // Make sure suppressNoisyIntent is set to true. Soon new group will be active
        verify(mAudioManager)
                .handleBluetoothActiveDeviceChanged(
                        eq(null), eq(mSingleDevice), connectionInfoArgumentCaptor.capture());
                        eq(mSingleDevice_2),
                        eq(mSingleDevice),
                        connectionInfoArgumentCaptor.capture());
        connInfo = connectionInfoArgumentCaptor.getValue();
        assertThat(connInfo.isSuppressNoisyIntent()).isTrue();

        injectAudioDeviceRemoved(
                mSingleDevice, AudioDeviceInfo.TYPE_BLE_HEADSET, true, false, false);
        injectAudioDeviceAdded(
                mSingleDevice_2, AudioDeviceInfo.TYPE_BLE_HEADSET, true, false, true);
        verify(mNativeInterface, times(0)).groupSetActive(-1);
    }

        reset(mAudioManager);
    /** Test switching active groups */
    @Test
    public void testAudioFrameworkAutonomousDeviceRemoval() {
        int groupId_1 = 1;

        // First wait for ACTIVE state will be sent from native
        LeAudioStackEvent activeGroupState =
        /* AUDIO_DIRECTION_OUTPUT_BIT = 0x01 */
        int direction = 1;
        int snkAudioLocation = 3;
        int srcAudioLocation = 4;
        int availableContexts = 5 + BluetoothLeAudio.CONTEXT_TYPE_RINGTONE;

        // Not connected device
        assertThat(mService.setActiveDevice(mSingleDevice)).isFalse();

        // Define some return values needed in test
        doReturn(-1).when(mVolumeControlService).getAudioDeviceGroupVolume(anyInt());
        doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class));

        // Connect both
        connectTestDevice(mSingleDevice, groupId_1);

        // Add location support
        LeAudioStackEvent audioConfChangedEvent =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_AUDIO_CONF_CHANGED);
        audioConfChangedEvent.device = mSingleDevice;
        audioConfChangedEvent.valueInt1 = direction;
        audioConfChangedEvent.valueInt2 = groupId_1;
        audioConfChangedEvent.valueInt3 = snkAudioLocation;
        audioConfChangedEvent.valueInt4 = srcAudioLocation;
        audioConfChangedEvent.valueInt5 = availableContexts;
        mService.messageFromNative(audioConfChangedEvent);

        assertThat(mService.setActiveDevice(mSingleDevice)).isTrue();
        verify(mNativeInterface).groupSetActive(groupId_1);

        // Set group and device as active
        LeAudioStackEvent groupStatusChangedEvent =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED);
        activeGroupState.valueInt1 = groupId_2;
        activeGroupState.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE;
        mService.messageFromNative(activeGroupState);
        groupStatusChangedEvent.valueInt1 = groupId_1;
        groupStatusChangedEvent.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE;
        mService.messageFromNative(groupStatusChangedEvent);

        verify(mTbsService).setInbandRingtoneSupport(mSingleDevice);

        ArgumentCaptor<BluetoothProfileConnectionInfo> connectionInfoArgumentCaptor =
                ArgumentCaptor.forClass(BluetoothProfileConnectionInfo.class);

        verify(mAudioManager)
                .handleBluetoothActiveDeviceChanged(
                        eq(mSingleDevice_2), eq(null), connectionInfoArgumentCaptor.capture());
        connInfo = connectionInfoArgumentCaptor.getValue();
                        eq(mSingleDevice), eq(null), connectionInfoArgumentCaptor.capture());

        injectAudioDeviceAdded(mSingleDevice, AudioDeviceInfo.TYPE_BLE_HEADSET, true, false, true);

        BluetoothProfileConnectionInfo connInfo = connectionInfoArgumentCaptor.getValue();
        assertThat(connInfo.isSuppressNoisyIntent()).isTrue();

        injectAudioDeviceAdded(
                mSingleDevice_2, AudioDeviceInfo.TYPE_BLE_HEADSET, true, false, true);
        // AudioManager removes audio device
        injectAudioDeviceRemoved(
                mSingleDevice, AudioDeviceInfo.TYPE_BLE_HEADSET, true, false, false);
        verify(mNativeInterface, times(1)).groupSetActive(-1);
    }

    /** Test setting active device group without Ringtone context */
+5 −1
Original line number Diff line number Diff line
@@ -1434,8 +1434,12 @@ public:
       * the new group so the group change is correctly handled in OnStateMachineStatusReportCb
       */
      active_group_id_ = group_id;
      SuspendedForReconfiguration();
      GroupStop(previous_active_group);
      callbacks_->OnGroupStatus(previous_active_group, GroupStatus::INACTIVE);
      /* Note: On purpose we are not sending INACTIVE status up to Java, because previous active
       * group will be provided in ACTIVE status. This is in order to have single call to audio
       * framework
       */
    }

    /* Reset sink listener notified status */