[Audiosharing] Use setBroadcastToUnicastFallbackGroup to set primary
Flag: com.android.settingslib.flags.adopt_primary_group_management_api
Test: atest
Bug: 381946931
Change-Id: Ib06dd2e202b07b9cdb25b1a671ee4d57246415ba
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
index 3130a0c..25180d8 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
@@ -16,6 +16,8 @@
package com.android.settings.connecteddevice.audiosharing;
+import static com.android.settingslib.Utils.isAudioModeOngoingCall;
+
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothCsipSetCoordinator;
@@ -48,6 +50,7 @@
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
@@ -91,6 +94,7 @@
Map<Integer, List<BluetoothDevice>> mGroupedConnectedDevices = new HashMap<>();
private List<AudioSharingDeviceItem> mDeviceItemsInSharingSession = new ArrayList<>();
private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
+ private AtomicBoolean mIsAudioModeOngoingCall = new AtomicBoolean(false);
@VisibleForTesting
final BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
@@ -202,28 +206,15 @@
mDeviceItemsInSharingSession,
pair == null ? -1 : pair.first,
(AudioSharingDeviceItem item) -> {
- int currentGroupId =
+ int currentCallAudioGroupId =
BluetoothUtils.getPrimaryGroupIdForBroadcast(
mContext.getContentResolver());
int clickedGroupId = item.getGroupId();
- if (clickedGroupId == currentGroupId) {
+ if (clickedGroupId == currentCallAudioGroupId) {
Log.d(TAG, "Skip set call audio device: unchanged");
return;
}
- List<BluetoothDevice> devices =
- mGroupedConnectedDevices.getOrDefault(
- clickedGroupId, ImmutableList.of());
- CachedBluetoothDevice lead =
- AudioSharingUtils.getLeadDevice(
- mCacheManager, devices);
- if (lead != null) {
- String addr = lead.getDevice().getAnonymizedAddress();
- Log.d(TAG, "Set call audio device: " + addr);
- AudioSharingUtils.setPrimary(mContext, lead);
- logCallAudioDeviceChange(currentGroupId, lead);
- } else {
- Log.d(TAG, "Skip set call audio device: no lead");
- }
+ setCallAudioGroup(clickedGroupId);
});
}
return true;
@@ -269,6 +260,11 @@
}
}
+ @Override
+ public void onAudioModeChanged() {
+ mIsAudioModeOngoingCall.set(isAudioModeOngoingCall(mContext));
+ }
+
/**
* Initialize the controller.
*
@@ -311,6 +307,7 @@
false,
mSettingsObserver);
mAssistant.registerServiceCallBack(mExecutor, mBroadcastAssistantCallback);
+ mIsAudioModeOngoingCall.set(isAudioModeOngoingCall(mContext));
mCallbacksRegistered.set(true);
}
}
@@ -333,6 +330,32 @@
}
}
+ private void setCallAudioGroup(int groupId) {
+ List<BluetoothDevice> devices =
+ mGroupedConnectedDevices.getOrDefault(
+ groupId, ImmutableList.of());
+ CachedBluetoothDevice lead =
+ AudioSharingUtils.getLeadDevice(
+ mCacheManager, devices);
+ if (lead != null) {
+ String addr = lead.getDevice().getAnonymizedAddress();
+ Log.d(TAG, "Set call audio device: " + addr);
+ if (Flags.adoptPrimaryGroupManagementApi() && !mIsAudioModeOngoingCall.get()) {
+ LeAudioProfile leaProfile = mBtManager == null ? null
+ : mBtManager.getProfileManager().getLeAudioProfile();
+ if (leaProfile != null) {
+ leaProfile.setBroadcastToUnicastFallbackGroup(groupId);
+ }
+ } else {
+ lead.setActive();
+ }
+ AudioSharingUtils.setUserPreferredPrimary(mContext, lead);
+ logCallAudioDeviceChange(groupId, lead);
+ } else {
+ Log.d(TAG, "Skip set call audio device: no lead");
+ }
+ }
+
/**
* Update the preference summary: current headset for call audio.
*
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
index c286ed6..ffbb13e 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
@@ -389,7 +389,8 @@
Log.d(TAG, "onDeviceClick, set active in call mode");
CachedBluetoothDevice cachedDevice =
((BluetoothDevicePreference) preference).getBluetoothDevice();
- AudioSharingUtils.setPrimary(mContext, cachedDevice);
+ cachedDevice.setActive();
+ AudioSharingUtils.setUserPreferredPrimary(mContext, cachedDevice);
}
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AUDIO_SHARING_DEVICE_CLICK,
isCallMode);
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
index 0c34487..2a1f4da 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
@@ -192,7 +192,8 @@
// If this method is called with user triggered, e.g. manual click on the
// "Connected devices" page, we need call setActive for the device, since user
// intend to switch active device for the call.
- AudioSharingUtils.setPrimary(mContext, cachedDevice);
+ cachedDevice.setActive();
+ AudioSharingUtils.setUserPreferredPrimary(mContext, cachedDevice);
}
return;
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java
index 5a15b6a..7824b26 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java
@@ -346,11 +346,10 @@
return vc != null && vc.isProfileReady();
}
- /** Set {@link CachedBluetoothDevice} as primary device for call audio */
- public static void setPrimary(
+ /** Set {@link CachedBluetoothDevice} as user preferred primary device for call audio */
+ public static void setUserPreferredPrimary(
@NonNull Context context, @Nullable CachedBluetoothDevice cachedDevice) {
if (cachedDevice == null) return;
- cachedDevice.setActive();
if (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(context)) {
int groupId = BluetoothUtils.getGroupId(cachedDevice);
// TODO: use real key name in SettingsProvider
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java
index 3075573..a2ac0cc 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java
@@ -24,6 +24,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -67,6 +68,7 @@
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -77,7 +79,6 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
import org.junit.After;
import org.junit.Before;
@@ -89,8 +90,10 @@
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowListView;
import org.robolectric.shadows.androidx.fragment.FragmentController;
import java.util.ArrayList;
@@ -483,19 +486,46 @@
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog.isShowing()).isTrue();
assertThat(dialog.getListView().getCount()).isEqualTo(2);
- ArrayList<View> outViews = new ArrayList<>();
- dialog.getListView()
- .findViewsWithText(outViews, TEST_DEVICE_NAME1, View.FIND_VIEWS_WITH_TEXT);
- assertThat(outViews.size()).isEqualTo(1);
- View view = Iterables.getOnlyElement(outViews);
- assertThat(view instanceof CheckedTextView).isTrue();
- assertThat(((CheckedTextView) view).isChecked()).isTrue();
+ ShadowListView listView = Shadows.shadowOf(dialog.getListView());
+ View view1 = listView.findItemContainingText(TEST_DEVICE_NAME1);
+ assertThat(view1).isNotNull();
+ assertThat(view1 instanceof CheckedTextView).isTrue();
+ assertThat(((CheckedTextView) view1).isChecked()).isTrue();
+ View view2 = listView.findItemContainingText(TEST_DEVICE_NAME2);
+ assertThat(view2).isNotNull();
+ assertThat(view2 instanceof CheckedTextView).isTrue();
+ assertThat(((CheckedTextView) view2).isChecked()).isFalse();
+
verify(mFeatureFactory.metricsFeatureProvider)
.visible(
/* context= */ eq(null),
/* source= */ anyInt(),
eq(SettingsEnums.DIALOG_AUDIO_SHARING_CALL_AUDIO),
/* latency= */ anyInt());
+
+ LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
+ when(mBtProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
+
+ // Perform click to switch call audio device by set active
+ mSetFlagsRule.disableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API);
+ int index = listView.findIndexOfItemContainingText(TEST_DEVICE_NAME2);
+ listView.performItemClick(index);
+ shadowOf(Looper.getMainLooper()).idle();
+ assertThat(((CheckedTextView) view1).isChecked()).isFalse();
+ assertThat(((CheckedTextView) view2).isChecked()).isTrue();
+ verify(mCachedDevice3).setActive();
+ verify(leAudioProfile, never()).setBroadcastToUnicastFallbackGroup(TEST_DEVICE_GROUP_ID2);
+
+ // Perform click to switch call audio device with API
+ mSetFlagsRule.enableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API);
+ Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID2);
+ index = listView.findIndexOfItemContainingText(TEST_DEVICE_NAME1);
+ listView.performItemClick(index);
+ shadowOf(Looper.getMainLooper()).idle();
+ assertThat(((CheckedTextView) view1).isChecked()).isTrue();
+ assertThat(((CheckedTextView) view2).isChecked()).isFalse();
+ verify(mCachedDevice1, never()).setActive();
+ verify(leAudioProfile).setBroadcastToUnicastFallbackGroup(TEST_DEVICE_GROUP_ID1);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
index a49d0c1..4a4a167 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
@@ -584,6 +584,7 @@
public void testInCallState_showCallStateTitleAndSetActiveOnDeviceClick() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API);
Settings.Secure.putInt(mContext.getContentResolver(),
BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID,
BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
@@ -609,6 +610,7 @@
public void testInCallState_enableHysteresisFix_setAndSaveActiveOnDeviceClick() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API);
Settings.Secure.putInt(mContext.getContentResolver(),
BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID,
BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java
index c96a086..b609cdd 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java
@@ -198,6 +198,7 @@
@Test
public void handleUserTriggeredDeviceConnected_inCall_setActive() {
mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API);
Settings.Secure.putInt(mContext.getContentResolver(),
BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID,
BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
@@ -218,6 +219,7 @@
@Test
public void handleUserTriggeredDeviceConnected_inCall_enableHysteresisFix_setAndSaveActive() {
mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API);
Settings.Secure.putInt(mContext.getContentResolver(),
BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID,
BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
@@ -452,6 +454,7 @@
@Test
public void handleDeviceConnected_inCall_doNothing() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API);
when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL);
setUpBroadcast(true);
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of());