Loading packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt +2 −1 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel.Companion.HIGH_SENSITIVITY import com.android.settingslib.metadata.SensitivityLevel.Companion.UNKNOWN_SENSITIVITY import com.android.settingslib.metadata.getPreferenceIcon import com.android.settingslib.metadata.isPreferenceIndexable import com.android.settingslib.preference.PreferenceScreenCreator import com.android.settingslib.preference.PreferenceScreenFactory import com.android.settingslib.preference.PreferenceScreenProvider Loading Loading @@ -470,7 +471,7 @@ fun PreferenceMetadata.toProto( if (metadata.keywords != 0) keywords = metadata.keywords val preferenceExtras = metadata.extras(context) preferenceExtras?.let { extras = it.toProto() } indexable = metadata.isIndexable(context) indexable = metadata.isPreferenceIndexable(context) enabled = metadata.isEnabled(context) if (metadata is PreferenceAvailabilityProvider) { available = metadata.isAvailable(context) Loading packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceMetadata.kt +23 −16 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import androidx.annotation.StringRes * - [PreferenceTitleProvider]: provide dynamic title content * - [PreferenceSummaryProvider]: provide dynamic summary content (e.g. based on preference value) * - [PreferenceIconProvider]: provide dynamic icon content (e.g. based on flag) * - [PreferenceIndexableProvider]: provide if it is indexable dynamically * - [PreferenceAvailabilityProvider]: provide preference availability (e.g. based on flag) * - [PreferenceLifecycleProvider]: provide the lifecycle callbacks and notify state change * Loading Loading @@ -86,6 +87,18 @@ interface PreferenceMetadata { val icon: Int @DrawableRes get() = 0 /** * Returns if preference is indexable for settings search. * * The override should return constant value `true` / `false` only, and implement * [PreferenceIndexableProvider] if the result is determined dynamically. * * Note: If [indexable] of a [PreferenceScreenMetadata] returns `false`, all the preferences on * the screen are not indexable. */ val indexable: Boolean get() = true /** Additional keywords for indexing. */ val keywords: Int @StringRes get() = 0 Loading @@ -111,21 +124,6 @@ interface PreferenceMetadata { */ fun tags(context: Context): Array<String> = arrayOf() /** * Returns if preference is indexable for settings search. * * Return `false` only when the preference is unavailable for indexing on current device. If it * is available on condition, override [PreferenceAvailabilityProvider]. * * Note: If a [PreferenceScreenMetadata.isIndexable] returns `false`, all the preferences on the * screen are not indexable. */ fun isIndexable(context: Context): Boolean = when (this) { is PreferenceGroup -> getPreferenceTitle(context)?.isNotEmpty() == true else -> true } /** * Returns if the preference is available on condition, which indicates its availability could * be changed at runtime and should not be cached (e.g. for indexing). Loading @@ -142,6 +140,10 @@ interface PreferenceMetadata { * * UI framework normally does not allow user to interact with the preference widget when it is * disabled. * * If [PreferenceScreenMetadata.isEnabled] is override and `false` value is returned * potentially, [PreferenceIndexableProvider] should be implemented to indicate that the screen * might not be accessible and thus no indexable. */ fun isEnabled(context: Context): Boolean = true Loading Loading @@ -169,7 +171,12 @@ interface PreferenceMetadata { } /** Metadata of preference group. */ @AnyThread interface PreferenceGroup : PreferenceMetadata @AnyThread interface PreferenceGroup : PreferenceMetadata { override val indexable get() = title != 0 } /** Metadata of preference category. */ @AnyThread Loading packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceSearchIndexablesProvider.kt +18 −7 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import kotlinx.coroutines.runBlocking * A screen is qualified as indexable only when: * - [PreferenceScreenMetadata.hasCompleteHierarchy] is true: hybrid mode is not supported to avoid * potential conflict. * - **AND** [PreferenceScreenMetadata.isIndexable] is true. * - **AND** [PreferenceScreenMetadata.isPreferenceIndexable] is true. * - **AND** [PreferenceScreenMetadata.isFlagEnabled] is true. * * The strategy to provide indexing data is: Loading Loading @@ -74,7 +74,7 @@ abstract class PreferenceSearchIndexablesProvider : SearchIndexablesProvider() { val isAvailableOnCondition = isParentAvailableOnCondition || metadata.isAvailableOnCondition if ( metadata.isIndexable(context) && metadata.isPreferenceIndexable(context) && (isAvailableOnCondition || metadata.isDynamic) && !metadata.isScreenEntryPoint(preferenceScreenMetadata) ) { Loading @@ -88,7 +88,7 @@ abstract class PreferenceSearchIndexablesProvider : SearchIndexablesProvider() { } preferenceScreenMetadata .getPreferenceHierarchy(context, coroutineScope) .visitRecursively(false) .visitRecursively(preferenceScreenMetadata is PreferenceIndexableProvider) } Log.d(TAG, "dynamicRawData: ${cursor.count} in ${SystemClock.elapsedRealtime() - start}ms") return cursor Loading @@ -104,7 +104,7 @@ abstract class PreferenceSearchIndexablesProvider : SearchIndexablesProvider() { fun PreferenceHierarchyNode.visitRecursively() { if (metadata.isAvailableOnCondition) return if ( metadata.isIndexable(context) && metadata.isPreferenceIndexable(context) && !metadata.isDynamic && !metadata.isScreenEntryPoint(preferenceScreenMetadata) ) { Loading Loading @@ -140,10 +140,18 @@ abstract class PreferenceSearchIndexablesProvider : SearchIndexablesProvider() { val preferenceScreenMetadata = factory.create(context) if ( preferenceScreenMetadata.hasCompleteHierarchy() && preferenceScreenMetadata.isIndexable(context) && preferenceScreenMetadata.isPreferenceIndexable(context) && preferenceScreenMetadata.isFlagEnabled(context) ) { if (preferenceScreenMetadata.isEnabled(context)) { action(preferenceScreenMetadata, this) } else if (preferenceScreenMetadata !is PreferenceIndexableProvider) { val key = preferenceScreenMetadata.key Log.e(TAG, "Screen $key does not implement PreferenceIndexableProvider") } else { val key = preferenceScreenMetadata.key Log.d(TAG, "Screen $key is disabled thus not indexable") } } } } Loading Loading @@ -201,7 +209,10 @@ abstract class PreferenceSearchIndexablesProvider : SearchIndexablesProvider() { * Dynamic summary is not taken into account because it is not used by settings search now. */ private val PreferenceMetadata.isDynamic: Boolean get() = this is PreferenceTitleProvider || this is PreferenceIconProvider get() = this is PreferenceTitleProvider || this is PreferenceIconProvider || this is PreferenceIndexableProvider /** * Returns if the preference is an entry point of another screen. Loading packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt +21 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,27 @@ interface PreferenceIconProvider { fun getIcon(context: Context): Int } /** Interface to provide information for settings search. */ interface PreferenceIndexableProvider { /** * Returns if preference is indexable for settings search. * * Return `false` only when the preference is unavailable for indexing on current device. * * Note: * - For [PreferenceScreenMetadata], all the preferences on the screen are not indexable if * [isIndexable] returns `false`. * - If [PreferenceScreenMetadata.isEnabled] is implemented, it should also implement this * interface to tell that the screen might be disabled and thus not accessible, in which case * all the preferences on the screen are not indexable. * - Implement [PreferenceAvailabilityProvider] if it is available on condition but check * [PreferenceAvailabilityProvider.isAvailable] inside [isIndexable] is optional. Unavailable * preference is always non indexable no matter what [isIndexable] returns. */ fun isIndexable(context: Context): Boolean } /** Interface to provide the state of preference availability. */ interface PreferenceAvailabilityProvider { Loading packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/Utils.kt +9 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,15 @@ fun PreferenceMetadata.getPreferenceIcon(context: Context): Int = else -> 0 } /** * Returns whether the preference is indexable. * * @return [PreferenceIndexableProvider.isIndexable] if implemented, otherwise * [PreferenceMetadata.indexable] */ fun PreferenceMetadata.isPreferenceIndexable(context: Context): Boolean = if (this is PreferenceIndexableProvider) isIndexable(context) else indexable /** * Performs preference hierarchy operation with a new [CoroutineScope]. * Loading Loading
packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt +2 −1 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel.Companion.HIGH_SENSITIVITY import com.android.settingslib.metadata.SensitivityLevel.Companion.UNKNOWN_SENSITIVITY import com.android.settingslib.metadata.getPreferenceIcon import com.android.settingslib.metadata.isPreferenceIndexable import com.android.settingslib.preference.PreferenceScreenCreator import com.android.settingslib.preference.PreferenceScreenFactory import com.android.settingslib.preference.PreferenceScreenProvider Loading Loading @@ -470,7 +471,7 @@ fun PreferenceMetadata.toProto( if (metadata.keywords != 0) keywords = metadata.keywords val preferenceExtras = metadata.extras(context) preferenceExtras?.let { extras = it.toProto() } indexable = metadata.isIndexable(context) indexable = metadata.isPreferenceIndexable(context) enabled = metadata.isEnabled(context) if (metadata is PreferenceAvailabilityProvider) { available = metadata.isAvailable(context) Loading
packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceMetadata.kt +23 −16 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import androidx.annotation.StringRes * - [PreferenceTitleProvider]: provide dynamic title content * - [PreferenceSummaryProvider]: provide dynamic summary content (e.g. based on preference value) * - [PreferenceIconProvider]: provide dynamic icon content (e.g. based on flag) * - [PreferenceIndexableProvider]: provide if it is indexable dynamically * - [PreferenceAvailabilityProvider]: provide preference availability (e.g. based on flag) * - [PreferenceLifecycleProvider]: provide the lifecycle callbacks and notify state change * Loading Loading @@ -86,6 +87,18 @@ interface PreferenceMetadata { val icon: Int @DrawableRes get() = 0 /** * Returns if preference is indexable for settings search. * * The override should return constant value `true` / `false` only, and implement * [PreferenceIndexableProvider] if the result is determined dynamically. * * Note: If [indexable] of a [PreferenceScreenMetadata] returns `false`, all the preferences on * the screen are not indexable. */ val indexable: Boolean get() = true /** Additional keywords for indexing. */ val keywords: Int @StringRes get() = 0 Loading @@ -111,21 +124,6 @@ interface PreferenceMetadata { */ fun tags(context: Context): Array<String> = arrayOf() /** * Returns if preference is indexable for settings search. * * Return `false` only when the preference is unavailable for indexing on current device. If it * is available on condition, override [PreferenceAvailabilityProvider]. * * Note: If a [PreferenceScreenMetadata.isIndexable] returns `false`, all the preferences on the * screen are not indexable. */ fun isIndexable(context: Context): Boolean = when (this) { is PreferenceGroup -> getPreferenceTitle(context)?.isNotEmpty() == true else -> true } /** * Returns if the preference is available on condition, which indicates its availability could * be changed at runtime and should not be cached (e.g. for indexing). Loading @@ -142,6 +140,10 @@ interface PreferenceMetadata { * * UI framework normally does not allow user to interact with the preference widget when it is * disabled. * * If [PreferenceScreenMetadata.isEnabled] is override and `false` value is returned * potentially, [PreferenceIndexableProvider] should be implemented to indicate that the screen * might not be accessible and thus no indexable. */ fun isEnabled(context: Context): Boolean = true Loading Loading @@ -169,7 +171,12 @@ interface PreferenceMetadata { } /** Metadata of preference group. */ @AnyThread interface PreferenceGroup : PreferenceMetadata @AnyThread interface PreferenceGroup : PreferenceMetadata { override val indexable get() = title != 0 } /** Metadata of preference category. */ @AnyThread Loading
packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceSearchIndexablesProvider.kt +18 −7 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import kotlinx.coroutines.runBlocking * A screen is qualified as indexable only when: * - [PreferenceScreenMetadata.hasCompleteHierarchy] is true: hybrid mode is not supported to avoid * potential conflict. * - **AND** [PreferenceScreenMetadata.isIndexable] is true. * - **AND** [PreferenceScreenMetadata.isPreferenceIndexable] is true. * - **AND** [PreferenceScreenMetadata.isFlagEnabled] is true. * * The strategy to provide indexing data is: Loading Loading @@ -74,7 +74,7 @@ abstract class PreferenceSearchIndexablesProvider : SearchIndexablesProvider() { val isAvailableOnCondition = isParentAvailableOnCondition || metadata.isAvailableOnCondition if ( metadata.isIndexable(context) && metadata.isPreferenceIndexable(context) && (isAvailableOnCondition || metadata.isDynamic) && !metadata.isScreenEntryPoint(preferenceScreenMetadata) ) { Loading @@ -88,7 +88,7 @@ abstract class PreferenceSearchIndexablesProvider : SearchIndexablesProvider() { } preferenceScreenMetadata .getPreferenceHierarchy(context, coroutineScope) .visitRecursively(false) .visitRecursively(preferenceScreenMetadata is PreferenceIndexableProvider) } Log.d(TAG, "dynamicRawData: ${cursor.count} in ${SystemClock.elapsedRealtime() - start}ms") return cursor Loading @@ -104,7 +104,7 @@ abstract class PreferenceSearchIndexablesProvider : SearchIndexablesProvider() { fun PreferenceHierarchyNode.visitRecursively() { if (metadata.isAvailableOnCondition) return if ( metadata.isIndexable(context) && metadata.isPreferenceIndexable(context) && !metadata.isDynamic && !metadata.isScreenEntryPoint(preferenceScreenMetadata) ) { Loading Loading @@ -140,10 +140,18 @@ abstract class PreferenceSearchIndexablesProvider : SearchIndexablesProvider() { val preferenceScreenMetadata = factory.create(context) if ( preferenceScreenMetadata.hasCompleteHierarchy() && preferenceScreenMetadata.isIndexable(context) && preferenceScreenMetadata.isPreferenceIndexable(context) && preferenceScreenMetadata.isFlagEnabled(context) ) { if (preferenceScreenMetadata.isEnabled(context)) { action(preferenceScreenMetadata, this) } else if (preferenceScreenMetadata !is PreferenceIndexableProvider) { val key = preferenceScreenMetadata.key Log.e(TAG, "Screen $key does not implement PreferenceIndexableProvider") } else { val key = preferenceScreenMetadata.key Log.d(TAG, "Screen $key is disabled thus not indexable") } } } } Loading Loading @@ -201,7 +209,10 @@ abstract class PreferenceSearchIndexablesProvider : SearchIndexablesProvider() { * Dynamic summary is not taken into account because it is not used by settings search now. */ private val PreferenceMetadata.isDynamic: Boolean get() = this is PreferenceTitleProvider || this is PreferenceIconProvider get() = this is PreferenceTitleProvider || this is PreferenceIconProvider || this is PreferenceIndexableProvider /** * Returns if the preference is an entry point of another screen. Loading
packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt +21 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,27 @@ interface PreferenceIconProvider { fun getIcon(context: Context): Int } /** Interface to provide information for settings search. */ interface PreferenceIndexableProvider { /** * Returns if preference is indexable for settings search. * * Return `false` only when the preference is unavailable for indexing on current device. * * Note: * - For [PreferenceScreenMetadata], all the preferences on the screen are not indexable if * [isIndexable] returns `false`. * - If [PreferenceScreenMetadata.isEnabled] is implemented, it should also implement this * interface to tell that the screen might be disabled and thus not accessible, in which case * all the preferences on the screen are not indexable. * - Implement [PreferenceAvailabilityProvider] if it is available on condition but check * [PreferenceAvailabilityProvider.isAvailable] inside [isIndexable] is optional. Unavailable * preference is always non indexable no matter what [isIndexable] returns. */ fun isIndexable(context: Context): Boolean } /** Interface to provide the state of preference availability. */ interface PreferenceAvailabilityProvider { Loading
packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/Utils.kt +9 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,15 @@ fun PreferenceMetadata.getPreferenceIcon(context: Context): Int = else -> 0 } /** * Returns whether the preference is indexable. * * @return [PreferenceIndexableProvider.isIndexable] if implemented, otherwise * [PreferenceMetadata.indexable] */ fun PreferenceMetadata.isPreferenceIndexable(context: Context): Boolean = if (this is PreferenceIndexableProvider) isIndexable(context) else indexable /** * Performs preference hierarchy operation with a new [CoroutineScope]. * Loading