Merge "Hide TTS search results if no TTS engine is available"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index cdda50e..f942ba9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -14485,7 +14485,8 @@
     <string name="find_broadcast_password_dialog_connection_error">Can\u2019t connect. Try again.</string>
     <!-- The error message of enter password dialog in bluetooth find broadcast page [CHAR LIMIT=none] -->
     <string name="find_broadcast_password_dialog_password_error">Wrong password</string>
-
+    <!-- The error message of join the broadcast session by scanning the QR code [CHAR LIMIT=none] -->
+    <string name="find_broadcast_join_broadcast_error">Can\u2019t join the broadcast</string>
 
     <!-- [CHAR LIMIT=NONE] Le audio QR code scanner sub-title -->
     <string name="bt_le_audio_scan_qr_code_scanner">To start listening, center the QR code below</string>
diff --git a/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java b/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java
index 733a4a9..9904e8b 100644
--- a/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java
@@ -171,6 +171,16 @@
     }
 
     /**
+     * Whether the broadcast source is connected at the beginging. We will get the
+     * BluetoothLeBroadcastReceiveState from the broadcast source.
+     * See {@link BluetoothFindBroadcastsFragment#addConnectedSourcePreference}
+     * @return If true, the broadcast source is already connected by the broadcast sink.
+     */
+    public boolean isCreatedByReceiveState() {
+        return mBluetoothLeBroadcastReceiveState != null;
+    }
+
+    /**
      * Clear the BluetoothLeBroadcastReceiveState and reset the state when the user clicks the
      * "leave broadcast" button.
      */
diff --git a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
index 13388b3..b84654d 100644
--- a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
@@ -19,6 +19,7 @@
 import static android.bluetooth.BluetoothDevice.BOND_NONE;
 import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
 
+import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.settings.SettingsEnums;
 import android.bluetooth.BluetoothDevice;
@@ -27,6 +28,7 @@
 import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.le.ScanFilter;
 import android.content.Context;
+import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -34,16 +36,17 @@
 import android.view.WindowManager;
 import android.widget.EditText;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 
 import com.android.settings.R;
 import com.android.settings.dashboard.RestrictedDashboardFragment;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
+import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastMetadata;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -66,6 +69,7 @@
 
     public static final String KEY_DEVICE_ADDRESS = "device_address";
     public static final String PREF_KEY_BROADCAST_SOURCE_LIST = "broadcast_source_list";
+    public static final int REQUEST_SCAN_BT_BROADCAST_QR_CODE = 0;
 
     @VisibleForTesting
     String mDeviceAddress;
@@ -75,9 +79,12 @@
     CachedBluetoothDevice mCachedDevice;
     @VisibleForTesting
     PreferenceCategory mBroadcastSourceListCategory;
+    @VisibleForTesting
+    BluetoothBroadcastSourcePreference mSelectedPreference;
     BluetoothFindBroadcastsHeaderController mBluetoothFindBroadcastsHeaderController;
+
     private LocalBluetoothLeBroadcastAssistant mLeBroadcastAssistant;
-    private BluetoothBroadcastSourcePreference mSelectedPreference;
+    private LocalBluetoothLeBroadcastMetadata mLocalBroadcastMetadata;
     private Executor mExecutor;
     private int mSourceId;
 
@@ -182,6 +189,7 @@
         mCachedDevice = getCachedDevice(mDeviceAddress);
         mLeBroadcastAssistant = getLeBroadcastAssistant();
         mExecutor = Executors.newSingleThreadExecutor();
+        mLocalBroadcastMetadata = new LocalBluetoothLeBroadcastMetadata();
 
         super.onAttach(context);
         if (mCachedDevice == null || mLeBroadcastAssistant == null) {
@@ -228,6 +236,34 @@
         }
     }
 
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        Log.d(TAG, "onActivityResult: " + requestCode + ", resultCode: " + resultCode);
+        if (requestCode == REQUEST_SCAN_BT_BROADCAST_QR_CODE) {
+            if (resultCode == Activity.RESULT_OK) {
+
+                //Get BroadcastMetadata
+                String broadcastMetadata = data.getStringExtra(
+                        QrCodeScanModeFragment.KEY_BROADCAST_METADATA);
+                BluetoothLeBroadcastMetadata source = convertToBroadcastMetadata(broadcastMetadata);
+
+                if (source != null) {
+                    Log.d(TAG, "onActivityResult source Id = " + source.getBroadcastId());
+                    //Create preference for the broadcast source
+                    updateListCategoryFromBroadcastMetadata(source, false);
+                    //Add Source
+                    addSource(mBroadcastSourceListCategory.findPreference(
+                            Integer.toString(source.getBroadcastId())));
+                } else {
+                    Toast.makeText(getContext(),
+                        R.string.find_broadcast_join_broadcast_error, Toast.LENGTH_SHORT).show();
+                    return;
+                }
+            }
+        }
+    }
+
     @VisibleForTesting
     void finishFragmentIfNecessary() {
         if (mCachedDevice.getBondState() == BOND_NONE) {
@@ -369,19 +405,31 @@
         return pref;
     }
 
-    private void addSource(BluetoothBroadcastSourcePreference pref) {
+    @VisibleForTesting
+    void addSource(BluetoothBroadcastSourcePreference pref) {
         if (mLeBroadcastAssistant == null || mCachedDevice == null) {
             Log.w(TAG, "addSource: LeBroadcastAssistant or CachedDevice is null!");
             return;
         }
         if (mSelectedPreference != null) {
-            // The previous preference status set false after user selects the new Preference.
-            getActivity().runOnUiThread(
+            if (mSelectedPreference.isCreatedByReceiveState()) {
+                Log.d(TAG, "addSource: Remove preference that created by getAllSources()");
+                getActivity().runOnUiThread(() ->
+                        mBroadcastSourceListCategory.removePreference(mSelectedPreference));
+                if (mLeBroadcastAssistant != null && !mLeBroadcastAssistant.isSearchInProgress()) {
+                    Log.d(TAG, "addSource: Start Searching For Broadcast Sources");
+                    mLeBroadcastAssistant.startSearchingForSources(getScanFilter());
+                }
+            } else {
+                Log.d(TAG, "addSource: Update preference that created by onSourceFound()");
+                // The previous preference status set false after user selects the new Preference.
+                getActivity().runOnUiThread(
                     () -> {
                         mSelectedPreference.updateMetadataAndRefreshUi(
                                 mSelectedPreference.getBluetoothLeBroadcastMetadata(), false);
                         mSelectedPreference.setOrder(1);
                     });
+            }
         }
         mSelectedPreference = pref;
         mLeBroadcastAssistant.addSource(mCachedDevice.getDevice(),
@@ -454,4 +502,8 @@
     public void setSourceId(int sourceId) {
         mSourceId = sourceId;
     }
+
+    private BluetoothLeBroadcastMetadata convertToBroadcastMetadata(String qrCodeString) {
+        return mLocalBroadcastMetadata.convertToBroadcastMetadata(qrCodeString);
+    }
 }
diff --git a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java
index 1282abd..d34476b 100644
--- a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java
+++ b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java
@@ -137,7 +137,8 @@
                 .putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_SINK_IS_GROUP, true)
                 .putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_DEVICE_SINK,
                         mCachedDevice.getDevice());
-        mContext.startActivity(intent);
+        mBluetoothFindBroadcastsFragment.startActivityForResult(intent,
+                BluetoothFindBroadcastsFragment.REQUEST_SCAN_BT_BROADCAST_QR_CODE);
     }
 
     @Override
diff --git a/src/com/android/settings/bluetooth/QrCodeScanModeController.java b/src/com/android/settings/bluetooth/QrCodeScanModeController.java
deleted file mode 100644
index 4504b4b..0000000
--- a/src/com/android/settings/bluetooth/QrCodeScanModeController.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.bluetooth;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothLeBroadcastMetadata;
-import android.content.Context;
-import android.util.Log;
-
-import com.android.settingslib.bluetooth.BluetoothUtils;
-import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
-import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
-import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastMetadata;
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-
-public class QrCodeScanModeController {
-
-    private static final boolean DEBUG = BluetoothUtils.D;
-    private static final String TAG = "QrCodeScanModeController";
-
-    private LocalBluetoothLeBroadcastMetadata mLocalBroadcastMetadata;
-    private LocalBluetoothLeBroadcastAssistant mLocalBroadcastAssistant;
-    private LocalBluetoothManager mLocalBluetoothManager;
-    private LocalBluetoothProfileManager mProfileManager;
-
-    public QrCodeScanModeController(Context context) {
-        if (DEBUG) {
-            Log.d(TAG, "QrCodeScanModeController constructor.");
-        }
-        mLocalBluetoothManager = Utils.getLocalBtManager(context);
-        mProfileManager = mLocalBluetoothManager.getProfileManager();
-        mLocalBroadcastMetadata = new LocalBluetoothLeBroadcastMetadata();
-        CachedBluetoothDeviceManager cachedDeviceManager = new CachedBluetoothDeviceManager(context,
-                mLocalBluetoothManager);
-        mLocalBroadcastAssistant = new LocalBluetoothLeBroadcastAssistant(context,
-                cachedDeviceManager, mProfileManager);
-    }
-
-    private BluetoothLeBroadcastMetadata convertToBroadcastMetadata(String qrCodeString) {
-        return mLocalBroadcastMetadata.convertToBroadcastMetadata(qrCodeString);
-    }
-
-    public void addSource(BluetoothDevice sink, String sourceMetadata,
-            boolean isGroupOp) {
-        mLocalBroadcastAssistant.addSource(sink,
-                convertToBroadcastMetadata(sourceMetadata), isGroupOp);
-    }
-}
diff --git a/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java b/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
index 767461b..4baaef4 100644
--- a/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
+++ b/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
@@ -16,9 +16,11 @@
 
 package com.android.settings.bluetooth;
 
+import android.app.Activity;
 import android.app.settings.SettingsEnums;
 import android.bluetooth.BluetoothDevice;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.Matrix;
 import android.graphics.Outline;
 import android.graphics.Rect;
@@ -67,13 +69,14 @@
 
     private static final Duration VIBRATE_DURATION_QR_CODE_RECOGNITION = Duration.ofMillis(3);
 
+    public static final String KEY_BROADCAST_METADATA = "key_broadcast_metadata";
+
     private boolean mIsGroupOp;
     private int mCornerRadius;
     private BluetoothDevice mSink;
     private String mBroadcastMetadata;
     private Context mContext;
     private QrCamera mCamera;
-    private QrCodeScanModeController mController;
     private TextureView mTextureView;
     private TextView mSummary;
     private TextView mErrorMessage;
@@ -87,7 +90,6 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mContext = getContext();
-        mController = new QrCodeScanModeController(mContext);
     }
 
     @Override
@@ -215,10 +217,10 @@
                     break;
 
                 case MESSAGE_SCAN_BROADCAST_SUCCESS:
-                    /* TODO(b/265281156) : Move the logic to BluetoothFindBroadcastsFragment.
-                    *  We only pass the QR code string to the previous page.
-                    */
-                    mController.addSource(mSink, mBroadcastMetadata, mIsGroupOp);
+                    Log.d(TAG, "scan success");
+                    final Intent resultIntent = new Intent();
+                    resultIntent.putExtra(KEY_BROADCAST_METADATA, mBroadcastMetadata);
+                    getActivity().setResult(Activity.RESULT_OK, resultIntent);
                     notifyUserForQrCodeRecognition();
                     break;
                 default:
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreferenceTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreferenceTest.java
new file mode 100644
index 0000000..85d12b9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreferenceTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothBroadcastSourcePreferenceTest {
+
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Spy
+    Context mContext = ApplicationProvider.getApplicationContext();
+    @Mock
+    BluetoothLeBroadcastReceiveState mBroadcastReceiveState;
+    @Mock
+    BluetoothLeBroadcastMetadata mBroadcastMetadata;
+
+    BluetoothBroadcastSourcePreference mPreference;
+
+
+    @Before
+    public void setUp() {
+        mPreference = new BluetoothBroadcastSourcePreference(mContext);
+    }
+
+    @Test
+    public void isCreatedByReceiveState_updateUiFromReceviceState_returnsTrue() {
+        mPreference.updateReceiveStateAndRefreshUi(mBroadcastReceiveState);
+
+        assertThat(mPreference.isCreatedByReceiveState()).isTrue();
+    }
+
+    @Test
+    public void isCreatedByReceiveState_updateUiFromMetadata_returnsFalse() {
+        mPreference.updateMetadataAndRefreshUi(mBroadcastMetadata, true);
+
+        assertThat(mPreference.isCreatedByReceiveState()).isFalse();
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragmentTest.java
new file mode 100644
index 0000000..9551c9a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragmentTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+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.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.preference.PreferenceCategory;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothFindBroadcastsFragmentTest {
+
+    private static final String TEST_ADDRESS = "55:66:77:88:99:AA";
+
+    private BluetoothFindBroadcastsFragment mFragment;
+    private FragmentActivity mActivity;
+    private Context mContext;
+    private FragmentTransaction mFragmentTransaction;
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private CachedBluetoothDevice mCachedDevice;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private LocalBluetoothManager mLocalManager;
+    @Mock
+    private PreferenceCategory mPreferenceCategroy;
+    @Mock
+    private LocalBluetoothLeBroadcastAssistant mBroadcastAssistant;
+    @Mock
+    private BluetoothLeBroadcastMetadata mBroadcastMetadata;
+    @Mock
+    private BluetoothBroadcastSourcePreference mBroadcastSourcePreference;
+    @Mock
+    private BluetoothBroadcastSourcePreference mBroadcastSourcePreferenceUserClick;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        FakeFeatureFactory.setupForTest();
+
+        mFragment = spy(new BluetoothFindBroadcastsFragment());
+        doReturn(mLocalManager).when(mFragment).getLocalBluetoothManager(any());
+        doReturn(mCachedDevice).when(mFragment).getCachedDevice(any());
+        doReturn(mBroadcastAssistant).when(mFragment).getLeBroadcastAssistant();
+        doReturn(mPreferenceCategroy).when(mFragment).findPreference(any());
+        mActivity = Robolectric.setupActivity(FragmentActivity.class);
+        when(mFragment.getActivity()).thenReturn(mActivity);
+
+        FragmentManager fragmentManager = mock(FragmentManager.class);
+        when(mFragment.getFragmentManager()).thenReturn(fragmentManager);
+        mFragmentTransaction = mock(FragmentTransaction.class);
+        when(fragmentManager.beginTransaction()).thenReturn(mFragmentTransaction);
+
+        when(mCachedDevice.getAddress()).thenReturn(TEST_ADDRESS);
+        when(mCachedDevice.getIdentityAddress()).thenReturn(TEST_ADDRESS);
+        Bundle args = new Bundle();
+        args.putString(BluetoothFindBroadcastsFragment.KEY_DEVICE_ADDRESS, TEST_ADDRESS);
+        mFragment.setArguments(args);
+        mFragment.onAttach(mContext);
+    }
+
+    @Test
+    public void verifyOnAttachResult() {
+        assertThat(mFragment.mDeviceAddress).isEqualTo(TEST_ADDRESS);
+        assertThat(mFragment.mManager).isEqualTo(mLocalManager);
+        assertThat(mFragment.mCachedDevice).isEqualTo(mCachedDevice);
+    }
+
+    @Test
+    public void addSource_selectedPrefIsNull_returnsNewPref() {
+        mFragment.mSelectedPreference = null;
+
+        mFragment.addSource(mBroadcastSourcePreference);
+
+        assertThat(mFragment.mSelectedPreference).isEqualTo(mBroadcastSourcePreference);
+    }
+
+    @Test
+    public void addSource_sourcePrefIsCreatedByReceiveState_removesOldPref() {
+        mFragment.mSelectedPreference = mBroadcastSourcePreference;
+        mFragment.mBroadcastSourceListCategory = mPreferenceCategroy;
+        doReturn(true).when(mFragment.mSelectedPreference).isCreatedByReceiveState();
+
+        mFragment.addSource(mBroadcastSourcePreferenceUserClick);
+
+        verify(mFragment.mBroadcastSourceListCategory).removePreference(mBroadcastSourcePreference);
+        assertThat(mFragment.mSelectedPreference).isEqualTo(mBroadcastSourcePreferenceUserClick);
+    }
+
+    @Test
+    public void addSource_sourcePrefIsCreatedByMetadata_updatesOldPref() {
+        when(mBroadcastSourcePreference.isCreatedByReceiveState()).thenReturn(false);
+        when(mBroadcastSourcePreference.getBluetoothLeBroadcastMetadata())
+                .thenReturn(mBroadcastMetadata);
+        mFragment.mSelectedPreference = mBroadcastSourcePreference;
+        mFragment.mBroadcastSourceListCategory = mPreferenceCategroy;
+
+        mFragment.addSource(mBroadcastSourcePreferenceUserClick);
+
+        verify(mBroadcastSourcePreference).updateMetadataAndRefreshUi(
+                any(BluetoothLeBroadcastMetadata.class), anyBoolean());
+        assertThat(mFragment.mSelectedPreference).isEqualTo(mBroadcastSourcePreferenceUserClick);
+    }
+
+}