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

Commit 6261de50 authored by Yiyi Shen's avatar Yiyi Shen Committed by Android (Google) Code Review
Browse files

Merge "[Audiosharing] Fix call audio device in call" into main

parents 899a6d8f b77c619e
Loading
Loading
Loading
Loading
+52 −44
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
import android.util.Pair;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -195,40 +196,33 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
                        }
                        updateDeviceItemsInSharingSession();
                        if (!mDeviceItemsInSharingSession.isEmpty()) {
                            int checkedItemIndex = getActiveItemIndex(mDeviceItemsInSharingSession);
                            Pair<Integer, AudioSharingDeviceItem> pair = getActiveItemWithIndex();
                            AudioSharingCallAudioDialogFragment.show(
                                    mFragment,
                                    mDeviceItemsInSharingSession,
                                    checkedItemIndex,
                                    pair == null ? -1 : pair.first,
                                    (AudioSharingDeviceItem item) -> {
                                        int currentGroupId =
                                                BluetoothUtils.getPrimaryGroupIdForBroadcast(
                                                        mContext.getContentResolver());
                                        if (item.getGroupId() == currentGroupId) {
                                            Log.d(
                                                    TAG,
                                                    "Skip set fallback active device: unchanged");
                                        int clickedGroupId = item.getGroupId();
                                        if (clickedGroupId == currentGroupId) {
                                            Log.d(TAG, "Skip set call audio device: unchanged");
                                            return;
                                        }
                                        List<BluetoothDevice> devices =
                                                mGroupedConnectedDevices.getOrDefault(
                                                        item.getGroupId(), ImmutableList.of());
                                                        clickedGroupId, ImmutableList.of());
                                        CachedBluetoothDevice lead =
                                                AudioSharingUtils.getLeadDevice(
                                                        mCacheManager, devices);
                                        if (lead != null) {
                                            Log.d(
                                                    TAG,
                                                    "Set fallback active device: "
                                                            + lead.getDevice()
                                                                    .getAnonymizedAddress());
                                            String addr = lead.getDevice().getAnonymizedAddress();
                                            Log.d(TAG, "Set call audio device: " + addr);
                                            lead.setActive();
                                            logCallAudioDeviceChange(currentGroupId, lead);
                                        } else {
                                            Log.d(
                                                    TAG,
                                                    "Fail to set fallback active device: no"
                                                            + " lead device");
                                            Log.d(TAG, "Skip set call audio device: no lead");
                                        }
                                    });
                        }
@@ -263,6 +257,18 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
        }
    }

    @Override
    public void onActiveDeviceChanged(@Nullable CachedBluetoothDevice activeDevice,
            int bluetoothProfile) {
        if (activeDevice != null && bluetoothProfile == BluetoothProfile.LE_AUDIO
                && BluetoothUtils.isBroadcasting(mBtManager)) {
            Log.d(TAG, "onActiveDeviceChanged: update summary, device = "
                    + activeDevice.getDevice().getAnonymizedAddress()
                    + ", profile = " + bluetoothProfile);
            updateSummary();
        }
    }

    /**
     * Initialize the controller.
     *
@@ -348,15 +354,9 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
     */
    private void updateSummary() {
        updateDeviceItemsInSharingSession();
        int fallbackActiveGroupId =
                BluetoothUtils.getPrimaryGroupIdForBroadcast(mContext.getContentResolver());
        if (fallbackActiveGroupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
            for (AudioSharingDeviceItem item : mDeviceItemsInSharingSession) {
                if (item.getGroupId() == fallbackActiveGroupId) {
                    Log.d(
                            TAG,
                            "updatePreference: set summary to fallback group "
                                    + fallbackActiveGroupId);
        Pair<Integer, AudioSharingDeviceItem> pair = getActiveItemWithIndex();
        if (pair != null) {
            Log.d(TAG, "updateSummary, group = " + pair.second.getGroupId());
            AudioSharingUtils.postOnMainThread(
                    mContext,
                    () -> {
@@ -364,14 +364,12 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
                            mPreference.setSummary(
                                    mContext.getString(
                                            R.string.audio_sharing_call_audio_description,
                                                    item.getName()));
                                            pair.second.getName()));
                        }
                    });
            return;
        }
            }
        }
        Log.d(TAG, "updatePreference: set empty summary");
        Log.d(TAG, "updateSummary: set empty");
        AudioSharingUtils.postOnMainThread(
                mContext,
                () -> {
@@ -388,16 +386,26 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
                        mBtManager, mGroupedConnectedDevices, /* filterByInSharing= */ true);
    }

    private int getActiveItemIndex(List<AudioSharingDeviceItem> deviceItems) {
        int checkedItemIndex = -1;
    @Nullable
    private Pair<Integer, AudioSharingDeviceItem> getActiveItemWithIndex() {
        List<AudioSharingDeviceItem> deviceItems = new ArrayList<>(mDeviceItemsInSharingSession);
        int fallbackActiveGroupId =
                BluetoothUtils.getPrimaryGroupIdForBroadcast(mContext.getContentResolver());
        if (fallbackActiveGroupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
            for (AudioSharingDeviceItem item : deviceItems) {
                if (item.getGroupId() == fallbackActiveGroupId) {
                return deviceItems.indexOf(item);
                    Log.d(TAG, "getActiveItemWithIndex, fallback group = " + item.getGroupId());
                    return new Pair<>(deviceItems.indexOf(item), item);
                }
            }
        }
        for (AudioSharingDeviceItem item : deviceItems) {
            if (item.isActive()) {
                Log.d(TAG, "getActiveItemWithIndex, active LEA group = " + item.getGroupId());
                return new Pair<>(deviceItems.indexOf(item), item);
            }
        }
        return checkedItemIndex;
        return null;
    }

    @VisibleForTesting
+8 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.settings.connecteddevice.audiosharing;
import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;

public final class AudioSharingDeviceItem implements Parcelable {
    private final String mName;
    private final int mGroupId;
@@ -72,4 +74,10 @@ public final class AudioSharingDeviceItem implements Parcelable {
                    return new AudioSharingDeviceItem[size];
                }
            };

    @Override
    @NonNull
    public String toString() {
        return "AudioSharingDeviceItem groupId = " + mGroupId + ", isActive = " + mIsActive;
    }
}
+71 −65
Original line number Diff line number Diff line
@@ -176,6 +176,22 @@ public class AudioSharingCallAudioPreferenceControllerTest {
        bisSyncState.add(1L);
        when(mState.getBisSyncState()).thenReturn(bisSyncState);
        when(mContext.getContentResolver()).thenReturn(mContentResolver);
        when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
        when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
        when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(false);
        when(mCachedDevice1.getMemberDevice()).thenReturn(ImmutableSet.of(mCachedDevice2));
        when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
        when(mCachedDevice2.getDevice()).thenReturn(mDevice2);
        when(mCachedDevice2.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice2.getName()).thenReturn(TEST_DEVICE_NAME1);
        when(mCachedDevice2.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(false);
        when(mCacheManager.findDevice(mDevice2)).thenReturn(mCachedDevice2);
        when(mCachedDevice3.getDevice()).thenReturn(mDevice3);
        when(mCachedDevice3.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID2);
        when(mCachedDevice3.getName()).thenReturn(TEST_DEVICE_NAME2);
        when(mCachedDevice3.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(false);
        when(mCacheManager.findDevice(mDevice3)).thenReturn(mCachedDevice3);
        mController = new AudioSharingCallAudioPreferenceController(mContext);
        mController.init(null);
        mContentObserver = mController.getSettingsObserver();
@@ -323,7 +339,9 @@ public class AudioSharingCallAudioPreferenceControllerTest {
        when(mBroadcast.isEnabled(any())).thenReturn(true);
        when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());
        mController.displayPreference(mScreen);
        shadowOf(Looper.getMainLooper()).idle();
        mPreference.setSummary("test");

        mController.onProfileConnectionStateChanged(
                mCachedDevice1,
                BluetoothAdapter.STATE_DISCONNECTED,
@@ -335,14 +353,13 @@ public class AudioSharingCallAudioPreferenceControllerTest {
    @Test
    public void onFallbackDeviceChanged_updateSummary() {
        Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
        when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
        when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
        when(mBroadcast.isEnabled(any())).thenReturn(true);
        when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
        when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
        mController.displayPreference(mScreen);
        shadowOf(Looper.getMainLooper()).idle();
        mPreference.setSummary("test");

        mContentObserver.onChange(true);
        shadowOf(Looper.getMainLooper()).idle();
        assertThat(mPreference.getSummary().toString())
@@ -352,20 +369,29 @@ public class AudioSharingCallAudioPreferenceControllerTest {
    }

    @Test
    public void displayPreference_showCorrectSummary() {
    public void onActiveDeviceChanged_updateSummary() {
        Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY,
                BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
        when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true);
        when(mBroadcast.isEnabled(any())).thenReturn(true);
        when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
        when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
        mController.displayPreference(mScreen);
        shadowOf(Looper.getMainLooper()).idle();
        mPreference.setSummary("test");

        mController.onActiveDeviceChanged(mCachedDevice1, BluetoothProfile.LE_AUDIO);
        shadowOf(Looper.getMainLooper()).idle();
        assertThat(mPreference.getSummary().toString())
                .isEqualTo(
                        mContext.getString(
                                R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
    }

    @Test
    public void displayPreference_fallbackDeviceInSharing_showCorrectSummary() {
        Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
        when(mCachedDevice2.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice2.getDevice()).thenReturn(mDevice2);
        when(mCachedDevice1.getMemberDevice()).thenReturn(ImmutableSet.of(mCachedDevice2));
        when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
        when(mCachedDevice3.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID2);
        when(mCachedDevice3.getDevice()).thenReturn(mDevice3);
        when(mCachedDevice3.getName()).thenReturn(TEST_DEVICE_NAME2);
        when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
        when(mCacheManager.findDevice(mDevice2)).thenReturn(mCachedDevice2);
        when(mCacheManager.findDevice(mDevice3)).thenReturn(mCachedDevice3);
        when(mCachedDevice3.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true);
        when(mBroadcast.isEnabled(any())).thenReturn(true);
        when(mAssistant.getAllConnectedDevices())
                .thenReturn(ImmutableList.of(mDevice1, mDevice2, mDevice3));
@@ -379,14 +405,24 @@ public class AudioSharingCallAudioPreferenceControllerTest {
    }

    @Test
    public void displayPreference_noFallbackDeviceInSharing_showEmptySummary() {
    public void displayPreference_activeDeviceInSharing_showCorrectSummary() {
        Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID2);
        when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
        when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
        when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
        when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true);
        when(mBroadcast.isEnabled(any())).thenReturn(true);
        when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1));
        when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2));
        when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
        mController.displayPreference(mScreen);
        shadowOf(Looper.getMainLooper()).idle();
        assertThat(mPreference.getSummary().toString())
                .isEqualTo(mContext.getString(
                        R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
    }

    @Test
    public void displayPreference_noFallbackDeviceOrActiveInSharing_showEmptySummary() {
        Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID2);
        when(mBroadcast.isEnabled(any())).thenReturn(true);
        when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2));
        when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
        mController.displayPreference(mScreen);
        shadowOf(Looper.getMainLooper()).idle();
@@ -394,7 +430,7 @@ public class AudioSharingCallAudioPreferenceControllerTest {
    }

    @Test
    public void displayPreference_noFallbackDevice_showEmptySummary() {
    public void displayPreference_noFallbackOrActiveDevice_showEmptySummary() {
        Settings.Secure.putInt(
                mContentResolver, TEST_SETTINGS_KEY, BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
        when(mBroadcast.isEnabled(any())).thenReturn(true);
@@ -412,17 +448,11 @@ public class AudioSharingCallAudioPreferenceControllerTest {
            ShadowAlertDialogCompat.reset();
        }
        Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
        when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
        when(mCachedDevice2.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID2);
        when(mCachedDevice2.getName()).thenReturn(TEST_DEVICE_NAME2);
        when(mCachedDevice2.getDevice()).thenReturn(mDevice2);
        when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
        when(mCacheManager.findDevice(mDevice2)).thenReturn(mCachedDevice2);
        mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(List.of(mDevice1, mDevice2));
        mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(
                List.of(mDevice1, mDevice2, mDevice3));
        when(mBroadcast.isEnabled(any())).thenReturn(true);
        when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2));
        when(mAssistant.getAllConnectedDevices()).thenReturn(
                ImmutableList.of(mDevice1, mDevice2, mDevice3));
        when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
        mController.init(mParentFragment);
        mController.displayPreference(mScreen);
@@ -449,14 +479,9 @@ public class AudioSharingCallAudioPreferenceControllerTest {

    @Test
    public void logCallAudioDeviceChange_changeCallAudioToEarlierConnectedDevice() {
        when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
        when(mCachedDevice2.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID2);
        when(mCachedDevice2.getDevice()).thenReturn(mDevice2);
        when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
        when(mCacheManager.findDevice(mDevice2)).thenReturn(mCachedDevice2);
        mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(List.of(mDevice1, mDevice2));
        mController.logCallAudioDeviceChange(TEST_DEVICE_GROUP_ID1, mCachedDevice2);
        mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(
                List.of(mDevice1, mDevice2, mDevice3));
        mController.logCallAudioDeviceChange(TEST_DEVICE_GROUP_ID1, mCachedDevice3);
        verify(mFeatureFactory.metricsFeatureProvider)
                .action(
                        mContext,
@@ -468,13 +493,8 @@ public class AudioSharingCallAudioPreferenceControllerTest {

    @Test
    public void logCallAudioDeviceChange_changeCallAudioToLaterConnectedDevice() {
        when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
        when(mCachedDevice2.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID2);
        when(mCachedDevice2.getDevice()).thenReturn(mDevice2);
        when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
        when(mCacheManager.findDevice(mDevice2)).thenReturn(mCachedDevice2);
        mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(List.of(mDevice1, mDevice2));
        mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(
                List.of(mDevice1, mDevice2, mDevice3));
        mController.logCallAudioDeviceChange(TEST_DEVICE_GROUP_ID2, mCachedDevice1);
        verify(mFeatureFactory.metricsFeatureProvider)
                .action(
@@ -487,14 +507,8 @@ public class AudioSharingCallAudioPreferenceControllerTest {

    @Test
    public void logCallAudioDeviceChange_deviceNotFoundInRecentList_unknownChangeType() {
        when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
        when(mCachedDevice2.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID2);
        when(mCachedDevice2.getDevice()).thenReturn(mDevice2);
        when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
        when(mCacheManager.findDevice(mDevice2)).thenReturn(mCachedDevice2);
        mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(List.of(mDevice1));
        mController.logCallAudioDeviceChange(TEST_DEVICE_GROUP_ID1, mCachedDevice2);
        mShadowBluetoothAdapter.setMostRecentlyConnectedDevices(List.of(mDevice1, mDevice2));
        mController.logCallAudioDeviceChange(TEST_DEVICE_GROUP_ID1, mCachedDevice3);
        verify(mFeatureFactory.metricsFeatureProvider)
                .action(
                        mContext,
@@ -505,10 +519,6 @@ public class AudioSharingCallAudioPreferenceControllerTest {

    @Test
    public void testBluetoothLeBroadcastAssistantCallbacks_updateSummary() {
        when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
        when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
        when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
        Settings.Secure.putInt(
                mContentResolver, TEST_SETTINGS_KEY, BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
        when(mBroadcast.isEnabled(any())).thenReturn(true);
@@ -532,10 +542,6 @@ public class AudioSharingCallAudioPreferenceControllerTest {

    @Test
    public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() {
        when(mCachedDevice1.getGroupId()).thenReturn(TEST_DEVICE_GROUP_ID1);
        when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
        when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
        when(mCacheManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
        Settings.Secure.putInt(
                mContentResolver, TEST_SETTINGS_KEY, BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
        when(mBroadcast.isEnabled(any())).thenReturn(true);
+9 −0
Original line number Diff line number Diff line
@@ -78,4 +78,13 @@ public class AudioSharingDeviceItemTest {
        assertThat(itemFromParcel.getGroupId()).isEqualTo(TEST_GROUP_ID);
        assertThat(itemFromParcel.isActive()).isEqualTo(TEST_IS_ACTIVE);
    }

    @Test
    public void toString_correctValue() {
        AudioSharingDeviceItem item =
                new AudioSharingDeviceItem(TEST_NAME, TEST_GROUP_ID, TEST_IS_ACTIVE);
        assertThat(item.toString()).isEqualTo(
                "AudioSharingDeviceItem groupId = " + TEST_GROUP_ID + ", isActive = "
                        + TEST_IS_ACTIVE);
    }
}