Merge "[Audiosharing] Save user preferred primary headset to SettingsProvider" into main
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
index 468ac3d..11a337f 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
@@ -219,7 +219,7 @@
                                         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 db2c7b2..47623e4 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
@@ -390,7 +390,7 @@
             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 396144a..0c34487 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
@@ -192,7 +192,7 @@
                     // 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 a662809..592c8eb 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.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.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.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 @@
         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 61bc8aa..0bc0b94 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 @@
 
 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 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.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 @@
     @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 @@
         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 ad6dd7f..c96a086 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 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.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 @@
 
     @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<BluetoothDevice> deviceList = ImmutableList.of(mDevice1);
@@ -201,6 +209,29 @@
         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<BluetoothDevice> 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