Merge "Accommodate BATT protocol modifications." into main
diff --git a/res/xml/connected_devices.xml b/res/xml/connected_devices.xml
index 05bf925..e8c169c 100644
--- a/res/xml/connected_devices.xml
+++ b/res/xml/connected_devices.xml
@@ -30,13 +30,6 @@
         android:key="audio_sharing_device_list"
         android:title="@string/audio_sharing_device_group_title"
         settings:controller="com.android.settings.connecteddevice.audiosharing.AudioSharingDevicePreferenceController">
-        <Preference
-            android:fragment="com.android.settings.connecteddevice.audiosharing.AudioSharingDashboardFragment"
-            android:icon="@drawable/ic_bt_le_audio_sharing"
-            android:key="connected_device_audio_sharing_settings"
-            android:order="100"
-            android:title="@string/audio_sharing_title"
-            settings:searchable="false" />
     </PreferenceCategory>
 
     <PreferenceCategory
@@ -44,6 +37,14 @@
         android:title="@string/connected_device_temp_bond_device_title"
         settings:controller="com.android.settings.connecteddevice.audiosharing.TemporaryBondDeviceGroupController" />
 
+    <Preference
+        android:fragment="com.android.settings.connecteddevice.audiosharing.AudioSharingDashboardFragment"
+        android:icon="@drawable/ic_bt_le_audio_sharing"
+        android:key="connected_device_audio_sharing_settings"
+        android:title="@string/audio_sharing_title"
+        settings:controller="com.android.settings.connecteddevice.audiosharing.AudioSharingPreferenceController"
+        settings:searchable="false" />
+
     <PreferenceCategory
         android:key="available_device_list"
         android:title="@string/connected_device_media_device_title"
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
index ffbb13e..a1ba3c9 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
@@ -78,8 +78,6 @@
 
     private static final String TAG = "AudioSharingDevicePrefController";
     private static final String KEY = "audio_sharing_device_list";
-    private static final String KEY_AUDIO_SHARING_SETTINGS =
-            "connected_device_audio_sharing_settings";
 
     @Nullable private final LocalBluetoothManager mBtManager;
     @Nullable private final CachedBluetoothDeviceManager mDeviceManager;
@@ -89,7 +87,6 @@
     private final Executor mExecutor;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
     @Nullable private PreferenceGroup mPreferenceGroup;
-    @Nullable private Preference mAudioSharingSettingsPreference;
     @Nullable private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
     @Nullable private DashboardFragment mFragment;
     @Nullable private AudioSharingDialogHandler mDialogHandler;
@@ -280,13 +277,8 @@
         super.displayPreference(screen);
         mPreferenceGroup = screen.findPreference(KEY);
         if (mPreferenceGroup != null) {
-            mAudioSharingSettingsPreference =
-                    mPreferenceGroup.findPreference(KEY_AUDIO_SHARING_SETTINGS);
             mPreferenceGroup.setVisible(false);
         }
-        if (mAudioSharingSettingsPreference != null) {
-            mAudioSharingSettingsPreference.setVisible(false);
-        }
 
         if (isAvailable()) {
             if (mBluetoothDeviceUpdater != null) {
@@ -320,11 +312,8 @@
     @Override
     public void onDeviceAdded(Preference preference) {
         if (mPreferenceGroup != null) {
-            if (mPreferenceGroup.getPreferenceCount() == 1) {
+            if (mPreferenceGroup.getPreferenceCount() == 0) {
                 mPreferenceGroup.setVisible(true);
-                if (mAudioSharingSettingsPreference != null) {
-                    mAudioSharingSettingsPreference.setVisible(true);
-                }
             }
             mPreferenceGroup.addPreference(preference);
         }
@@ -334,11 +323,8 @@
     public void onDeviceRemoved(Preference preference) {
         if (mPreferenceGroup != null) {
             mPreferenceGroup.removePreference(preference);
-            if (mPreferenceGroup.getPreferenceCount() == 1) {
+            if (mPreferenceGroup.getPreferenceCount() == 0) {
                 mPreferenceGroup.setVisible(false);
-                if (mAudioSharingSettingsPreference != null) {
-                    mAudioSharingSettingsPreference.setVisible(false);
-                }
             }
         }
     }
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java
index f3effbd..e034d36 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceController.java
@@ -45,6 +45,9 @@
 public class AudioSharingPreferenceController extends BasePreferenceController
         implements DefaultLifecycleObserver, BluetoothCallback {
     private static final String TAG = "AudioSharingPreferenceController";
+    private static final String CONNECTED_DEVICES_PREF_KEY =
+            "connected_device_audio_sharing_settings";
+    private static final String CONNECTION_PREFERENCES_PREF_KEY = "audio_sharing_settings";
 
     @Nullable private final LocalBluetoothManager mBtManager;
     @Nullable private final BluetoothEventManager mEventManager;
@@ -57,7 +60,7 @@
             new BluetoothLeBroadcast.Callback() {
                 @Override
                 public void onBroadcastStarted(int reason, int broadcastId) {
-                    refreshSummary();
+                    refreshPreference();
                 }
 
                 @Override
@@ -69,7 +72,7 @@
 
                 @Override
                 public void onBroadcastStopped(int reason, int broadcastId) {
-                    refreshSummary();
+                    refreshPreference();
                 }
 
                 @Override
@@ -111,6 +114,7 @@
         }
         mEventManager.registerCallback(this);
         mBroadcast.registerServiceCallBack(mExecutor, mBroadcastCallback);
+        updateVisibility();
     }
 
     @Override
@@ -131,6 +135,13 @@
     public void displayPreference(@NonNull PreferenceScreen screen) {
         super.displayPreference(screen);
         mPreference = screen.findPreference(getPreferenceKey());
+        // super.displayPreference set the visibility based on isAvailable()
+        // immediately set the preference invisible on Connected devices page to avoid the audio
+        // sharing entrance being shown before updateVisibility(need binder call) take effects.
+        if (mPreference != null && CONNECTED_DEVICES_PREF_KEY.equals(getPreferenceKey())) {
+            mPreference.setVisible(false);
+        }
+        updateVisibility();
     }
 
     @Override
@@ -141,14 +152,51 @@
 
     @Override
     public CharSequence getSummary() {
-        return BluetoothUtils.isBroadcasting(mBtManager)
-                ? mContext.getString(R.string.audio_sharing_summary_on)
-                : mContext.getString(R.string.audio_sharing_summary_off);
+        return switch (getPreferenceKey()) {
+            case CONNECTION_PREFERENCES_PREF_KEY -> BluetoothUtils.isBroadcasting(mBtManager)
+                    ? mContext.getString(R.string.audio_sharing_summary_on)
+                    : mContext.getString(R.string.audio_sharing_summary_off);
+            default -> "";
+        };
     }
 
     @Override
     public void onBluetoothStateChanged(@AdapterState int bluetoothState) {
-        refreshSummary();
+        refreshPreference();
+    }
+
+    private void refreshPreference() {
+        switch (getPreferenceKey()) {
+            // Audio sharing entrance on Connected devices page has no summary, but its visibility
+            // will change based on audio sharing state
+            case CONNECTED_DEVICES_PREF_KEY -> updateVisibility();
+            // Audio sharing entrance on Connection preferences page always show up, but its summary
+            // will change based on audio sharing state
+            case CONNECTION_PREFERENCES_PREF_KEY -> refreshSummary();
+        }
+    }
+
+    private void updateVisibility() {
+        if (mPreference == null) {
+            return;
+        }
+        switch (getPreferenceKey()) {
+            case CONNECTED_DEVICES_PREF_KEY -> {
+                var unused =
+                        ThreadUtils.postOnBackgroundThread(
+                                () -> {
+                                    boolean visible = BluetoothUtils.isBroadcasting(mBtManager);
+                                    AudioSharingUtils.postOnMainThread(
+                                            mContext,
+                                            () -> {
+                                                // Check nullability to pass NullAway check
+                                                if (mPreference != null) {
+                                                    mPreference.setVisible(visible);
+                                                }
+                                            });
+                                });
+            }
+        }
     }
 
     private void refreshSummary() {
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
index 7ca3256..4492115 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
@@ -128,6 +128,7 @@
     // join the audio sharing, we will wait for the process complete for this list of sinks and then
     // popup audio sharing dialog with options to pair new device.
     private CopyOnWriteArrayList<BluetoothDevice> mSinksToWaitFor = new CopyOnWriteArrayList<>();
+    private AtomicBoolean mStartingSharing = new AtomicBoolean(false);
     private AtomicBoolean mStoppingSharing = new AtomicBoolean(false);
 
     @VisibleForTesting
@@ -160,6 +161,7 @@
                 @Override
                 public void onBroadcastStartFailed(int reason) {
                     Log.d(TAG, "onBroadcastStartFailed(), reason = " + reason);
+                    mStartingSharing.compareAndSet(true, false);
                     updateSwitch();
                     showErrorDialog();
                     mMetricsFeatureProvider.action(
@@ -177,16 +179,8 @@
                                     + broadcastId
                                     + ", metadata = "
                                     + metadata.getBroadcastName());
-                    if (mAssistant == null
-                            || mAssistant.getAllConnectedDevices().stream()
-                                    .anyMatch(
-                                            device -> BluetoothUtils
-                                                    .hasActiveLocalBroadcastSourceForBtDevice(
-                                                            device, mBtManager))) {
-                        Log.d(
-                                TAG,
-                                "Skip handleOnBroadcastReady: null assistant or "
-                                        + "sink has active local source.");
+                    if (!mStartingSharing.compareAndSet(true, false)) {
+                        Log.d(TAG, "Skip handleOnBroadcastReady, not in starting process");
                         return;
                     }
                     handleOnBroadcastReady();
@@ -213,6 +207,7 @@
                 @Override
                 public void onBroadcastStopFailed(int reason) {
                     Log.d(TAG, "onBroadcastStopFailed(), reason = " + reason);
+                    mStoppingSharing.compareAndSet(true, false);
                     updateSwitch();
                     mMetricsFeatureProvider.action(
                             mContext,
@@ -565,6 +560,7 @@
             mDeviceItemsForSharing.remove(0);
         }
         if (mBroadcast != null) {
+            mStartingSharing.set(true);
             mBroadcast.startPrivateBroadcast();
             mSinksInAdding.clear();
             AudioSharingUtils.postOnMainThread(mContext,
@@ -583,7 +579,7 @@
             int broadcastId = mBroadcast.getLatestBroadcastId();
             if (broadcastId != -1) {
                 mBroadcast.stopBroadcast(broadcastId);
-                mStoppingSharing.compareAndSet(false, true);
+                mStoppingSharing.set(true);
                 mSinksInAdding.clear();
                 mSinksToWaitFor.clear();
             }
diff --git a/src/com/android/settings/password/SetupChooseLockPattern.java b/src/com/android/settings/password/SetupChooseLockPattern.java
index 55b38471..7941049 100644
--- a/src/com/android/settings/password/SetupChooseLockPattern.java
+++ b/src/com/android/settings/password/SetupChooseLockPattern.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.password;
 
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
-
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
 
 import android.content.Context;
@@ -138,17 +136,10 @@
         protected void updateStage(Stage stage) {
             super.updateStage(stage);
             if (!showMinimalUi() && mOptionsButton != null) {
-                // In landscape, keep view stub to avoid pattern view shifting, but in portrait the
-                // header title and description could become multiple lines in confirm stage,
-                // gone the button view to reserve more room for growth height of header.
-                @View.Visibility
-                final int hideOrGone =
-                        getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE
-                                ? View.INVISIBLE : View.GONE;
                 mOptionsButton.setVisibility(
                         (stage == Stage.Introduction || stage == Stage.HelpScreen ||
                                 stage == Stage.ChoiceTooShort || stage == Stage.FirstChoiceValid)
-                                ? View.VISIBLE : hideOrGone);
+                                ? View.VISIBLE : View.INVISIBLE);
             }
 
             if (stage.leftMode == LeftButtonMode.Gone && stage == Stage.Introduction) {
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 4a4a167..1156b7a 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceControllerTest.java
@@ -117,8 +117,6 @@
         })
 public class AudioSharingDevicePreferenceControllerTest {
     private static final String KEY = "audio_sharing_device_list";
-    private static final String KEY_AUDIO_SHARING_SETTINGS =
-            "connected_device_audio_sharing_settings";
     private static final String TEST_DEVICE_NAME = "test";
 
     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -151,7 +149,6 @@
     private Lifecycle mLifecycle;
     private LifecycleOwner mLifecycleOwner;
     private PreferenceCategory mPreferenceGroup;
-    private Preference mAudioSharingPreference;
     private FakeFeatureFactory mFeatureFactory;
     private AudioManager mAudioManager;
 
@@ -189,10 +186,6 @@
         when(mScreen.getContext()).thenReturn(mContext);
         mPreferenceGroup = spy(new PreferenceCategory(mContext));
         doReturn(mPreferenceManager).when(mPreferenceGroup).getPreferenceManager();
-        mAudioSharingPreference = new Preference(mContext);
-        mPreferenceGroup.addPreference(mAudioSharingPreference);
-        when(mPreferenceGroup.findPreference(KEY_AUDIO_SHARING_SETTINGS))
-                .thenReturn(mAudioSharingPreference);
         when(mScreen.findPreference(KEY)).thenReturn(mPreferenceGroup);
         mController = new AudioSharingDevicePreferenceController(mContext);
         mController.init(mFragment);
@@ -260,7 +253,6 @@
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.displayPreference(mScreen);
         assertThat(mPreferenceGroup.isVisible()).isFalse();
-        assertThat(mAudioSharingPreference.isVisible()).isFalse();
         verify(mBluetoothDeviceUpdater, never()).forceUpdate();
     }
 
@@ -269,7 +261,6 @@
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mController.displayPreference(mScreen);
         assertThat(mPreferenceGroup.isVisible()).isFalse();
-        assertThat(mAudioSharingPreference.isVisible()).isFalse();
         verify(mBluetoothDeviceUpdater).setPrefContext(mContext);
         verify(mBluetoothDeviceUpdater).forceUpdate();
     }
@@ -299,8 +290,7 @@
         shadowOf(Looper.getMainLooper()).idle();
 
         assertThat(mPreferenceGroup.isVisible()).isTrue();
-        assertThat(mAudioSharingPreference.isVisible()).isTrue();
-        assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2);
+        assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
     }
 
     @Test
@@ -312,8 +302,7 @@
         shadowOf(Looper.getMainLooper()).idle();
 
         assertThat(mPreferenceGroup.isVisible()).isFalse();
-        assertThat(mAudioSharingPreference.isVisible()).isFalse();
-        assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
+        assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java
index d9c883e..cdf21db 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingPreferenceControllerTest.java
@@ -25,8 +25,10 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
@@ -77,7 +79,8 @@
             ShadowThreadUtils.class
         })
 public class AudioSharingPreferenceControllerTest {
-    private static final String PREF_KEY = "audio_sharing_settings";
+    private static final String PREF_KEY1 = "audio_sharing_settings";
+    private static final String PREF_KEY2 = "connected_device_audio_sharing_settings";
 
     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -110,9 +113,6 @@
         when(localBluetoothManager.getEventManager()).thenReturn(mBtEventManager);
         when(localBluetoothManager.getProfileManager()).thenReturn(mLocalBtProfileManager);
         when(mLocalBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
-        mController = new AudioSharingPreferenceController(mContext, PREF_KEY);
-        mPreference = spy(new Preference(mContext));
-        when(mScreen.findPreference(PREF_KEY)).thenReturn(mPreference);
     }
 
     @After
@@ -124,6 +124,7 @@
     @Test
     public void onStart_flagOn_registerCallback() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        setupControllerWithKey(PREF_KEY1);
         mController.onStart(mLifecycleOwner);
         verify(mBtEventManager).registerCallback(mController);
         verify(mBroadcast).registerServiceCallBack(any(), any(BluetoothLeBroadcast.Callback.class));
@@ -132,6 +133,7 @@
     @Test
     public void onStart_flagOff_skipRegisterCallback() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        setupControllerWithKey(PREF_KEY1);
         mController.onStart(mLifecycleOwner);
         verify(mBtEventManager, never()).registerCallback(mController);
         verify(mBroadcast, never())
@@ -141,6 +143,7 @@
     @Test
     public void onStop_flagOn_unregisterCallback() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        setupControllerWithKey(PREF_KEY1);
         mController.onStop(mLifecycleOwner);
         verify(mBtEventManager).unregisterCallback(mController);
         verify(mBroadcast).unregisterServiceCallBack(any(BluetoothLeBroadcast.Callback.class));
@@ -149,6 +152,7 @@
     @Test
     public void onStop_flagOff_skipUnregisterCallback() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        setupControllerWithKey(PREF_KEY1);
         mController.onStop(mLifecycleOwner);
         verify(mBtEventManager, never()).unregisterCallback(mController);
         verify(mBroadcast, never())
@@ -158,65 +162,147 @@
     @Test
     public void getAvailabilityStatus_flagOn() {
         mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        setupControllerWithKey(PREF_KEY1);
         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
 
     @Test
     public void getAvailabilityStatus_flagOff() {
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+        setupControllerWithKey(PREF_KEY1);
         assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
     }
 
     @Test
-    public void getSummary_broadcastOn() {
+    public void getSummary_connectionPreference_broadcastOn() {
         when(mBroadcast.isEnabled(any())).thenReturn(true);
+        setupControllerWithKey(PREF_KEY1);
         assertThat(mController.getSummary().toString())
                 .isEqualTo(mContext.getString(R.string.audio_sharing_summary_on));
     }
 
     @Test
-    public void getSummary_broadcastOff() {
+    public void getSummary_connectionPreference_broadcastOff() {
         when(mBroadcast.isEnabled(any())).thenReturn(false);
+        setupControllerWithKey(PREF_KEY1);
         assertThat(mController.getSummary().toString())
                 .isEqualTo(mContext.getString(R.string.audio_sharing_summary_off));
     }
 
     @Test
+    public void getSummary_connectedDevices_broadcastOn() {
+        when(mBroadcast.isEnabled(any())).thenReturn(true);
+        setupControllerWithKey(PREF_KEY2);
+        assertThat(mController.getSummary().toString()).isEmpty();
+    }
+
+    @Test
+    public void getSummary_connectedDevices_broadcastOff() {
+        when(mBroadcast.isEnabled(any())).thenReturn(false);
+        setupControllerWithKey(PREF_KEY2);
+        assertThat(mController.getSummary().toString()).isEmpty();
+    }
+
+    @Test
     public void onBluetoothStateChanged_refreshSummary() {
+        setupControllerWithKey(PREF_KEY1);
+        mController.updateState(mPreference);
         mController.displayPreference(mScreen);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreference.getSummary().toString())
+                .isEqualTo(mContext.getString(R.string.audio_sharing_summary_off));
+        assertThat(mPreference.isVisible()).isTrue();
+
         when(mBroadcast.isEnabled(any())).thenReturn(true);
         mController.onBluetoothStateChanged(STATE_ON);
         shadowOf(Looper.getMainLooper()).idle();
         assertThat(mPreference.getSummary().toString())
                 .isEqualTo(mContext.getString(R.string.audio_sharing_summary_on));
+        assertThat(mPreference.isVisible()).isTrue();
 
         when(mBroadcast.isEnabled(any())).thenReturn(false);
         mController.onBluetoothStateChanged(STATE_OFF);
         shadowOf(Looper.getMainLooper()).idle();
         assertThat(mPreference.getSummary().toString())
                 .isEqualTo(mContext.getString(R.string.audio_sharing_summary_off));
+        assertThat(mPreference.isVisible()).isTrue();
+    }
+
+    @Test
+    public void onBluetoothStateChanged_refreshVisibility() {
+        setupControllerWithKey(PREF_KEY2);
+        mController.updateState(mPreference);
+        mController.displayPreference(mScreen);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreference.getSummary().toString()).isEmpty();
+        assertThat(mPreference.isVisible()).isFalse();
+
+        when(mBroadcast.isEnabled(any())).thenReturn(true);
+        mController.onBluetoothStateChanged(STATE_ON);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreference.getSummary().toString()).isEmpty();
+        assertThat(mPreference.isVisible()).isTrue();
+
+        when(mBroadcast.isEnabled(any())).thenReturn(false);
+        mController.onBluetoothStateChanged(STATE_OFF);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreference.getSummary().toString()).isEmpty();
+        assertThat(mPreference.isVisible()).isFalse();
     }
 
     @Test
     public void testBluetoothLeBroadcastCallbacks_refreshSummary() {
+        setupControllerWithKey(PREF_KEY1);
+        mController.updateState(mPreference);
         mController.displayPreference(mScreen);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreference.getSummary().toString())
+                .isEqualTo(mContext.getString(R.string.audio_sharing_summary_off));
+        assertThat(mPreference.isVisible()).isTrue();
 
         when(mBroadcast.isEnabled(any())).thenReturn(true);
         mController.mBroadcastCallback.onBroadcastStarted(/* reason= */ 1, /* broadcastId= */ 1);
         shadowOf(Looper.getMainLooper()).idle();
         assertThat(mPreference.getSummary().toString())
                 .isEqualTo(mContext.getString(R.string.audio_sharing_summary_on));
+        assertThat(mPreference.isVisible()).isTrue();
 
         when(mBroadcast.isEnabled(any())).thenReturn(false);
         mController.mBroadcastCallback.onBroadcastStopped(/* reason= */ 1, /* broadcastId= */ 1);
         shadowOf(Looper.getMainLooper()).idle();
         assertThat(mPreference.getSummary().toString())
                 .isEqualTo(mContext.getString(R.string.audio_sharing_summary_off));
+        assertThat(mPreference.isVisible()).isTrue();
+    }
+
+    @Test
+    public void testBluetoothLeBroadcastCallbacks_refreshVisibility() {
+        setupControllerWithKey(PREF_KEY2);
+        mController.updateState(mPreference);
+        mController.displayPreference(mScreen);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreference.getSummary().toString()).isEmpty();
+        assertThat(mPreference.isVisible()).isFalse();
+
+        when(mBroadcast.isEnabled(any())).thenReturn(true);
+        mController.mBroadcastCallback.onBroadcastStarted(/* reason= */ 1, /* broadcastId= */ 1);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreference.getSummary().toString()).isEmpty();
+        assertThat(mPreference.isVisible()).isTrue();
+
+        when(mBroadcast.isEnabled(any())).thenReturn(false);
+        mController.mBroadcastCallback.onBroadcastStopped(/* reason= */ 1, /* broadcastId= */ 1);
+        shadowOf(Looper.getMainLooper()).idle();
+        assertThat(mPreference.getSummary().toString()).isEmpty();
+        assertThat(mPreference.isVisible()).isFalse();
     }
 
     @Test
     public void testBluetoothLeBroadcastCallbacks_doNothing() {
+        setupControllerWithKey(PREF_KEY1);
         mController.displayPreference(mScreen);
+        shadowOf(Looper.getMainLooper()).idle();
+        verify(mPreference).setVisible(anyBoolean());
 
         mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
         verify(mPreference, never()).setSummary(any());
@@ -233,5 +319,34 @@
         mController.mBroadcastCallback.onBroadcastUpdateFailed(
                 /* reason= */ 1, /* broadcastId= */ 1);
         verify(mPreference, never()).setSummary(any());
+        verify(mPreference).setVisible(anyBoolean());
+
+        setupControllerWithKey(PREF_KEY2);
+        mController.displayPreference(mScreen);
+        shadowOf(Looper.getMainLooper()).idle();
+        verify(mPreference, times(3)).setVisible(anyBoolean());
+
+        mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
+        verify(mPreference, never()).setSummary(any());
+        mController.mBroadcastCallback.onBroadcastUpdated(/* reason= */ 1, /* broadcastId= */ 1);
+        verify(mPreference, never()).setSummary(any());
+        mController.mBroadcastCallback.onPlaybackStarted(/* reason= */ 1, /* broadcastId= */ 1);
+        verify(mPreference, never()).setSummary(any());
+        mController.mBroadcastCallback.onPlaybackStopped(/* reason= */ 1, /* broadcastId= */ 1);
+        verify(mPreference, never()).setSummary(any());
+        mController.mBroadcastCallback.onBroadcastStartFailed(/* reason= */ 1);
+        verify(mPreference, never()).setSummary(any());
+        mController.mBroadcastCallback.onBroadcastStopFailed(/* reason= */ 1);
+        verify(mPreference, never()).setSummary(any());
+        mController.mBroadcastCallback.onBroadcastUpdateFailed(
+                /* reason= */ 1, /* broadcastId= */ 1);
+        verify(mPreference, never()).setSummary(any());
+        verify(mPreference, times(3)).setVisible(anyBoolean());
+    }
+
+    private void setupControllerWithKey(String preferenceKey) {
+        mController = new AudioSharingPreferenceController(mContext, preferenceKey);
+        mPreference = spy(new Preference(mContext));
+        when(mScreen.findPreference(preferenceKey)).thenReturn(mPreference);
     }
 }
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 7851b2b..dea9823 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java
@@ -515,23 +515,14 @@
     }
 
     @Test
-    public void onBroadcastMetadataChanged_hasLocalSource_noDialog() {
+    public void onBroadcastMetadataChanged_notTriggeredHere_noDialog() {
         FeatureFlagUtils.setEnabled(
                 mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
         when(mBtnView.isEnabled()).thenReturn(true);
         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1));
-        when(mState.getBroadcastId()).thenReturn(1);
-        when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
-        when(mAssistant.getAllSources(mDevice2)).thenReturn(ImmutableList.of(mState));
+        when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of());
         when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
         doNothing().when(mBroadcast).startPrivateBroadcast();
-        mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
-        shadowOf(Looper.getMainLooper()).idle();
-
-        verify(mBroadcast).startPrivateBroadcast();
-        List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
-        assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
-                AudioSharingProgressDialogFragment.class.getName());
 
         mController.mBroadcastCallback.onBroadcastMetadataChanged(/* reason= */ 1, mMetadata);
         shadowOf(Looper.getMainLooper()).idle();
@@ -540,7 +531,7 @@
         verify(mFeatureFactory.metricsFeatureProvider, never())
                 .action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING));
 
-        childFragments = mParentFragment.getChildFragmentManager().getFragments();
+        List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
         // No audio sharing dialog.
         assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).doesNotContain(
                 AudioSharingDialogFragment.class.getName());
@@ -613,7 +604,7 @@
     }
 
     @Test
-    public void onBroadcastMetadataChanged_oneActiveOnConnected_showJoinAudioSharingDialog() {
+    public void onBroadcastMetadataChanged_oneActiveOneConnected_showJoinAudioSharingDialog() {
         FeatureFlagUtils.setEnabled(
                 mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
         when(mBtnView.isEnabled()).thenReturn(true);
@@ -681,7 +672,7 @@
     }
 
     @Test
-    public void onBroadcastMetadataChanged_oneActiveOnConnected_clickShareBtnOnDialog_addSource() {
+    public void onBroadcastMetadataChanged_oneActiveOneConnected_clickShareBtnOnDialog_addSource() {
         FeatureFlagUtils.setEnabled(
                 mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
         when(mBtnView.isEnabled()).thenReturn(true);
@@ -722,7 +713,7 @@
     }
 
     @Test
-    public void onBroadcastMetadataChanged_oneActiveOnConnected_clickCancelBtnOnDialog_doNothing() {
+    public void onBroadcastMetadataChanged_oneActiveOneConnected_clickCancelBtnOnDlg_doNothing() {
         FeatureFlagUtils.setEnabled(
                 mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
         when(mBtnView.isEnabled()).thenReturn(true);