Merge "Add new sample rate dialog layout for new Bluetooth developer option"
diff --git a/src/com/android/settings/core/BasePreferenceController.java b/src/com/android/settings/core/BasePreferenceController.java
index cef372e..eeb77ad 100644
--- a/src/com/android/settings/core/BasePreferenceController.java
+++ b/src/com/android/settings/core/BasePreferenceController.java
@@ -275,6 +275,14 @@
     }
 
     /**
+     * Updates dynamic raw data for search provider.
+     *
+     * Called by SearchIndexProvider#getDynamicRawDataToIndex
+     */
+    public void updateDynamicRawDataToIndex(List<SearchIndexableRaw> rawData) {
+    }
+
+    /**
      * Set {@link UiBlockListener}
      *
      * @param uiBlockListener listener to set
@@ -308,4 +316,4 @@
      */
     public interface UiBlocker {
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/core/PreferenceControllerMixin.java b/src/com/android/settings/core/PreferenceControllerMixin.java
index fa61552..6ddea3d 100644
--- a/src/com/android/settings/core/PreferenceControllerMixin.java
+++ b/src/com/android/settings/core/PreferenceControllerMixin.java
@@ -18,8 +18,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.settingslib.search.SearchIndexableRaw;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.search.SearchIndexableRaw;
 
 import java.util.List;
 
@@ -62,4 +62,12 @@
      */
     default void updateRawDataToIndex(List<SearchIndexableRaw> rawData) {
     }
+
+    /**
+     * Updates dynamic raw data for search provider.
+     *
+     * Called by SearchIndexProvider#getDynamicRawDataToIndex
+     */
+    default void updateDynamicRawDataToIndex(List<SearchIndexableRaw> rawData) {
+    }
 }
diff --git a/src/com/android/settings/search/BaseSearchIndexProvider.java b/src/com/android/settings/search/BaseSearchIndexProvider.java
index abf1c99..da89062 100644
--- a/src/com/android/settings/search/BaseSearchIndexProvider.java
+++ b/src/com/android/settings/search/BaseSearchIndexProvider.java
@@ -77,8 +77,25 @@
     }
 
     @Override
+    @CallSuper
     public List<SearchIndexableRaw> getDynamicRawDataToIndex(Context context, boolean enabled) {
-        return null;
+        final List<SearchIndexableRaw> dynamicRaws = new ArrayList<>();
+        final List<AbstractPreferenceController> controllers = getPreferenceControllers(context);
+        if (controllers == null || controllers.isEmpty()) {
+            return dynamicRaws;
+        }
+        for (AbstractPreferenceController controller : controllers) {
+            if (controller instanceof PreferenceControllerMixin) {
+                ((PreferenceControllerMixin) controller).updateDynamicRawDataToIndex(dynamicRaws);
+            } else if (controller instanceof BasePreferenceController) {
+                ((BasePreferenceController) controller).updateDynamicRawDataToIndex(dynamicRaws);
+            } else {
+                Log.e(TAG, controller.getClass().getName()
+                        + " must implement " + PreferenceControllerMixin.class.getName()
+                        + " treating the dynamic indexable");
+            }
+        }
+        return dynamicRaws;
     }
 
     @Override
diff --git a/src/com/android/settings/slices/Sliceable.java b/src/com/android/settings/slices/Sliceable.java
index aab4906..ad27b7c 100644
--- a/src/com/android/settings/slices/Sliceable.java
+++ b/src/com/android/settings/slices/Sliceable.java
@@ -25,6 +25,8 @@
 import android.net.Uri;
 import android.widget.Toast;
 
+import androidx.slice.Slice;
+
 import com.android.settings.R;
 
 /**
@@ -49,13 +51,24 @@
      * <p>
      * This does not guarantee the setting is available.
      *
-     * @return {@code true} if the controller should be used externally as a Slice.
+     * @return {@code true} if the controller should be used as a Slice.
      */
     default boolean isSliceable() {
         return false;
     }
 
     /**
+     * Determines if the {@link Slice} should be public to other apps.
+     * This does not guarantee the setting is available.
+     *
+     * @return {@code true} if the controller should be used as a Slice, and is
+     * publicly visible to other apps.
+     */
+    default boolean isPublicSlice() {
+        return false;
+    }
+
+    /**
      * Returns uri for this slice (if it's a slice).
      */
     default Uri getSliceUri() {
diff --git a/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java b/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
index 5e5e573..5221630 100644
--- a/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
+++ b/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
@@ -28,6 +28,7 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.search.SearchIndexableRaw;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -77,6 +78,12 @@
         public String getPreferenceKey() {
             return TEST_PREF_KEY;
         }
+
+        @Override
+        public void updateDynamicRawDataToIndex(List<SearchIndexableRaw> rawData) {
+            final SearchIndexableRaw raw = new SearchIndexableRaw(this.mContext);
+            rawData.add(raw);
+        }
     }
 
     @Test
@@ -190,4 +197,18 @@
 
         assertThat(nonIndexableKeys).contains("pref_key_5");
     }
+
+    @Test
+    public void getDynamicRawDataToIndex_noPreferenceController_shouldReturnEmptyList() {
+        assertThat(mIndexProvider.getDynamicRawDataToIndex(mContext, true)).isEmpty();
+    }
+
+    @Test
+    public void getDynamicRawDataToIndex_hasDynamicRaw_shouldNotEmpty() {
+        List<AbstractPreferenceController> controllers = new ArrayList<>();
+        controllers.add(new AvailablePreferenceController(mContext));
+        doReturn(controllers).when(mIndexProvider).createPreferenceControllers(mContext);
+
+        assertThat(mIndexProvider.getDynamicRawDataToIndex(mContext, true)).isNotEmpty();
+    }
 }