[Audiosharing] Increase audio sharing test coverage

Bug: 345686602
Test: atest
Change-Id: Iec196fc884c3b7ddd580eb8dd13b445d59e3b1b7
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
index b623ba8..6ba7183 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java
@@ -72,7 +72,7 @@
     private static final String PREF_KEY = "calls_and_alarms";
 
     @VisibleForTesting
-    protected enum ChangeCallAudioType {
+    enum ChangeCallAudioType {
         UNKNOWN,
         CONNECTED_EARLIER,
         CONNECTED_LATER
@@ -90,7 +90,9 @@
     Map<Integer, List<CachedBluetoothDevice>> mGroupedConnectedDevices = new HashMap<>();
     private List<AudioSharingDeviceItem> mDeviceItemsInSharingSession = new ArrayList<>();
     private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
-    private final BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
+
+    @VisibleForTesting
+    final BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
             new BluetoothLeBroadcastAssistant.Callback() {
                 @Override
                 public void onSearchStarted(int reason) {}
@@ -276,7 +278,7 @@
 
     /** Test only: set callback registration status in tests. */
     @VisibleForTesting
-    public void setCallbacksRegistered(boolean registered) {
+    void setCallbacksRegistered(boolean registered) {
         mCallbacksRegistered.set(registered);
     }
 
@@ -385,7 +387,7 @@
     }
 
     @VisibleForTesting
-    protected void logCallAudioDeviceChange(int currentGroupId, CachedBluetoothDevice target) {
+    void logCallAudioDeviceChange(int currentGroupId, CachedBluetoothDevice target) {
         var unused =
                 ThreadUtils.postOnBackgroundThread(
                         () -> {
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
index 51a8e11..b932a7e 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
@@ -87,7 +87,8 @@
     @Nullable private AudioSharingDialogHandler mDialogHandler;
     private AtomicBoolean mIntentHandled = new AtomicBoolean(false);
 
-    private BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
+    @VisibleForTesting
+    BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
             new BluetoothLeBroadcastAssistant.Callback() {
                 @Override
                 public void onSearchStarted(int reason) {}
@@ -368,23 +369,23 @@
     }
 
     @VisibleForTesting
-    public void setBluetoothDeviceUpdater(@Nullable BluetoothDeviceUpdater bluetoothDeviceUpdater) {
+    void setBluetoothDeviceUpdater(@Nullable BluetoothDeviceUpdater bluetoothDeviceUpdater) {
         mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
     }
 
     @VisibleForTesting
-    public void setDialogHandler(@Nullable AudioSharingDialogHandler dialogHandler) {
+    void setDialogHandler(@Nullable AudioSharingDialogHandler dialogHandler) {
         mDialogHandler = dialogHandler;
     }
 
     @VisibleForTesting
-    public void setHostFragment(@Nullable DashboardFragment fragment) {
+    void setHostFragment(@Nullable DashboardFragment fragment) {
         mFragment = fragment;
     }
 
     /** Test only: set intent handle state for test. */
     @VisibleForTesting
-    public void setIntentHandled(boolean handled) {
+    void setIntentHandled(boolean handled) {
         mIntentHandled.set(handled);
     }
 
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java
index 4a067ac..ee2ba7b 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java
@@ -79,13 +79,10 @@
     private Map<Integer, Integer> mValueMap = new HashMap<Integer, Integer>();
     private AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
 
-    private BluetoothVolumeControl.Callback mVolumeControlCallback =
+    @VisibleForTesting
+    BluetoothVolumeControl.Callback mVolumeControlCallback =
             new BluetoothVolumeControl.Callback() {
                 @Override
-                public void onVolumeOffsetChanged(
-                        @NonNull BluetoothDevice device, int volumeOffset) {}
-
-                @Override
                 public void onDeviceVolumeChanged(
                         @NonNull BluetoothDevice device,
                         @IntRange(from = -255, to = 255) int volume) {
@@ -117,7 +114,8 @@
                 }
             };
 
-    private BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
+    @VisibleForTesting
+    BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
             new BluetoothLeBroadcastAssistant.Callback() {
                 @Override
                 public void onSearchStarted(int reason) {}
@@ -323,26 +321,26 @@
     }
 
     @VisibleForTesting
-    public void setDeviceUpdater(@Nullable AudioSharingDeviceVolumeControlUpdater updater) {
+    void setDeviceUpdater(@Nullable AudioSharingDeviceVolumeControlUpdater updater) {
         mBluetoothDeviceUpdater = updater;
     }
 
     /** Test only: set callback registration status in tests. */
     @VisibleForTesting
-    public void setCallbacksRegistered(boolean registered) {
+    void setCallbacksRegistered(boolean registered) {
         mCallbacksRegistered.set(registered);
     }
 
     /** Test only: set volume map in tests. */
     @VisibleForTesting
-    public void setVolumeMap(@Nullable Map<Integer, Integer> map) {
+    void setVolumeMap(@Nullable Map<Integer, Integer> map) {
         mValueMap.clear();
         mValueMap.putAll(map);
     }
 
     /** Test only: set value for private preferenceGroup in tests. */
     @VisibleForTesting
-    public void setPreferenceGroup(@Nullable PreferenceGroup group) {
+    void setPreferenceGroup(@Nullable PreferenceGroup group) {
         mPreferenceGroup = group;
         mPreference = group;
     }
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java
index 165beae..2ee286d 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFactory.java
@@ -345,4 +345,6 @@
             return dialog;
         }
     }
+
+    private AudioSharingDialogFactory() {}
 }
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
index 5458a9f..8d69cf6 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java
@@ -28,6 +28,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.DialogFragment;
 import androidx.fragment.app.Fragment;
 
@@ -61,7 +62,8 @@
     private final MetricsFeatureProvider mMetricsFeatureProvider;
     private List<BluetoothDevice> mTargetSinks = new ArrayList<>();
 
-    private final BluetoothLeBroadcast.Callback mBroadcastCallback =
+    @VisibleForTesting
+    final BluetoothLeBroadcast.Callback mBroadcastCallback =
             new BluetoothLeBroadcast.Callback() {
                 @Override
                 public void onBroadcastStarted(int reason, int broadcastId) {
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java
index 5f6d84a..dcd8a3b 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDisconnectDialogFragment.java
@@ -145,9 +145,17 @@
         return sNewDevice;
     }
 
+    /** Test only: get the {@link DialogEventListener} passed to the dialog. */
+    @VisibleForTesting
+    @Nullable
+    DialogEventListener getListener() {
+        return sListener;
+    }
+
     /** Test only: get the event data passed to the dialog. */
     @VisibleForTesting
-    protected @NonNull Pair<Integer, Object>[] getEventData() {
+    @NonNull
+    Pair<Integer, Object>[] getEventData() {
         return sEventData;
     }
 
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java
index 7eebbcb..ec669bf 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinDialogFragment.java
@@ -110,9 +110,17 @@
         return sNewDevice;
     }
 
+    /** Test only: get the {@link DialogEventListener} passed to the dialog. */
+    @VisibleForTesting
+    @Nullable
+    DialogEventListener getListener() {
+        return sListener;
+    }
+
     /** Test only: get the event data passed to the dialog. */
     @VisibleForTesting
-    protected @NonNull Pair<Integer, Object>[] getEventData() {
+    @NonNull
+    Pair<Integer, Object>[] getEventData() {
         return sEventData;
     }
 
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
index 5022579..89d2c95 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
@@ -117,7 +117,7 @@
             };
 
     @VisibleForTesting
-    protected final BluetoothLeBroadcast.Callback mBroadcastCallback =
+    final BluetoothLeBroadcast.Callback mBroadcastCallback =
             new BluetoothLeBroadcast.Callback() {
                 @Override
                 public void onBroadcastStarted(int reason, int broadcastId) {
@@ -392,7 +392,7 @@
 
     /** Test only: set callback registration status in tests. */
     @VisibleForTesting
-    public void setCallbacksRegistered(boolean registered) {
+    void setCallbacksRegistered(boolean registered) {
         mCallbacksRegistered.set(registered);
     }
 
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 af817d2..aba0a79 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java
@@ -25,7 +25,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
@@ -35,6 +35,7 @@
 import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothLeBroadcastAssistant;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
 import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothStatusCodes;
@@ -130,6 +131,7 @@
     @Mock private CachedBluetoothDevice mCachedDevice2;
     @Mock private CachedBluetoothDevice mCachedDevice3;
     @Mock private BluetoothLeBroadcastReceiveState mState;
+    @Mock private BluetoothLeBroadcastMetadata mSource;
     @Mock private ContentResolver mContentResolver;
     private AudioSharingCallAudioPreferenceController mController;
     @Spy private ContentObserver mContentObserver;
@@ -183,13 +185,13 @@
     public void onStart_flagOff_doNothing() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.onStart(mLifecycleOwner);
-        verify(mBtEventManager, times(0)).registerCallback(mController);
-        verify(mContentResolver, times(0))
+        verify(mBtEventManager, never()).registerCallback(mController);
+        verify(mContentResolver, never())
                 .registerContentObserver(
                         Settings.Secure.getUriFor(SETTINGS_KEY_FALLBACK_DEVICE_GROUP_ID),
                         false,
                         mContentObserver);
-        verify(mAssistant, times(0))
+        verify(mAssistant, never())
                 .registerServiceCallBack(any(), any(BluetoothLeBroadcastAssistant.Callback.class));
     }
 
@@ -212,9 +214,9 @@
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.setCallbacksRegistered(true);
         mController.onStop(mLifecycleOwner);
-        verify(mBtEventManager, times(0)).unregisterCallback(mController);
-        verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver);
-        verify(mAssistant, times(0))
+        verify(mBtEventManager, never()).unregisterCallback(mController);
+        verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
+        verify(mAssistant, never())
                 .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
     }
 
@@ -223,9 +225,9 @@
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.setCallbacksRegistered(false);
         mController.onStop(mLifecycleOwner);
-        verify(mBtEventManager, times(0)).unregisterCallback(mController);
-        verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver);
-        verify(mAssistant, times(0))
+        verify(mBtEventManager, never()).unregisterCallback(mController);
+        verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
+        verify(mAssistant, never())
                 .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
     }
 
@@ -500,4 +502,80 @@
                         AudioSharingCallAudioPreferenceController.ChangeCallAudioType.UNKNOWN
                                 .ordinal());
     }
+
+    @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);
+        when(mAssistant.getDevicesMatchingConnectionStates(
+                        new int[] {BluetoothProfile.STATE_CONNECTED}))
+                .thenReturn(ImmutableList.of());
+        mController.displayPreference(mScreen);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreference.getSummary().toString()).isEmpty();
+
+        // onReceiveStateChanged will update summary
+        Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
+        when(mAssistant.getDevicesMatchingConnectionStates(
+                        new int[] {BluetoothProfile.STATE_CONNECTED}))
+                .thenReturn(ImmutableList.of(mDevice1));
+        when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
+        mController.mBroadcastAssistantCallback.onReceiveStateChanged(
+                mDevice1, /* sourceId= */ 1, mState);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreference.getSummary().toString())
+                .isEqualTo(
+                        mContext.getString(
+                                R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1));
+    }
+
+    @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);
+        when(mAssistant.getDevicesMatchingConnectionStates(
+                        new int[] {BluetoothProfile.STATE_CONNECTED}))
+                .thenReturn(ImmutableList.of());
+        mController.displayPreference(mScreen);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreference.getSummary().toString()).isEmpty();
+
+        Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
+        when(mAssistant.getDevicesMatchingConnectionStates(
+                        new int[] {BluetoothProfile.STATE_CONNECTED}))
+                .thenReturn(ImmutableList.of(mDevice1));
+        when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
+        mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceAdded(
+                mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceAddFailed(
+                mDevice1, mSource, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceRemoved(
+                mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
+                mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceModified(
+                mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceModifyFailed(
+                mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceFound(mSource);
+        mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
+        shadowOf(Looper.getMainLooper()).idle();
+
+        // Above callbacks won't update summary.
+        assertThat(mPreference.getSummary().toString()).isEmpty();
+    }
 }
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 14bca08..eb29b50 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -35,6 +36,8 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothLeBroadcastAssistant;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothStatusCodes;
 import android.content.Context;
@@ -85,6 +88,8 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.shadow.api.Shadow;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.Executor;
 
 @RunWith(RobolectricTestRunner.class)
@@ -113,6 +118,8 @@
     @Mock private LocalBluetoothLeBroadcast mBroadcast;
     @Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
     @Mock private VolumeControlProfile mVolumeControl;
+    @Mock private BluetoothLeBroadcastReceiveState mState;
+    @Mock private BluetoothLeBroadcastMetadata mSource;
     @Mock private PreferenceScreen mScreen;
     @Mock private AudioSharingDialogHandler mDialogHandler;
     @Mock private DashboardFragment mFragment;
@@ -177,13 +184,13 @@
     public void onStart_flagOff_doNothing() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.onStart(mLifecycleOwner);
-        verify(mEventManager, times(0)).registerCallback(any(BluetoothCallback.class));
-        verify(mDialogHandler, times(0)).registerCallbacks(any(Executor.class));
-        verify(mAssistant, times(0))
+        verify(mEventManager, never()).registerCallback(any(BluetoothCallback.class));
+        verify(mDialogHandler, never()).registerCallbacks(any(Executor.class));
+        verify(mAssistant, never())
                 .registerServiceCallBack(
                         any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
-        verify(mBluetoothDeviceUpdater, times(0)).registerCallback();
-        verify(mBluetoothDeviceUpdater, times(0)).refreshPreference();
+        verify(mBluetoothDeviceUpdater, never()).registerCallback();
+        verify(mBluetoothDeviceUpdater, never()).refreshPreference();
     }
 
     @Test
@@ -203,11 +210,11 @@
     public void onStop_flagOff_doNothing() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.onStop(mLifecycleOwner);
-        verify(mEventManager, times(0)).unregisterCallback(any(BluetoothCallback.class));
-        verify(mDialogHandler, times(0)).unregisterCallbacks();
-        verify(mAssistant, times(0))
+        verify(mEventManager, never()).unregisterCallback(any(BluetoothCallback.class));
+        verify(mDialogHandler, never()).unregisterCallbacks();
+        verify(mAssistant, never())
                 .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
-        verify(mBluetoothDeviceUpdater, times(0)).unregisterCallback();
+        verify(mBluetoothDeviceUpdater, never()).unregisterCallback();
     }
 
     @Test
@@ -227,7 +234,7 @@
         mController.displayPreference(mScreen);
         assertThat(mPreferenceGroup.isVisible()).isFalse();
         assertThat(mAudioSharingPreference.isVisible()).isFalse();
-        verify(mBluetoothDeviceUpdater, times(0)).forceUpdate();
+        verify(mBluetoothDeviceUpdater, never()).forceUpdate();
     }
 
     @Test
@@ -401,8 +408,8 @@
         doReturn(intent).when(mActivity).getIntent();
         mController.displayPreference(mScreen);
 
-        verify(mDeviceManager, times(0)).findDevice(any(BluetoothDevice.class));
-        verify(mDialogHandler, times(0))
+        verify(mDeviceManager, never()).findDevice(any(BluetoothDevice.class));
+        verify(mDialogHandler, never())
                 .handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean());
     }
 
@@ -418,8 +425,8 @@
         when(mDevice.isConnected()).thenReturn(false);
         mController.displayPreference(mScreen);
 
-        verify(mDeviceManager, times(0)).findDevice(any(BluetoothDevice.class));
-        verify(mDialogHandler, times(0))
+        verify(mDeviceManager, never()).findDevice(any(BluetoothDevice.class));
+        verify(mDialogHandler, never())
                 .handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean());
     }
 
@@ -436,8 +443,8 @@
         mController.setIntentHandled(true);
         mController.displayPreference(mScreen);
 
-        verify(mDeviceManager, times(0)).findDevice(any(BluetoothDevice.class));
-        verify(mDialogHandler, times(0))
+        verify(mDeviceManager, never()).findDevice(any(BluetoothDevice.class));
+        verify(mDialogHandler, never())
                 .handleDeviceConnected(any(CachedBluetoothDevice.class), anyBoolean());
     }
 
@@ -484,4 +491,56 @@
 
         verify(mDialogHandler).handleDeviceConnected(mCachedDevice, true);
     }
+
+    @Test
+    public void testBluetoothLeBroadcastAssistantCallbacks_updateGroup() {
+        // onReceiveStateChanged with unconnected state will do nothing
+        when(mState.getBisSyncState()).thenReturn(new ArrayList<>());
+        mController.mBroadcastAssistantCallback.onReceiveStateChanged(
+                mDevice, /* sourceId= */ 1, mState);
+        shadowOf(Looper.getMainLooper()).idle();
+        verify(mBluetoothDeviceUpdater, never()).forceUpdate();
+        verify(mDialogHandler, never()).closeOpeningDialogsForLeaDevice(mCachedDevice);
+
+        // onReceiveStateChanged with connected state will update group preference and handle
+        // stale dialogs
+        List<Long> bisSyncState = new ArrayList<>();
+        bisSyncState.add(1L);
+        when(mState.getBisSyncState()).thenReturn(bisSyncState);
+        mController.mBroadcastAssistantCallback.onReceiveStateChanged(
+                mDevice, /* sourceId= */ 1, mState);
+        shadowOf(Looper.getMainLooper()).idle();
+        verify(mBluetoothDeviceUpdater).forceUpdate();
+        verify(mDialogHandler).closeOpeningDialogsForLeaDevice(mCachedDevice);
+
+        // onSourceRemoved will update group preference
+        mController.mBroadcastAssistantCallback.onSourceRemoved(
+                mDevice, /* sourceId= */ 1, /* reason= */ 1);
+        shadowOf(Looper.getMainLooper()).idle();
+        verify(mBluetoothDeviceUpdater, times(2)).forceUpdate();
+    }
+
+    @Test
+    public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() {
+        mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceAdded(
+                mDevice, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceAddFailed(
+                mDevice, mSource, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
+                mDevice, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceModified(
+                mDevice, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceModifyFailed(
+                mDevice, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceFound(mSource);
+        mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
+        shadowOf(Looper.getMainLooper()).idle();
+
+        // Above callbacks won't update group preference
+        verify(mBluetoothDeviceUpdater, never()).forceUpdate();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java
index 7a21f02..65a0492 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeControlUpdaterTest.java
@@ -22,6 +22,7 @@
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoInteractions;
@@ -41,6 +42,7 @@
 import androidx.preference.Preference;
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.settings.bluetooth.BluetoothDevicePreference;
 import com.android.settings.bluetooth.Utils;
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
 import com.android.settings.testutils.FakeFeatureFactory;
@@ -80,6 +82,9 @@
     private static final String TEST_SETTINGS_KEY =
             "bluetooth_le_broadcast_fallback_active_group_id";
     private static final int TEST_DEVICE_GROUP_ID = 1;
+    private static final int TEST_VOLUME_VALUE = 255;
+    private static final int TEST_MAX_STREAM_VALUE = 10;
+    private static final int TEST_MIN_STREAM_VALUE = 0;
 
     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
 
@@ -249,10 +254,11 @@
                 (AudioSharingDeviceVolumePreference) captor.getValue();
 
         SeekBar seekBar = mock(SeekBar.class);
-        when(seekBar.getProgress()).thenReturn(255);
+        when(seekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE);
         preference.onStopTrackingTouch(seekBar);
 
-        verify(mVolumeControl).setDeviceVolume(mBluetoothDevice, 255, true);
+        verify(mVolumeControl)
+                .setDeviceVolume(mBluetoothDevice, TEST_VOLUME_VALUE, /* isGroupOp= */ true);
         verifyNoInteractions(mAudioManager);
         verify(mFeatureFactory.metricsFeatureProvider)
                 .action(
@@ -273,14 +279,17 @@
 
         Settings.Secure.putInt(
                 mContext.getContentResolver(), TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID);
-        when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)).thenReturn(10);
-        when(mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC)).thenReturn(0);
+        when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+                .thenReturn(TEST_MAX_STREAM_VALUE);
+        when(mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC))
+                .thenReturn(TEST_MIN_STREAM_VALUE);
         SeekBar seekBar = mock(SeekBar.class);
-        when(seekBar.getProgress()).thenReturn(255);
+        when(seekBar.getProgress()).thenReturn(TEST_VOLUME_VALUE);
         preference.onStopTrackingTouch(seekBar);
 
         verifyNoInteractions(mVolumeControl);
-        verify(mAudioManager).setStreamVolume(AudioManager.STREAM_MUSIC, 10, 0);
+        verify(mAudioManager)
+                .setStreamVolume(AudioManager.STREAM_MUSIC, TEST_MAX_STREAM_VALUE, /* flags= */ 0);
         verify(mFeatureFactory.metricsFeatureProvider)
                 .action(
                         mContext,
@@ -289,6 +298,22 @@
     }
 
     @Test
+    public void testOnSeekBarChangeListener_doNothing() {
+        ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
+        setupPreferenceMapWithDevice();
+
+        verify(mDevicePreferenceCallback).onDeviceAdded(captor.capture());
+        assertThat(captor.getValue() instanceof AudioSharingDeviceVolumePreference).isTrue();
+        AudioSharingDeviceVolumePreference preference =
+                (AudioSharingDeviceVolumePreference) captor.getValue();
+        SeekBar seekBar = mock(SeekBar.class);
+        preference.onProgressChanged(seekBar, TEST_VOLUME_VALUE, /* fromUser= */ false);
+
+        verifyNoInteractions(mAudioManager);
+        verifyNoInteractions(mVolumeControl);
+    }
+
+    @Test
     public void getLogTag_returnsCorrectTag() {
         assertThat(mDeviceUpdater.getLogTag()).isEqualTo(TAG);
     }
@@ -298,6 +323,35 @@
         assertThat(mDeviceUpdater.getPreferenceKey()).isEqualTo(PREF_KEY);
     }
 
+    @Test
+    public void addPreferenceWithSortType_doNothing() {
+        mDeviceUpdater.addPreference(
+                mCachedBluetoothDevice, BluetoothDevicePreference.SortType.TYPE_DEFAULT);
+        // Verify AudioSharingDeviceVolumeControlUpdater overrides BluetoothDeviceUpdater and won't
+        // trigger add preference.
+        verifyNoInteractions(mDevicePreferenceCallback);
+    }
+
+    @Test
+    public void launchDeviceDetails_doNothing() {
+        Preference preference = mock(Preference.class);
+        mDeviceUpdater.launchDeviceDetails(preference);
+        // Verify AudioSharingDeviceVolumeControlUpdater overrides BluetoothDeviceUpdater and won't
+        // launch device details
+        verifyNoInteractions(preference);
+    }
+
+    @Test
+    public void refreshPreference_doNothing() {
+        setupPreferenceMapWithDevice();
+        verify(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class));
+        when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(ImmutableList.of());
+        mDeviceUpdater.refreshPreference();
+        // Verify AudioSharingDeviceVolumeControlUpdater overrides BluetoothDeviceUpdater and won't
+        // refresh preference map
+        verify(mDevicePreferenceCallback, never()).onDeviceRemoved(any(Preference.class));
+    }
+
     private void setupPreferenceMapWithDevice() {
         // Add device to preferenceMap
         when(mBroadcast.isEnabled(null)).thenReturn(true);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java
index 7c8709c..d5dfb50 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -34,6 +35,8 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothLeBroadcastAssistant;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.BluetoothStatusCodes;
 import android.bluetooth.BluetoothVolumeControl;
 import android.content.ContentResolver;
@@ -81,6 +84,8 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.shadow.api.Shadow;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.Executor;
 
 @RunWith(RobolectricTestRunner.class)
@@ -114,6 +119,8 @@
     @Mock private LocalBluetoothProfileManager mProfileManager;
     @Mock private LocalBluetoothLeBroadcast mBroadcast;
     @Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
+    @Mock private BluetoothLeBroadcastReceiveState mState;
+    @Mock private BluetoothLeBroadcastMetadata mSource;
     @Mock private AudioSharingDeviceVolumeControlUpdater mDeviceUpdater;
     @Mock private VolumeControlProfile mVolumeControl;
     @Mock private PreferenceScreen mScreen;
@@ -164,6 +171,7 @@
         doReturn(TEST_DEVICE_GROUP_ID1).when(mCachedDevice1).getGroupId();
         doReturn(mDevice1).when(mCachedDevice1).getDevice();
         doReturn(ImmutableSet.of()).when(mCachedDevice1).getMemberDevice();
+        when(mCachedDeviceManager.findDevice(mDevice1)).thenReturn(mCachedDevice1);
         when(mPreference1.getCachedDevice()).thenReturn(mCachedDevice1);
         doReturn(TEST_DEVICE_NAME2).when(mCachedDevice2).getName();
         doReturn(TEST_DEVICE_GROUP_ID2).when(mCachedDevice2).getGroupId();
@@ -185,13 +193,13 @@
     public void onStart_flagOff_doNothing() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.onStart(mLifecycleOwner);
-        verify(mAssistant, times(0))
+        verify(mAssistant, never())
                 .registerServiceCallBack(
                         any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
-        verify(mDeviceUpdater, times(0)).registerCallback();
-        verify(mVolumeControl, times(0))
+        verify(mDeviceUpdater, never()).registerCallback();
+        verify(mVolumeControl, never())
                 .registerCallback(any(Executor.class), any(BluetoothVolumeControl.Callback.class));
-        verify(mContentResolver, times(0))
+        verify(mContentResolver, never())
                 .registerContentObserver(
                         Settings.Secure.getUriFor(SETTINGS_KEY_FALLBACK_DEVICE_GROUP_ID),
                         false,
@@ -216,15 +224,32 @@
     }
 
     @Test
+    public void onAudioSharingProfilesConnected_flagOn_registerCallbacks() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        mController.onAudioSharingProfilesConnected();
+        verify(mAssistant)
+                .registerServiceCallBack(
+                        any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
+        verify(mDeviceUpdater).registerCallback();
+        verify(mVolumeControl)
+                .registerCallback(any(Executor.class), any(BluetoothVolumeControl.Callback.class));
+        verify(mContentResolver)
+                .registerContentObserver(
+                        Settings.Secure.getUriFor(SETTINGS_KEY_FALLBACK_DEVICE_GROUP_ID),
+                        false,
+                        mContentObserver);
+    }
+
+    @Test
     public void onStop_flagOff_doNothing() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.onStop(mLifecycleOwner);
-        verify(mAssistant, times(0))
+        verify(mAssistant, never())
                 .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
-        verify(mDeviceUpdater, times(0)).unregisterCallback();
-        verify(mVolumeControl, times(0))
+        verify(mDeviceUpdater, never()).unregisterCallback();
+        verify(mVolumeControl, never())
                 .unregisterCallback(any(BluetoothVolumeControl.Callback.class));
-        verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver);
+        verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
     }
 
     @Test
@@ -232,12 +257,12 @@
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.setCallbacksRegistered(false);
         mController.onStop(mLifecycleOwner);
-        verify(mAssistant, times(0))
+        verify(mAssistant, never())
                 .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
-        verify(mDeviceUpdater, times(0)).unregisterCallback();
-        verify(mVolumeControl, times(0))
+        verify(mDeviceUpdater, never()).unregisterCallback();
+        verify(mVolumeControl, never())
                 .unregisterCallback(any(BluetoothVolumeControl.Callback.class));
-        verify(mContentResolver, times(0)).unregisterContentObserver(mContentObserver);
+        verify(mContentResolver, never()).unregisterContentObserver(mContentObserver);
     }
 
     @Test
@@ -257,7 +282,7 @@
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.displayPreference(mScreen);
         assertThat(mPreferenceGroup.isVisible()).isFalse();
-        verify(mDeviceUpdater, times(0)).forceUpdate();
+        verify(mDeviceUpdater, never()).forceUpdate();
     }
 
     @Test
@@ -324,7 +349,7 @@
         mPreferenceGroup.addPreference(mPreference1);
         mController.setPreferenceGroup(mPreferenceGroup);
         mController.onDeviceRemoved(mPreference1);
-        verify(mPreferenceGroup, times(0)).setVisible(false);
+        verify(mPreferenceGroup, never()).setVisible(false);
         assertThat(mPreferenceGroup.isVisible()).isTrue();
     }
 
@@ -344,7 +369,7 @@
         mController.updateVisibility();
         shadowOf(Looper.getMainLooper()).idle();
 
-        verify(mPreferenceGroup, times(0)).setVisible(anyBoolean());
+        verify(mPreferenceGroup, never()).setVisible(anyBoolean());
     }
 
     @Test
@@ -411,4 +436,64 @@
         verify(mPreference1).setOrder(0);
         verify(mPreference2).setOrder(1);
     }
+
+    @Test
+    public void onDeviceVolumeChanged_updatePreference() {
+        when(mPreference1.getProgress()).thenReturn(TEST_MAX_VOLUME_VALUE);
+        mController.setPreferenceGroup(mPreferenceGroup);
+        mController.onDeviceAdded(mPreference1);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
+
+        mController.mVolumeControlCallback.onDeviceVolumeChanged(mDevice1, TEST_VOLUME_VALUE);
+        shadowOf(Looper.getMainLooper()).idle();
+
+        verify(mPreference1).setProgress(TEST_VOLUME_VALUE);
+    }
+
+    @Test
+    public void testBluetoothLeBroadcastAssistantCallbacks_updateGroup() {
+        when(mState.getBisSyncState()).thenReturn(new ArrayList<>());
+        // onReceiveStateChanged with unconnected state will do nothing
+        mController.mBroadcastAssistantCallback.onReceiveStateChanged(
+                mDevice1, /* sourceId= */ 1, mState);
+        verify(mDeviceUpdater, never()).forceUpdate();
+
+        // onReceiveStateChanged with connected state will update group preference
+        List<Long> bisSyncState = new ArrayList<>();
+        bisSyncState.add(1L);
+        when(mState.getBisSyncState()).thenReturn(bisSyncState);
+        mController.mBroadcastAssistantCallback.onReceiveStateChanged(
+                mDevice1, /* sourceId= */ 1, mState);
+        verify(mDeviceUpdater).forceUpdate();
+
+        // onSourceRemoved will update group preference
+        mController.mBroadcastAssistantCallback.onSourceRemoved(
+                mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+        verify(mDeviceUpdater, times(2)).forceUpdate();
+    }
+
+    @Test
+    public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() {
+        mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceAdded(
+                mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceAddFailed(
+                mDevice1, mSource, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceRemoveFailed(
+                mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceModified(
+                mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceModifyFailed(
+                mDevice1, /* sourceId= */ 1, /* reason= */ 1);
+        mController.mBroadcastAssistantCallback.onSourceFound(mSource);
+        mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1);
+        shadowOf(Looper.getMainLooper()).idle();
+
+        // Above callbacks won't update group preference
+        verify(mDeviceUpdater, never()).forceUpdate();
+    }
 }
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 633bc06..00e210d 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandlerTest.java
@@ -19,7 +19,11 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+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;
 import static org.robolectric.Shadows.shadowOf;
@@ -27,6 +31,8 @@
 import android.app.settings.SettingsEnums;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeBroadcast;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
 import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothStatusCodes;
@@ -38,7 +44,6 @@
 import androidx.fragment.app.DialogFragment;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
-import androidx.test.core.app.ApplicationProvider;
 
 import com.android.settings.bluetooth.Utils;
 import com.android.settings.testutils.FakeFeatureFactory;
@@ -71,6 +76,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 @RunWith(RobolectricTestRunner.class)
 @Config(
@@ -82,6 +88,7 @@
     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
+    private static final int TEST_SOURCE_ID = 1;
     private static final String TEST_DEVICE_NAME1 = "test1";
     private static final String TEST_DEVICE_NAME2 = "test2";
     private static final String TEST_DEVICE_NAME3 = "test3";
@@ -109,15 +116,22 @@
     @Mock private BluetoothDevice mDevice3;
     @Mock private BluetoothDevice mDevice4;
     @Mock private LeAudioProfile mLeAudioProfile;
-    private Fragment mParentFragment;
     @Mock private BluetoothLeBroadcastReceiveState mState;
+    @Mock private BluetoothLeBroadcastMetadata mMetadata;
+    private Fragment mParentFragment;
     private Context mContext;
     private AudioSharingDialogHandler mHandler;
     private FakeFeatureFactory mFeatureFactory;
 
     @Before
     public void setup() {
-        mContext = ApplicationProvider.getApplicationContext();
+        mParentFragment = new Fragment();
+        FragmentController.setupFragment(
+                mParentFragment,
+                FragmentActivity.class,
+                0 /* containerViewId */,
+                null /* bundle */);
+        mContext = mParentFragment.getContext();
         ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
         mLocalBtManager = Utils.getLocalBtManager(mContext);
         ShadowBluetoothAdapter shadowBluetoothAdapter =
@@ -135,6 +149,7 @@
         List<Long> bisSyncState = new ArrayList<>();
         bisSyncState.add(1L);
         when(mState.getBisSyncState()).thenReturn(bisSyncState);
+        when(mState.getSourceId()).thenReturn(TEST_SOURCE_ID);
         when(mLeAudioProfile.isEnabled(any())).thenReturn(true);
         when(mCachedDevice1.getName()).thenReturn(TEST_DEVICE_NAME1);
         when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
@@ -158,12 +173,6 @@
         when(mCacheManager.findDevice(mDevice2)).thenReturn(mCachedDevice2);
         when(mCacheManager.findDevice(mDevice3)).thenReturn(mCachedDevice3);
         when(mCacheManager.findDevice(mDevice4)).thenReturn(mCachedDevice4);
-        mParentFragment = new Fragment();
-        FragmentController.setupFragment(
-                mParentFragment,
-                FragmentActivity.class,
-                0 /* containerViewId */,
-                null /* bundle */);
         mHandler = new AudioSharingDialogHandler(mContext, mParentFragment);
     }
 
@@ -269,6 +278,10 @@
                                 AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
                                         .ordinal(),
                                 2));
+        AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
+        assertThat(listener).isNotNull();
+        listener.onShareClick();
+        verify(mBroadcast).startPrivateBroadcast();
     }
 
     @Test
@@ -309,6 +322,10 @@
                                 AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
                                         .ordinal(),
                                 1));
+        AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
+        assertThat(listener).isNotNull();
+        listener.onShareClick();
+        verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
     }
 
     @Test
@@ -351,6 +368,11 @@
                                 AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
                                         .ordinal(),
                                 1));
+        AudioSharingDisconnectDialogFragment.DialogEventListener listener = fragment.getListener();
+        assertThat(listener).isNotNull();
+        listener.onItemClick(AudioSharingUtils.buildAudioSharingDeviceItem(mCachedDevice3));
+        verify(mAssistant).removeSource(mDevice3, TEST_SOURCE_ID);
+        verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
     }
 
     @Test
@@ -363,7 +385,7 @@
         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
         mHandler.handleDeviceConnected(mCachedDevice2, /* userTriggered= */ false);
         shadowOf(Looper.getMainLooper()).idle();
-        verify(mCachedDevice2, times(0)).setActive();
+        verify(mCachedDevice2, never()).setActive();
     }
 
     @Test
@@ -415,7 +437,7 @@
         when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
         mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ false);
         shadowOf(Looper.getMainLooper()).idle();
-        verify(mCachedDevice1, times(0)).setActive();
+        verify(mCachedDevice1, never()).setActive();
     }
 
     @Test
@@ -455,6 +477,10 @@
                                 AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
                                         .ordinal(),
                                 2));
+        AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
+        assertThat(listener).isNotNull();
+        listener.onShareClick();
+        verify(mBroadcast).startPrivateBroadcast();
     }
 
     @Test
@@ -495,6 +521,10 @@
                                 AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
                                         .ordinal(),
                                 1));
+        AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
+        assertThat(listener).isNotNull();
+        listener.onShareClick();
+        verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
     }
 
     @Test
@@ -536,6 +566,11 @@
                                 AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
                                         .ordinal(),
                                 1));
+        AudioSharingDisconnectDialogFragment.DialogEventListener listener = fragment.getListener();
+        assertThat(listener).isNotNull();
+        listener.onItemClick(AudioSharingUtils.buildAudioSharingDeviceItem(mCachedDevice3));
+        verify(mAssistant).removeSource(mDevice3, TEST_SOURCE_ID);
+        verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
     }
 
     @Test
@@ -588,7 +623,106 @@
                         SettingsEnums.DIALOG_STOP_AUDIO_SHARING);
     }
 
+    @Test
+    public void closeOpeningDialogsOtherThan() {
+        setUpBroadcast(true);
+        ImmutableList<BluetoothDevice> deviceList = ImmutableList.of(mDevice3);
+        when(mAssistant.getDevicesMatchingConnectionStates(
+                        new int[] {BluetoothProfile.STATE_CONNECTED}))
+                .thenReturn(deviceList);
+        when(mAssistant.getAllSources(mDevice3)).thenReturn(ImmutableList.of(mState));
+        mHandler.handleDeviceConnected(mCachedDevice2, /* userTriggered= */ true);
+        shadowOf(Looper.getMainLooper()).idle();
+        List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+        assertThat(childFragments)
+                .comparingElementsUsing(TAG_EQUALS)
+                .containsExactly(AudioSharingStopDialogFragment.tag());
+
+        deviceList = ImmutableList.of(mDevice1, mDevice3);
+        when(mAssistant.getDevicesMatchingConnectionStates(
+                        new int[] {BluetoothProfile.STATE_CONNECTED}))
+                .thenReturn(deviceList);
+        when(mAssistant.getAllSources(mDevice1)).thenReturn(ImmutableList.of());
+        mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ false);
+        shadowOf(Looper.getMainLooper()).idle();
+        childFragments = mParentFragment.getChildFragmentManager().getFragments();
+        assertThat(childFragments)
+                .comparingElementsUsing(TAG_EQUALS)
+                .containsExactly(AudioSharingJoinDialogFragment.tag());
+
+        verify(mFeatureFactory.metricsFeatureProvider)
+                .action(
+                        mContext,
+                        SettingsEnums.ACTION_AUDIO_SHARING_DIALOG_AUTO_DISMISS,
+                        SettingsEnums.DIALOG_STOP_AUDIO_SHARING);
+    }
+
+    @Test
+    public void registerCallbacks() {
+        Executor executor = mock(Executor.class);
+        mHandler.registerCallbacks(executor);
+        verify(mBroadcast)
+                .registerServiceCallBack(eq(executor), any(BluetoothLeBroadcast.Callback.class));
+    }
+
+    @Test
+    public void unregisterCallbacks() {
+        mHandler.unregisterCallbacks();
+        verify(mBroadcast).unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
+    }
+
+    @Test
+    public void onPlaybackStarted_addSource() {
+        setUpBroadcast(false);
+        ImmutableList<BluetoothDevice> deviceList = ImmutableList.of(mDevice1, mDevice3);
+        when(mAssistant.getDevicesMatchingConnectionStates(
+                        new int[] {BluetoothProfile.STATE_CONNECTED}))
+                .thenReturn(deviceList);
+        when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
+        mHandler.handleDeviceConnected(mCachedDevice1, /* userTriggered= */ true);
+        shadowOf(Looper.getMainLooper()).idle();
+        List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
+        assertThat(childFragments)
+                .comparingElementsUsing(TAG_EQUALS)
+                .containsExactly(AudioSharingJoinDialogFragment.tag());
+        AudioSharingJoinDialogFragment fragment =
+                (AudioSharingJoinDialogFragment) Iterables.getOnlyElement(childFragments);
+        AudioSharingJoinDialogFragment.DialogEventListener listener = fragment.getListener();
+        assertThat(listener).isNotNull();
+        listener.onShareClick();
+
+        setUpBroadcast(true);
+        mHandler.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
+        shadowOf(Looper.getMainLooper()).idle();
+
+        verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
+        verify(mAssistant).addSource(mDevice3, mMetadata, /* isGroupOp= */ false);
+    }
+
+    @Test
+    public void testBluetoothLeBroadcastCallbacks_doNothing() {
+        mHandler.mBroadcastCallback.onBroadcastStarted(/* reason= */ 1, /* broadcastId= */ 1);
+        mHandler.mBroadcastCallback.onBroadcastStopped(/* reason= */ 1, /* broadcastId= */ 1);
+        mHandler.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
+        mHandler.mBroadcastCallback.onBroadcastUpdated(/* reason= */ 1, /* broadcastId= */ 1);
+        mHandler.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
+        mHandler.mBroadcastCallback.onPlaybackStopped(/* reason= */ 1, /* broadcastId= */ 1);
+        mHandler.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 1);
+        mHandler.mBroadcastCallback.onBroadcastStopFailed(/* reason= */ 1);
+        mHandler.mBroadcastCallback.onBroadcastUpdateFailed(/* reason= */ 1, /* broadcastId= */ 1);
+
+        verify(mAssistant, never())
+                .addSource(
+                        any(BluetoothDevice.class),
+                        any(BluetoothLeBroadcastMetadata.class),
+                        anyBoolean());
+        verify(mAssistant, never()).removeSource(any(BluetoothDevice.class), anyInt());
+    }
+
     private void setUpBroadcast(boolean isBroadcasting) {
         when(mBroadcast.isEnabled(any())).thenReturn(isBroadcasting);
+        if (isBroadcasting) {
+            when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
+        }
     }
 }
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java
index 8f85feb8..012f88c 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java
@@ -22,11 +22,13 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
@@ -36,6 +38,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothLeBroadcast;
 import android.bluetooth.BluetoothLeBroadcastAssistant;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothStatusCodes;
 import android.content.BroadcastReceiver;
@@ -181,7 +184,7 @@
         doNothing()
                 .when(mAssistant)
                 .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
-        mSwitchBar = new SettingsMainSwitchBar(mContext);
+        mSwitchBar = spy(new SettingsMainSwitchBar(mContext));
         mSwitchBar.setDisabledByAdmin(mock(RestrictedLockUtils.EnforcedAdmin.class));
         mOnAudioSharingStateChanged = false;
         mOnAudioSharingServiceConnected = false;
@@ -258,15 +261,15 @@
     public void onStart_flagOff_doNothing() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.onStart(mLifecycleOwner);
-        verify(mContext, times(0))
+        verify(mContext, never())
                 .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), anyInt());
-        verify(mBroadcast, times(0))
+        verify(mBroadcast, never())
                 .registerServiceCallBack(
                         any(Executor.class), any(BluetoothLeBroadcast.Callback.class));
-        verify(mAssistant, times(0))
+        verify(mAssistant, never())
                 .registerServiceCallBack(
                         any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
-        verify(mBtProfileManager, times(0)).addServiceListener(mController);
+        verify(mBtProfileManager, never()).addServiceListener(mController);
     }
 
     @Test
@@ -279,10 +282,10 @@
 
         verify(mContext)
                 .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), anyInt());
-        verify(mBroadcast, times(0))
+        verify(mBroadcast, never())
                 .registerServiceCallBack(
                         any(Executor.class), any(BluetoothLeBroadcast.Callback.class));
-        verify(mAssistant, times(0))
+        verify(mAssistant, never())
                 .registerServiceCallBack(
                         any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
         verify(mBtProfileManager).addServiceListener(mController);
@@ -305,7 +308,7 @@
         verify(mAssistant)
                 .registerServiceCallBack(
                         any(Executor.class), any(BluetoothLeBroadcastAssistant.Callback.class));
-        verify(mBtProfileManager, times(0)).addServiceListener(mController);
+        verify(mBtProfileManager, never()).addServiceListener(mController);
         assertThat(mSwitchBar.isChecked()).isTrue();
         assertThat(mSwitchBar.isEnabled()).isTrue();
     }
@@ -314,12 +317,12 @@
     public void onStop_flagOff_doNothing() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.onStop(mLifecycleOwner);
-        verify(mContext, times(0)).unregisterReceiver(any(BroadcastReceiver.class));
-        verify(mBroadcast, times(0))
+        verify(mContext, never()).unregisterReceiver(any(BroadcastReceiver.class));
+        verify(mBroadcast, never())
                 .unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
-        verify(mAssistant, times(0))
+        verify(mAssistant, never())
                 .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
-        verify(mBtProfileManager, times(0)).removeServiceListener(mController);
+        verify(mBtProfileManager, never()).removeServiceListener(mController);
     }
 
     @Test
@@ -331,9 +334,9 @@
 
         verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
         verify(mBtProfileManager).removeServiceListener(mController);
-        verify(mBroadcast, times(0))
+        verify(mBroadcast, never())
                 .unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
-        verify(mAssistant, times(0))
+        verify(mAssistant, never())
                 .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class));
     }
 
@@ -358,7 +361,7 @@
         when(mBtnView.isEnabled()).thenReturn(true);
         when(mBroadcast.isEnabled(null)).thenReturn(true);
         mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
-        verify(mBroadcast, times(0)).startPrivateBroadcast();
+        verify(mBroadcast, never()).startPrivateBroadcast();
     }
 
     @Test
@@ -372,7 +375,7 @@
         doNothing().when(mBroadcast).startPrivateBroadcast();
         mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
         assertThat(mSwitchBar.isChecked()).isFalse();
-        verify(mBroadcast, times(0)).startPrivateBroadcast();
+        verify(mBroadcast, never()).startPrivateBroadcast();
     }
 
     @Test
@@ -407,7 +410,7 @@
         when(mBroadcast.isEnabled(null)).thenReturn(false);
         when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
         mController.onCheckedChanged(mBtnView, /* isChecked= */ false);
-        verify(mBroadcast, times(0)).stopBroadcast(anyInt());
+        verify(mBroadcast, never()).stopBroadcast(anyInt());
     }
 
     @Test
@@ -465,4 +468,46 @@
                                         .ordinal(),
                                 1));
     }
+
+    @Test
+    public void testBluetoothLeBroadcastCallbacks_updateSwitch() {
+        mOnAudioSharingStateChanged = false;
+        mSwitchBar.setChecked(false);
+        when(mBroadcast.isEnabled(any())).thenReturn(false);
+        mController.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 1);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mSwitchBar.isChecked()).isFalse();
+        assertThat(mOnAudioSharingStateChanged).isFalse();
+
+        when(mBroadcast.isEnabled(any())).thenReturn(true);
+        mController.mBroadcastCallback.onBroadcastStarted(/* reason= */ 1, /* broadcastId= */ 1);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mSwitchBar.isChecked()).isTrue();
+        assertThat(mOnAudioSharingStateChanged).isTrue();
+
+        mOnAudioSharingStateChanged = false;
+        mController.mBroadcastCallback.onBroadcastStopFailed(/* reason= */ 1);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mSwitchBar.isChecked()).isTrue();
+        assertThat(mOnAudioSharingStateChanged).isFalse();
+
+        when(mBroadcast.isEnabled(any())).thenReturn(false);
+        mController.mBroadcastCallback.onBroadcastStopped(/* reason= */ 1, /* broadcastId= */ 1);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mSwitchBar.isChecked()).isFalse();
+        assertThat(mOnAudioSharingStateChanged).isTrue();
+    }
+
+    @Test
+    public void testBluetoothLeBroadcastCallbacks_doNothing() {
+        BluetoothLeBroadcastMetadata metadata = mock(BluetoothLeBroadcastMetadata.class);
+        mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, metadata);
+        mController.mBroadcastCallback.onBroadcastUpdated(/* reason= */ 1, /* broadcastId= */ 1);
+        mController.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
+        mController.mBroadcastCallback.onPlaybackStopped(/* reason= */ 1, /* broadcastId= */ 1);
+        mController.mBroadcastCallback.onBroadcastUpdateFailed(
+                /* reason= */ 1, /* broadcastId= */ 1);
+        verify(mSwitchBar, never()).setChecked(anyBoolean());
+        assertThat(mOnAudioSharingStateChanged).isFalse();
+    }
 }