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

Commit 041bdb0a authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "le_audio: Update fallback input device" into main am: 67fad757 am: 1d27c124

parents 0c351a1e 1d27c124
Loading
Loading
Loading
Loading
+33 −16
Original line number Diff line number Diff line
@@ -1677,9 +1677,10 @@ public class LeAudioService extends ProfileService {
        }

        if (device != null && mActiveAudioInDevice != null) {
            LeAudioDeviceDescriptor deviceDescriptor = getDeviceDescriptor(device);
            LeAudioDeviceDescriptor deviceDescriptor = getDeviceDescriptor(mActiveAudioInDevice);
            if (deviceDescriptor == null) {
                Log.e(TAG, "updateActiveInDevice: No valid descriptor for device: " + device);
                Log.e(TAG, "updateActiveInDevice: No valid descriptor for device: "
                        + mActiveAudioInDevice);
                return false;
            }

@@ -1744,9 +1745,10 @@ public class LeAudioService extends ProfileService {
        }

        if (device != null && mActiveAudioOutDevice != null) {
            LeAudioDeviceDescriptor deviceDescriptor = getDeviceDescriptor(device);
            LeAudioDeviceDescriptor deviceDescriptor = getDeviceDescriptor(mActiveAudioOutDevice);
            if (deviceDescriptor == null) {
                Log.e(TAG, "updateActiveOutDevice: No valid descriptor for device: " + device);
                Log.e(TAG, "updateActiveOutDevice: No valid descriptor for device: "
                        + mActiveAudioOutDevice);
                return false;
            }

@@ -2375,30 +2377,45 @@ public class LeAudioService extends ProfileService {
                        + ", mExposedActiveDevice: "
                        + mExposedActiveDevice);

        LeAudioGroupDescriptor groupDescriptor = getGroupDescriptor(currentlyActiveGroupId);
        if (isBroadcastActive()
                && currentlyActiveGroupId == LE_AUDIO_GROUP_ID_INVALID
                && mUnicastGroupIdDeactivatedForBroadcastTransition != LE_AUDIO_GROUP_ID_INVALID) {

            LeAudioGroupDescriptor fallbackGroupDescriptor = getGroupDescriptor(groupId);

            // If broadcast is ongoing and need to update unicast fallback active group
            // we need to update the cached group id and skip changing the active device
            updateFallbackUnicastGroupIdForBroadcast(groupId);

            if (fallbackGroupDescriptor != null) {
                if (groupId == LE_AUDIO_GROUP_ID_INVALID) {
                    /* In case of removing fallback unicast group, monitoring input device should be
                     * removed from active devices.
                     */
            if (groupDescriptor != null && groupId == LE_AUDIO_GROUP_ID_INVALID) {
                    updateActiveDevices(
                            groupId,
                        groupDescriptor.mDirection,
                            fallbackGroupDescriptor.mDirection,
                            AUDIO_DIRECTION_NONE,
                            false,
                        groupDescriptor.mHasFallbackDeviceWhenGettingInactive,
                            fallbackGroupDescriptor.mHasFallbackDeviceWhenGettingInactive,
                            false);
                } else {
                    if (mActiveAudioInDevice != null) {
                        updateActiveDevices(
                                groupId,
                                fallbackGroupDescriptor.mDirection,
                                AUDIO_DIRECTION_INPUT_BIT,
                                false,
                                fallbackGroupDescriptor.mHasFallbackDeviceWhenGettingInactive,
                                true);
                    }
                }
            }

            return true;
        }

        LeAudioGroupDescriptor groupDescriptor = getGroupDescriptor(currentlyActiveGroupId);
        if (groupDescriptor != null && groupId == currentlyActiveGroupId) {
            /* Make sure active group is already exposed to audio framework.
             * If not, lets wait for it and don't sent additional intent.
+59 −20
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
@@ -76,6 +77,7 @@ public class LeAudioBroadcastServiceTest {

    private BluetoothAdapter mAdapter;
    private BluetoothDevice mDevice;
    private BluetoothDevice mDevice2;
    private BluetoothDevice mBroadcastDevice;

    private Context mTargetContext;
@@ -234,6 +236,7 @@ public class LeAudioBroadcastServiceTest {
        mTargetContext.registerReceiver(mLeAudioIntentReceiver, filter);

        mDevice = TestUtils.getTestDevice(mAdapter, 0);
        mDevice2 = TestUtils.getTestDevice(mAdapter, 1);
        mBroadcastDevice = TestUtils.getTestDevice(mAdapter, 1);
        when(mAdapterService.getDeviceFromByte(Utils.getBytesFromAddress("FF:FF:FF:FF:FF:FF")))
                .thenReturn(mBroadcastDevice);
@@ -534,7 +537,9 @@ public class LeAudioBroadcastServiceTest {
    public void testCreateBroadcast_updateQualityToStandard() {
        byte[] code = {0x00, 0x01, 0x00, 0x02};
        int groupId = 1;
        prepareConnectedUnicastDevice(groupId);

        initializeNative();
        prepareConnectedUnicastDevice(groupId, mDevice);

        synchronized (mService.mBroadcastCallbacks) {
            mService.mBroadcastCallbacks.register(mCallbacks);
@@ -771,61 +776,61 @@ public class LeAudioBroadcastServiceTest {
        }
    }

    private void prepareConnectedUnicastDevice(int groupId) {
        int direction = 3;
        int snkAudioLocation = 3;
        int srcAudioLocation = 4;
        int availableContexts = 5 + BluetoothLeAudio.CONTEXT_TYPE_RINGTONE;

        /* Initialize native */
    private void initializeNative() {
        LeAudioStackEvent stackEvent =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_NATIVE_INITIALIZED);
        mService.messageFromNative(stackEvent);
        Assert.assertTrue(mService.mLeAudioNativeIsInitialized);
    }

    private void prepareConnectedUnicastDevice(int groupId, BluetoothDevice device) {
        int direction = 3;
        int snkAudioLocation = 3;
        int srcAudioLocation = 4;
        int availableContexts = 5 + BluetoothLeAudio.CONTEXT_TYPE_RINGTONE;

        /* Prepare active group to cause pending broadcast */
        doReturn(BluetoothDevice.BOND_BONDED)
                .when(mAdapterService)
                .getBondState(any(BluetoothDevice.class));
        doReturn(true).when(mLeAudioNativeInterface).connectLeAudio(any(BluetoothDevice.class));
        when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.LE_AUDIO))
        when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO))
                .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED);
        doReturn(new ParcelUuid[] {BluetoothUuid.LE_AUDIO})
                .when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
        Assert.assertTrue(mService.connect(mDevice));
        Assert.assertTrue(mService.connect(device));

        // Verify the connection state broadcast, and that we are in Connected state
        verifyConnectionStateIntent(
                TIMEOUT_MS,
                mDevice,
                device,
                BluetoothProfile.STATE_CONNECTING,
                BluetoothProfile.STATE_DISCONNECTED);
        Assert.assertEquals(
                BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(mDevice));
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(device));

        LeAudioStackEvent create_event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
        create_event.device = mDevice;
        create_event.device = device;
        create_event.valueInt1 = LeAudioStackEvent.CONNECTION_STATE_CONNECTED;
        mService.messageFromNative(create_event);

        verifyConnectionStateIntent(
                TIMEOUT_MS,
                mDevice,
                device,
                BluetoothProfile.STATE_CONNECTED,
                BluetoothProfile.STATE_CONNECTING);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice));
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(device));

        create_event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_NODE_STATUS_CHANGED);
        create_event.device = mDevice;
        create_event.device = device;
        create_event.valueInt1 = groupId;
        create_event.valueInt2 = LeAudioStackEvent.GROUP_NODE_ADDED;
        mService.messageFromNative(create_event);

        create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_AUDIO_CONF_CHANGED);
        create_event.device = mDevice;
        create_event.device = device;
        create_event.valueInt1 = direction;
        create_event.valueInt2 = groupId;
        create_event.valueInt3 = snkAudioLocation;
@@ -848,7 +853,8 @@ public class LeAudioBroadcastServiceTest {
        mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
        mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BIG_DEPENDS_ON_AUDIO_STATE);

        prepareConnectedUnicastDevice(groupId);
        initializeNative();
        prepareConnectedUnicastDevice(groupId, mDevice);

        LeAudioStackEvent stackEvent =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED);
@@ -953,7 +959,8 @@ public class LeAudioBroadcastServiceTest {
            mService.mBroadcastCallbacks.register(mCallbacks);
        }

        prepareConnectedUnicastDevice(groupId);
        initializeNative();
        prepareConnectedUnicastDevice(groupId, mDevice);

        LeAudioStackEvent create_event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED);
@@ -1490,6 +1497,38 @@ public class LeAudioBroadcastServiceTest {
        verify(mBassClientService, times(1)).resumeReceiversSourceSynchronization();
    }

    @Test
    public void testUpdateFallbackInputDevice() {
        mSetFlagsRule.disableFlags(Flags.FLAG_LEAUDIO_USE_AUDIO_MODE_LISTENER);
        int groupId = 1;
        int groupId2 = 2;
        int broadcastId = 243;
        byte[] code = {0x00, 0x01, 0x00, 0x02};

        initializeNative();
        prepareConnectedUnicastDevice(groupId2, mDevice2);
        prepareHandoverStreamingBroadcast(groupId, broadcastId, code);

        Assert.assertEquals(mService.mUnicastGroupIdDeactivatedForBroadcastTransition, groupId);

        reset(mAudioManager);

        /* Update fallback active device (only input is active) */
        ArgumentCaptor<BluetoothProfileConnectionInfo> connectionInfoArgumentCaptor =
                ArgumentCaptor.forClass(BluetoothProfileConnectionInfo.class);

        Assert.assertTrue(mService.setActiveDevice(mDevice2));

        verify(mAudioManager, times(1))
                .handleBluetoothActiveDeviceChanged(
                        eq(mDevice2), eq(mDevice), connectionInfoArgumentCaptor.capture());
        List<BluetoothProfileConnectionInfo> connInfos =
                connectionInfoArgumentCaptor.getAllValues();
        Assert.assertEquals(connInfos.size(), 1);
        Assert.assertFalse(connInfos.get(0).isLeOutput());
        Assert.assertEquals(mService.mUnicastGroupIdDeactivatedForBroadcastTransition, groupId2);
    }

    private class LeAudioIntentReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
+62 −0
Original line number Diff line number Diff line
@@ -1464,6 +1464,68 @@ public class LeAudioServiceTest {
                .isEqualTo(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
    }

    /** Test setting active devices from the same group */
    @Test
    public void testSetActiveDevicesFromSameGroup() {
        int groupId = 1;
        /* AUDIO_DIRECTION_OUTPUT_BIT = 0x01 */
        /* AUDIO_DIRECTION_INPUT_BIT = 0x02 */
        int direction = 3;
        int snkAudioLocation = 3;
        int srcAudioLocation = 4;
        int availableContexts = 5 + BluetoothLeAudio.CONTEXT_TYPE_RINGTONE;

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

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

        // Connected device
        doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class));
        connectTestDevice(mLeftDevice, groupId);
        connectTestDevice(mRightDevice, groupId);

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

        assertThat(mService.setActiveDevice(mLeftDevice)).isTrue();
        verify(mNativeInterface).groupSetActive(groupId);

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

        verify(mAudioManager, times(2))
                .handleBluetoothActiveDeviceChanged(
                        eq(mLeftDevice), eq(null), connectionInfoArgumentCaptor.capture());
        List<BluetoothProfileConnectionInfo> connInfos =
                connectionInfoArgumentCaptor.getAllValues();
        assertThat(connInfos.size()).isEqualTo(2);
        assertThat(connInfos.get(0).isLeOutput()).isEqualTo(true);
        assertThat(connInfos.get(1).isLeOutput()).isEqualTo(false);

        reset(mAudioManager);

        assertThat(mService.setActiveDevice(mRightDevice)).isTrue();
        verify(mAudioManager, times(0))
                .handleBluetoothActiveDeviceChanged(
                        any(), any(), any(BluetoothProfileConnectionInfo.class));
        connInfos = connectionInfoArgumentCaptor.getAllValues();
        assertThat(connInfos.size()).isEqualTo(2);
    }

    /** Test setting active device group with not available contexts */
    @Test
    public void testSetActiveDeviceGroupWithNoContextTypes() {