diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java index 468ac3d5652..11a337fb616 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java @@ -219,7 +219,7 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP if (lead != null) { String addr = lead.getDevice().getAnonymizedAddress(); Log.d(TAG, "Set call audio device: " + addr); - lead.setActive(); + AudioSharingUtils.setPrimary(mContext, lead); logCallAudioDeviceChange(currentGroupId, lead); } else { Log.d(TAG, "Skip set call audio device: no lead"); diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java index db2c7b21b1b..47623e4f197 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java @@ -390,7 +390,7 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro Log.d(TAG, "onDeviceClick, set active in call mode"); CachedBluetoothDevice cachedDevice = ((BluetoothDevicePreference) preference).getBluetoothDevice(); - cachedDevice.setActive(); + AudioSharingUtils.setPrimary(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 396144ab16c..0c3448729b8 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java @@ -192,7 +192,7 @@ public class AudioSharingDialogHandler { // 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. - cachedDevice.setActive(); + AudioSharingUtils.setPrimary(mContext, cachedDevice); } return; } diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java index a662809fb78..592c8eb84c5 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java @@ -21,6 +21,7 @@ import static com.android.settings.connecteddevice.audiosharing.AudioSharingUtil import static com.android.settings.connecteddevice.audiosharing.AudioSharingUtils.MetricKey.METRIC_KEY_PAGE_ID; import static com.android.settings.connecteddevice.audiosharing.AudioSharingUtils.MetricKey.METRIC_KEY_SOURCE_PAGE_ID; import static com.android.settings.connecteddevice.audiosharing.AudioSharingUtils.MetricKey.METRIC_KEY_USER_TRIGGERED; +import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID; import static java.util.stream.Collectors.toList; @@ -28,6 +29,7 @@ import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeBroadcastMetadata; import android.content.Context; +import android.provider.Settings; import android.util.Log; import android.util.Pair; import android.widget.Toast; @@ -44,6 +46,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.settingslib.bluetooth.VolumeControlProfile; +import com.android.settingslib.flags.Flags; import java.util.ArrayList; import java.util.Comparator; @@ -344,6 +347,27 @@ public class AudioSharingUtils { return vc != null && vc.isProfileReady(); } + /** Set {@link CachedBluetoothDevice} as primary device for call audio */ + public static void setPrimary(@NonNull Context context, + @Nullable CachedBluetoothDevice cachedDevice) { + if (cachedDevice == null) return; + cachedDevice.setActive(); + if (Flags.audioSharingHysteresisModeFix()) { + int groupId = BluetoothUtils.getGroupId(cachedDevice); + // TODO: use real key name in SettingsProvider + int userPreferredId = Settings.Secure.getInt( + context.getContentResolver(), + BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID, + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + if (groupId != userPreferredId) { + Settings.Secure.putInt( + context.getContentResolver(), + BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID, + groupId); + } + } + } + /** * Build audio sharing dialog log event data * 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 61bc8aaa055..0bc0b949193 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java @@ -18,6 +18,7 @@ package com.android.settings.connecteddevice.audiosharing; import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE; import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; +import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID; import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.EXTRA_BLUETOOTH_DEVICE; import static com.google.common.truth.Truth.assertThat; @@ -37,6 +38,7 @@ import static org.robolectric.Shadows.shadowOf; import android.app.settings.SettingsEnums; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastMetadata; @@ -50,6 +52,7 @@ import android.media.AudioManager; import android.os.Bundle; import android.os.Looper; import android.platform.test.flag.junit.SetFlagsRule; +import android.provider.Settings; import android.util.Pair; import androidx.annotation.NonNull; @@ -587,6 +590,10 @@ public class AudioSharingDevicePreferenceControllerTest { @Test public void testInCallState_showCallStateTitleAndSetActiveOnDeviceClick() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); + Settings.Secure.putInt(mContext.getContentResolver(), + BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID, + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); mController.displayPreference(mScreen); mAudioManager.setMode(AudioManager.MODE_IN_CALL); @@ -599,6 +606,32 @@ public class AudioSharingDevicePreferenceControllerTest { BluetoothDevicePreference preference = createBluetoothDevicePreference(); mController.onDeviceClick(preference); verify(mCachedDevice).setActive(); + assertThat(Settings.Secure.getInt(mContext.getContentResolver(), + BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID, + BluetoothCsipSetCoordinator.GROUP_ID_INVALID)).isEqualTo( + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + } + + @Test + public void testInCallState_enableHysteresisFix_setAndSaveActiveOnDeviceClick() { + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); + Settings.Secure.putInt(mContext.getContentResolver(), + BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID, + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + mController.displayPreference(mScreen); + + mAudioManager.setMode(AudioManager.MODE_IN_CALL); + mController.onAudioModeChanged(); + shadowOf(Looper.getMainLooper()).idle(); + + BluetoothDevicePreference preference = createBluetoothDevicePreference(); + when(mCachedDevice.getGroupId()).thenReturn(1); + mController.onDeviceClick(preference); + verify(mCachedDevice).setActive(); + assertThat(Settings.Secure.getInt(mContext.getContentResolver(), + BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID, + BluetoothCsipSetCoordinator.GROUP_ID_INVALID)).isEqualTo(1); } @Test 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 ad6dd7f0754..c96a08623f8 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java @@ -16,6 +16,8 @@ package com.android.settings.connecteddevice.audiosharing; +import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -32,6 +34,7 @@ import static org.robolectric.Shadows.shadowOf; import android.app.settings.SettingsEnums; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeBroadcast; import android.bluetooth.BluetoothLeBroadcastMetadata; @@ -43,6 +46,7 @@ import android.media.AudioManager; import android.os.Bundle; import android.os.Looper; import android.platform.test.flag.junit.SetFlagsRule; +import android.provider.Settings; import android.util.Pair; import androidx.fragment.app.DialogFragment; @@ -193,6 +197,10 @@ public class AudioSharingDialogHandlerTest { @Test public void handleUserTriggeredDeviceConnected_inCall_setActive() { + mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); + Settings.Secure.putInt(mContext.getContentResolver(), + BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID, + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); setUpBroadcast(true); ImmutableList deviceList = ImmutableList.of(mDevice1); @@ -201,6 +209,29 @@ public class AudioSharingDialogHandlerTest { mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ true); shadowOf(Looper.getMainLooper()).idle(); verify(mCachedDevice1).setActive(); + assertThat(Settings.Secure.getInt(mContext.getContentResolver(), + BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID, + BluetoothCsipSetCoordinator.GROUP_ID_INVALID)).isEqualTo( + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + } + + @Test + public void handleUserTriggeredDeviceConnected_inCall_enableHysteresisFix_setAndSaveActive() { + mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX); + Settings.Secure.putInt(mContext.getContentResolver(), + BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID, + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); + setUpBroadcast(true); + ImmutableList deviceList = ImmutableList.of(mDevice1); + when(mAssistant.getAllConnectedDevices()).thenReturn(deviceList); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of()); + mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ true); + shadowOf(Looper.getMainLooper()).idle(); + verify(mCachedDevice1).setActive(); + assertThat(Settings.Secure.getInt(mContext.getContentResolver(), + BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID, + BluetoothCsipSetCoordinator.GROUP_ID_INVALID)).isEqualTo(1); } @Test