1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settingslib.metadata 18 19 import android.content.Context 20 import android.content.Intent 21 import android.os.Bundle 22 import androidx.annotation.AnyThread 23 import androidx.annotation.DrawableRes 24 import androidx.annotation.StringRes 25 26 /** 27 * Interface provides preference metadata (title, summary, icon, etc.). 28 * 29 * Besides the existing APIs, subclass could integrate with following interface to provide more 30 * information: 31 * - [PreferenceTitleProvider]: provide dynamic title content 32 * - [PreferenceSummaryProvider]: provide dynamic summary content (e.g. based on preference value) 33 * - [PreferenceIconProvider]: provide dynamic icon content (e.g. based on flag) 34 * - [PreferenceAvailabilityProvider]: provide preference availability (e.g. based on flag) 35 * - [PreferenceLifecycleProvider]: provide the lifecycle callbacks and notify state change 36 * 37 * Notes: 38 * - UI framework support: 39 * - This class does not involve any UI logic, it is the data layer. 40 * - Subclass could integrate with datastore and UI widget to provide UI layer. For instance, 41 * `PreferenceBinding` supports Jetpack Preference binding. 42 * - Datastore: 43 * - Subclass should implement the [PersistentPreference] to note that current preference is 44 * persistent in datastore. 45 * - It is always recommended to support back up preference value changed by user. Typically, 46 * the back up and restore happen within datastore, the [allowBackup] API is to mark if 47 * current preference value should be backed up (backup allowed by default). 48 * - Preference indexing for search: 49 * - Override [isIndexable] API to mark if preference is indexable (enabled by default). 50 * - If [isIndexable] returns true, preference title and summary will be indexed with cache. 51 * More indexing data could be provided through [keywords]. 52 * - Settings search will cache the preference title/summary/keywords for indexing. The cache is 53 * invalidated when system locale changed, app upgraded, etc. 54 * - Dynamic content is not suitable to be cached for indexing. Subclass that implements 55 * [PreferenceTitleProvider] / [PreferenceSummaryProvider] will not have its title / summary 56 * indexed. 57 */ 58 @AnyThread 59 interface PreferenceMetadata { 60 61 /** Preference key. */ 62 val key: String 63 64 /** 65 * Preference title resource id. 66 * 67 * Implement [PreferenceTitleProvider] if title is generated dynamically. 68 */ 69 val title: Int 70 @StringRes get() = 0 71 72 /** 73 * Preference summary resource id. 74 * 75 * Implement [PreferenceSummaryProvider] if summary is generated dynamically (e.g. summary is 76 * provided per preference value) 77 */ 78 val summary: Int 79 @StringRes get() = 0 80 81 /** Icon of the preference. */ 82 val icon: Int 83 @DrawableRes get() = 0 84 85 /** Additional keywords for indexing. */ 86 val keywords: Int 87 @StringRes get() = 0 88 89 /** 90 * Return the extras Bundle object associated with this preference. 91 * 92 * It is used to provide more *internal* information for metadata. External app is not expected 93 * to use this information as it could be changed in future. Consider [tags] for external usage. 94 */ extrasnull95 fun extras(context: Context): Bundle? = null 96 97 /** 98 * Returns the tags associated with this preference. 99 * 100 * Unlike [extras], tags are exposed for external usage. The returned tag list must be constants 101 * and **append only**. Do not edit/delete existing tag strings as it can cause backward 102 * compatibility issue. 103 * 104 * Use cases: 105 * - identify a specific preference 106 * - identify a group of preferences related to network settings 107 */ 108 fun tags(context: Context): Array<String> = arrayOf() 109 110 /** 111 * Returns if preference is indexable, default value is `true`. 112 * 113 * Return `false` only when the preference is always unavailable on current device. If it is 114 * conditional available, override [PreferenceAvailabilityProvider]. 115 */ 116 fun isIndexable(context: Context): Boolean = true 117 118 /** 119 * Returns if preference is enabled. 120 * 121 * UI framework normally does not allow user to interact with the preference widget when it is 122 * disabled. 123 */ 124 fun isEnabled(context: Context): Boolean = true 125 126 /** Returns the keys of depended preferences. */ 127 fun dependencies(context: Context): Array<String> = arrayOf() 128 129 /** Returns if the preference is persistent in datastore. */ 130 fun isPersistent(context: Context): Boolean = false 131 132 /** 133 * Returns if preference value backup is allowed (by default returns `true` if preference is 134 * persistent). 135 */ 136 fun allowBackup(context: Context): Boolean = isPersistent(context) 137 138 /** Returns preference intent. */ 139 fun intent(context: Context): Intent? = null 140 } 141 142 /** Metadata of preference group. */ 143 @AnyThread interface PreferenceGroup : PreferenceMetadata 144 145 /** Metadata of preference category. */ 146 @AnyThread 147 open class PreferenceCategory(override val key: String, override val title: Int) : PreferenceGroup 148