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

This commit is contained in:
Yiyi Shen
2024-10-08 12:51:08 +00:00
committed by Android (Google) Code Review
4 changed files with 141 additions and 110 deletions

View File

@@ -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);
}
}
return checkedItemIndex;
}
for (AudioSharingDeviceItem item : deviceItems) {
if (item.isActive()) {
Log.d(TAG, "getActiveItemWithIndex, active LEA group = " + item.getGroupId());
return new Pair<>(deviceItems.indexOf(item), item);
}
}
return null;
}
@VisibleForTesting

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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);
}
}