summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt10
-rw-r--r--packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGetterFlags.kt31
-rw-r--r--packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt237
3 files changed, 176 insertions, 102 deletions
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt
index 088bef230374..7aece5185800 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt
@@ -42,7 +42,7 @@ abstract class GetPreferenceGraphApiHandler(
callingUid: Int,
request: GetPreferenceGraphRequest,
): PreferenceGraphProto {
- val builder = PreferenceGraphBuilder.of(application, request)
+ val builder = PreferenceGraphBuilder.of(application, myUid, callingUid, request)
if (request.screenKeys.isEmpty()) {
for (key in PreferenceScreenRegistry.preferenceScreens.keys) {
builder.addPreferenceScreenFromRegistry(key)
@@ -68,16 +68,18 @@ constructor(
val screenKeys: Set<String> = setOf(),
val visitedScreens: Set<String> = setOf(),
val locale: Locale? = null,
- val includeValue: Boolean = true,
+ val flags: Int = PreferenceGetterFlags.ALL,
+ val includeValue: Boolean = true, // TODO: clean up
val includeValueDescriptor: Boolean = true,
)
object GetPreferenceGraphRequestCodec : MessageCodec<GetPreferenceGraphRequest> {
override fun encode(data: GetPreferenceGraphRequest): Bundle =
- Bundle(3).apply {
+ Bundle(4).apply {
putStringArray(KEY_SCREEN_KEYS, data.screenKeys.toTypedArray())
putStringArray(KEY_VISITED_KEYS, data.visitedScreens.toTypedArray())
putString(KEY_LOCALE, data.locale?.toLanguageTag())
+ putInt(KEY_FLAGS, data.flags)
}
override fun decode(data: Bundle): GetPreferenceGraphRequest {
@@ -88,12 +90,14 @@ object GetPreferenceGraphRequestCodec : MessageCodec<GetPreferenceGraphRequest>
screenKeys.toSet(),
visitedScreens.toSet(),
data.getString(KEY_LOCALE).toLocale(),
+ data.getInt(KEY_FLAGS),
)
}
private const val KEY_SCREEN_KEYS = "k"
private const val KEY_VISITED_KEYS = "v"
private const val KEY_LOCALE = "l"
+ private const val KEY_FLAGS = "f"
}
object PreferenceGraphProtoCodec : MessageCodec<PreferenceGraphProto> {
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGetterFlags.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGetterFlags.kt
new file mode 100644
index 000000000000..632f154b72ab
--- /dev/null
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGetterFlags.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 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.settingslib.graph
+
+/** Flags for preference getter operation. */
+object PreferenceGetterFlags {
+ const val VALUE = 1 shl 0
+ const val VALUE_DESCRIPTOR = 1 shl 1
+ const val METADATA = 1 shl 2
+ const val ALL = (1 shl 3) - 1
+
+ fun Int.includeValue() = (this and VALUE) != 0
+
+ fun Int.includeValueDescriptor() = (this and VALUE_DESCRIPTOR) != 0
+
+ fun Int.includeMetadata() = (this and METADATA) != 0
+}
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
index 6760e72be4a6..a65d24cf3d6f 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
@@ -31,6 +31,9 @@ import androidx.preference.Preference
import androidx.preference.PreferenceGroup
import androidx.preference.PreferenceScreen
import androidx.preference.TwoStatePreference
+import com.android.settingslib.graph.PreferenceGetterFlags.includeMetadata
+import com.android.settingslib.graph.PreferenceGetterFlags.includeValue
+import com.android.settingslib.graph.PreferenceGetterFlags.includeValueDescriptor
import com.android.settingslib.graph.proto.PreferenceGraphProto
import com.android.settingslib.graph.proto.PreferenceGroupProto
import com.android.settingslib.graph.proto.PreferenceProto
@@ -41,7 +44,6 @@ import com.android.settingslib.metadata.BooleanValue
import com.android.settingslib.metadata.PersistentPreference
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.PreferenceHierarchy
-import com.android.settingslib.metadata.PreferenceHierarchyNode
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceRestrictionProvider
import com.android.settingslib.metadata.PreferenceScreenBindingKeyProvider
@@ -50,6 +52,7 @@ import com.android.settingslib.metadata.PreferenceScreenRegistry
import com.android.settingslib.metadata.PreferenceSummaryProvider
import com.android.settingslib.metadata.PreferenceTitleProvider
import com.android.settingslib.metadata.RangeValue
+import com.android.settingslib.metadata.ReadWritePermit
import com.android.settingslib.preference.PreferenceScreenFactory
import com.android.settingslib.preference.PreferenceScreenProvider
import java.util.Locale
@@ -60,14 +63,17 @@ private const val TAG = "PreferenceGraphBuilder"
/** Builder of preference graph. */
class PreferenceGraphBuilder
-private constructor(private val context: Context, private val request: GetPreferenceGraphRequest) {
+private constructor(
+ private val context: Context,
+ private val myUid: Int,
+ private val callingUid: Int,
+ private val request: GetPreferenceGraphRequest,
+) {
private val preferenceScreenFactory by lazy {
PreferenceScreenFactory(context.ofLocale(request.locale))
}
private val builder by lazy { PreferenceGraphProto.newBuilder() }
private val visitedScreens = mutableSetOf<String>().apply { addAll(request.visitedScreens) }
- private val includeValue = request.includeValue
- private val includeValueDescriptor = request.includeValueDescriptor
private suspend fun init() {
for (key in request.screenKeys) {
@@ -229,7 +235,7 @@ private constructor(private val context: Context, private val request: GetPrefer
enabled = isEnabled
available = isVisible
persistent = isPersistent
- if (includeValue && isPersistent && this@toProto is TwoStatePreference) {
+ if (request.flags.includeValue() && isPersistent && this@toProto is TwoStatePreference) {
value = preferenceValueProto { booleanValue = this@toProto.isChecked }
}
this@toProto.fragment.toActionTarget(preferenceExtras)?.let {
@@ -243,14 +249,14 @@ private constructor(private val context: Context, private val request: GetPrefer
screenMetadata: PreferenceScreenMetadata,
isRoot: Boolean,
): PreferenceGroupProto = preferenceGroupProto {
- preference = toProto(screenMetadata, this@toProto, isRoot)
+ preference = toProto(screenMetadata, this@toProto.metadata, isRoot)
forEachAsync {
addPreferences(
preferenceOrGroupProto {
if (it is PreferenceHierarchy) {
group = it.toProto(screenMetadata, false)
} else {
- preference = toProto(screenMetadata, it, false)
+ preference = toProto(screenMetadata, it.metadata, false)
}
}
)
@@ -259,93 +265,19 @@ private constructor(private val context: Context, private val request: GetPrefer
private suspend fun toProto(
screenMetadata: PreferenceScreenMetadata,
- node: PreferenceHierarchyNode,
+ metadata: PreferenceMetadata,
isRoot: Boolean,
- ) = preferenceProto {
- val metadata = node.metadata
- key = metadata.key
- metadata.getTitleTextProto(isRoot)?.let { title = it }
- if (metadata.summary != 0) {
- summary = textProto { resourceId = metadata.summary }
- } else {
- (metadata as? PreferenceSummaryProvider)?.getSummary(context)?.let {
- summary = textProto { string = it.toString() }
- }
- }
- val metadataIcon = metadata.getPreferenceIcon(context)
- if (metadataIcon != 0) icon = metadataIcon
- if (metadata.keywords != 0) keywords = metadata.keywords
- val preferenceExtras = metadata.extras(context)
- preferenceExtras?.let { extras = it.toProto() }
- indexable = metadata.isIndexable(context)
- enabled = metadata.isEnabled(context)
- if (metadata is PreferenceAvailabilityProvider) {
- available = metadata.isAvailable(context)
- }
- if (metadata is PreferenceRestrictionProvider) {
- restricted = metadata.isRestricted(context)
- }
- persistent = metadata.isPersistent(context)
- if (persistent) {
- if (includeValue && metadata is PersistentPreference<*>) {
- value = preferenceValueProto {
- when (metadata) {
- is BooleanValue ->
- metadata
- .storage(context)
- .getValue(metadata.key, Boolean::class.javaObjectType)
- ?.let { booleanValue = it }
- is RangeValue -> {
- metadata
- .storage(context)
- .getValue(metadata.key, Int::class.javaObjectType)
- ?.let { intValue = it }
- }
- else -> {}
- }
- }
+ ) =
+ metadata.toProto(context, myUid, callingUid, screenMetadata, isRoot, request.flags).also {
+ if (metadata is PreferenceScreenMetadata) {
+ @Suppress("CheckReturnValue") addPreferenceScreenMetadata(metadata)
}
- if (includeValueDescriptor) {
- valueDescriptor = preferenceValueDescriptorProto {
- when (metadata) {
- is BooleanValue -> booleanType = true
- is RangeValue -> rangeValue = rangeValueProto {
- min = metadata.getMinValue(context)
- max = metadata.getMaxValue(context)
- step = metadata.getIncrementStep(context)
- }
- else -> {}
- }
+ metadata.intent(context)?.resolveActivity(context.packageManager)?.let {
+ if (it.packageName == context.packageName) {
+ add(it.className)
}
}
}
- if (metadata is PreferenceScreenMetadata) {
- @Suppress("CheckReturnValue") addPreferenceScreenMetadata(metadata)
- }
- metadata.intent(context)?.let { actionTarget = it.toActionTarget() }
- screenMetadata.getLaunchIntent(context, metadata)?.let { launchIntent = it.toProto() }
- }
-
- private fun PreferenceMetadata.getTitleTextProto(isRoot: Boolean): TextProto? {
- if (isRoot && this is PreferenceScreenMetadata) {
- val titleRes = screenTitle
- if (titleRes != 0) {
- return textProto { resourceId = titleRes }
- } else {
- getScreenTitle(context)?.let {
- return textProto { string = it.toString() }
- }
- }
- } else {
- val titleRes = title
- if (titleRes != 0) {
- return textProto { resourceId = titleRes }
- }
- }
- return (this as? PreferenceTitleProvider)?.getTitle(context)?.let {
- textProto { string = it.toString() }
- }
- }
private suspend fun String?.toActionTarget(extras: Bundle?): ActionTarget? {
if (this.isNullOrEmpty()) return null
@@ -399,22 +331,129 @@ private constructor(private val context: Context, private val request: GetPrefer
return null
}
- private suspend fun Intent.toActionTarget(): ActionTarget {
- if (component?.packageName == "") {
- setClassName(context, component!!.className)
+ private suspend fun Intent.toActionTarget() =
+ toActionTarget(context).also {
+ resolveActivity(context.packageManager)?.let {
+ if (it.packageName == context.packageName) {
+ add(it.className)
+ }
+ }
}
- resolveActivity(context.packageManager)?.let {
- if (it.packageName == context.packageName) {
- add(it.className)
+
+ companion object {
+ suspend fun of(
+ context: Context,
+ myUid: Int,
+ callingUid: Int,
+ request: GetPreferenceGraphRequest,
+ ) = PreferenceGraphBuilder(context, myUid, callingUid, request).also { it.init() }
+ }
+}
+
+fun PreferenceMetadata.toProto(
+ context: Context,
+ myUid: Int,
+ callingUid: Int,
+ screenMetadata: PreferenceScreenMetadata,
+ isRoot: Boolean,
+ flags: Int,
+) = preferenceProto {
+ val metadata = this@toProto
+ key = metadata.key
+ if (flags.includeMetadata()) {
+ metadata.getTitleTextProto(context, isRoot)?.let { title = it }
+ if (metadata.summary != 0) {
+ summary = textProto { resourceId = metadata.summary }
+ } else {
+ (metadata as? PreferenceSummaryProvider)?.getSummary(context)?.let {
+ summary = textProto { string = it.toString() }
}
}
- return actionTargetProto { intent = toProto() }
+ val metadataIcon = metadata.getPreferenceIcon(context)
+ if (metadataIcon != 0) icon = metadataIcon
+ if (metadata.keywords != 0) keywords = metadata.keywords
+ val preferenceExtras = metadata.extras(context)
+ preferenceExtras?.let { extras = it.toProto() }
+ indexable = metadata.isIndexable(context)
+ enabled = metadata.isEnabled(context)
+ if (metadata is PreferenceAvailabilityProvider) {
+ available = metadata.isAvailable(context)
+ }
+ if (metadata is PreferenceRestrictionProvider) {
+ restricted = metadata.isRestricted(context)
+ }
+ metadata.intent(context)?.let { actionTarget = it.toActionTarget(context) }
+ screenMetadata.getLaunchIntent(context, metadata)?.let { launchIntent = it.toProto() }
}
+ persistent = metadata.isPersistent(context)
+ if (persistent) {
+ if (
+ flags.includeValue() &&
+ enabled &&
+ (!hasAvailable() || available) &&
+ (!hasRestricted() || !restricted) &&
+ metadata is PersistentPreference<*> &&
+ metadata.getReadPermit(context, myUid, callingUid) == ReadWritePermit.ALLOW
+ ) {
+ value = preferenceValueProto {
+ when (metadata) {
+ is BooleanValue ->
+ metadata
+ .storage(context)
+ .getValue(metadata.key, Boolean::class.javaObjectType)
+ ?.let { booleanValue = it }
+ is RangeValue -> {
+ metadata
+ .storage(context)
+ .getValue(metadata.key, Int::class.javaObjectType)
+ ?.let { intValue = it }
+ }
+ else -> {}
+ }
+ }
+ }
+ if (flags.includeValueDescriptor()) {
+ valueDescriptor = preferenceValueDescriptorProto {
+ when (metadata) {
+ is BooleanValue -> booleanType = true
+ is RangeValue -> rangeValue = rangeValueProto {
+ min = metadata.getMinValue(context)
+ max = metadata.getMaxValue(context)
+ step = metadata.getIncrementStep(context)
+ }
+ else -> {}
+ }
+ }
+ }
+ }
+}
- companion object {
- suspend fun of(context: Context, request: GetPreferenceGraphRequest) =
- PreferenceGraphBuilder(context, request).also { it.init() }
+private fun PreferenceMetadata.getTitleTextProto(context: Context, isRoot: Boolean): TextProto? {
+ if (isRoot && this is PreferenceScreenMetadata) {
+ val titleRes = screenTitle
+ if (titleRes != 0) {
+ return textProto { resourceId = titleRes }
+ } else {
+ getScreenTitle(context)?.let {
+ return textProto { string = it.toString() }
+ }
+ }
+ } else {
+ val titleRes = title
+ if (titleRes != 0) {
+ return textProto { resourceId = titleRes }
+ }
+ }
+ return (this as? PreferenceTitleProvider)?.getTitle(context)?.let {
+ textProto { string = it.toString() }
+ }
+}
+
+private fun Intent.toActionTarget(context: Context): ActionTarget {
+ if (component?.packageName == "") {
+ setClassName(context, component!!.className)
}
+ return actionTargetProto { intent = toProto() }
}
@SuppressLint("AppBundleLocaleChanges")