Merge "[Catalyst] Create preference widget for placeholder" into main
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt
index bde4217..a2b826a 100644
--- a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt
@@ -166,10 +166,6 @@
         }
         return null
     }
-
-    /** Returns all the [PreferenceHierarchyNode]s appear in the hierarchy. */
-    fun getAllPreferences(): List<PreferenceHierarchyNode> =
-        mutableListOf<PreferenceHierarchyNode>().apply { forEachRecursively { add(it) } }
 }
 
 /**
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt
index 49acc1d..6b7be91 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt
@@ -108,6 +108,9 @@
     }
 }
 
+/** Interface indicates that a virtual [Preference] should be created for binding. */
+interface PreferenceBindingPlaceholder
+
 /** Abstract preference screen to provide preference hierarchy and binding factory. */
 interface PreferenceScreenCreator : PreferenceScreenMetadata, PreferenceScreenProvider {
 
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
index fbe8927..cfe6089 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
@@ -218,34 +218,47 @@
             preferenceScreen: PreferenceScreen,
             preferenceBindingFactory: PreferenceBindingFactory,
             preferenceHierarchy: PreferenceHierarchy,
-        ) =
-            preferenceScreen.bindRecursively(
-                preferenceBindingFactory,
-                preferenceHierarchy.getAllPreferences().associateBy { it.metadata.key },
-            )
-
-        private fun PreferenceGroup.bindRecursively(
-            preferenceBindingFactory: PreferenceBindingFactory,
-            preferences: Map<String, PreferenceHierarchyNode>,
-            storages: MutableMap<KeyValueStore, PreferenceDataStore> = mutableMapOf(),
         ) {
-            preferences[key]?.let { preferenceBindingFactory.bind(this, it) }
-            val count = preferenceCount
-            for (index in 0 until count) {
-                val preference = getPreference(index)
-                if (preference is PreferenceGroup) {
-                    preference.bindRecursively(preferenceBindingFactory, preferences, storages)
-                } else {
-                    preferences[preference.key]?.let {
-                        val metadata = it.metadata
-                        (metadata as? PersistentPreference<*>)?.storage(context)?.let { storage ->
-                            preference.preferenceDataStore =
-                                storages.getOrPut(storage) { PreferenceDataStoreAdapter(storage) }
+            val preferences = mutableMapOf<String, PreferenceHierarchyNode>()
+            preferenceHierarchy.forEachRecursively {
+                val metadata = it.metadata
+                preferences[metadata.key] = it
+            }
+            val storages = mutableMapOf<KeyValueStore, PreferenceDataStore>()
+
+            fun Preference.setPreferenceDataStore(metadata: PreferenceMetadata) {
+                (metadata as? PersistentPreference<*>)?.storage(context)?.let { storage ->
+                    preferenceDataStore =
+                        storages.getOrPut(storage) { PreferenceDataStoreAdapter(storage) }
+                }
+            }
+
+            fun PreferenceGroup.bindRecursively() {
+                preferences.remove(key)?.let { preferenceBindingFactory.bind(this, it) }
+                val count = preferenceCount
+                for (index in 0 until count) {
+                    val preference = getPreference(index)
+                    if (preference is PreferenceGroup) {
+                        preference.bindRecursively()
+                    } else {
+                        preferences.remove(preference.key)?.let {
+                            preference.setPreferenceDataStore(it.metadata)
+                            preferenceBindingFactory.bind(preference, it)
                         }
-                        preferenceBindingFactory.bind(preference, it)
                     }
                 }
             }
+
+            preferenceScreen.bindRecursively()
+            for (node in preferences.values) {
+                val metadata = node.metadata
+                val binding = preferenceBindingFactory.getPreferenceBinding(metadata)
+                if (binding !is PreferenceBindingPlaceholder) continue
+                val preference = binding.createWidget(preferenceScreen.context)
+                preference.setPreferenceDataStore(metadata)
+                preferenceBindingFactory.bind(preference, node, binding)
+                preferenceScreen.addPreference(preference)
+            }
         }
     }
 }