Loading packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt +7 −3 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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 { Loading @@ -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> { Loading packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGetterFlags.kt 0 → 100644 +31 −0 Original line number Diff line number Diff line /* * 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 } packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt +138 −99 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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) { Loading Loading @@ -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 { Loading @@ -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) } } ) Loading @@ -259,12 +265,103 @@ private constructor(private val context: Context, private val request: GetPrefer private suspend fun toProto( screenMetadata: PreferenceScreenMetadata, node: PreferenceHierarchyNode, metadata: PreferenceMetadata, isRoot: Boolean, ) = metadata.toProto(context, myUid, callingUid, screenMetadata, isRoot, request.flags).also { if (metadata is PreferenceScreenMetadata) { @Suppress("CheckReturnValue") addPreferenceScreenMetadata(metadata) } metadata.intent(context)?.resolveActivity(context.packageManager)?.let { if (it.packageName == context.packageName) { add(it.className) } } } private suspend fun String?.toActionTarget(extras: Bundle?): ActionTarget? { if (this.isNullOrEmpty()) return null try { val fragmentClass = context.classLoader.loadClass(this) if (Fragment::class.java.isAssignableFrom(fragmentClass)) { @Suppress("UNCHECKED_CAST") return (fragmentClass as Class<out Fragment>).toActionTarget(extras) } } catch (e: Exception) { Log.e(TAG, "Cannot loadClass $this", e) } return null } private suspend fun Class<out Fragment>.toActionTarget(extras: Bundle?): ActionTarget? { if ( !PreferenceScreenProvider::class.java.isAssignableFrom(this) && !PreferenceScreenBindingKeyProvider::class.java.isAssignableFrom(this) ) { return null } val fragment = withContext(Dispatchers.Main) { return@withContext try { newInstance().apply { arguments = extras } } catch (e: Exception) { Log.e(TAG, "Fail to instantiate fragment ${this@toActionTarget}", e) null } } if (fragment is PreferenceScreenBindingKeyProvider) { val screenKey = fragment.getPreferenceScreenBindingKey(context) if (screenKey != null && addPreferenceScreenFromRegistry(screenKey)) { return actionTargetProto { key = screenKey } } } if (fragment is PreferenceScreenProvider) { try { val screen = fragment.createPreferenceScreen(preferenceScreenFactory) val screenKey = screen?.key if (!screenKey.isNullOrEmpty()) { @Suppress("CheckReturnValue") addPreferenceScreen(screenKey) { screen.toProto(null) } return actionTargetProto { key = screenKey } } } catch (e: Exception) { Log.e(TAG, "Fail to createPreferenceScreen for $fragment", e) } } return null } private suspend fun Intent.toActionTarget() = toActionTarget(context).also { 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 = node.metadata val metadata = this@toProto key = metadata.key metadata.getTitleTextProto(isRoot)?.let { title = it } if (flags.includeMetadata()) { metadata.getTitleTextProto(context, isRoot)?.let { title = it } if (metadata.summary != 0) { summary = textProto { resourceId = metadata.summary } } else { Loading @@ -285,9 +382,19 @@ private constructor(private val context: Context, private val request: GetPrefer 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 (includeValue && metadata is PersistentPreference<*>) { if ( flags.includeValue() && enabled && (!hasAvailable() || available) && (!hasRestricted() || !restricted) && metadata is PersistentPreference<*> && metadata.getReadPermit(context, myUid, callingUid) == ReadWritePermit.ALLOW ) { value = preferenceValueProto { when (metadata) { is BooleanValue -> Loading @@ -305,7 +412,7 @@ private constructor(private val context: Context, private val request: GetPrefer } } } if (includeValueDescriptor) { if (flags.includeValueDescriptor()) { valueDescriptor = preferenceValueDescriptorProto { when (metadata) { is BooleanValue -> booleanType = true Loading @@ -319,14 +426,9 @@ private constructor(private val context: Context, private val request: GetPrefer } } } 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? { private fun PreferenceMetadata.getTitleTextProto(context: Context, isRoot: Boolean): TextProto? { if (isRoot && this is PreferenceScreenMetadata) { val titleRes = screenTitle if (titleRes != 0) { Loading @@ -347,76 +449,13 @@ private constructor(private val context: Context, private val request: GetPrefer } } private suspend fun String?.toActionTarget(extras: Bundle?): ActionTarget? { if (this.isNullOrEmpty()) return null try { val fragmentClass = context.classLoader.loadClass(this) if (Fragment::class.java.isAssignableFrom(fragmentClass)) { @Suppress("UNCHECKED_CAST") return (fragmentClass as Class<out Fragment>).toActionTarget(extras) } } catch (e: Exception) { Log.e(TAG, "Cannot loadClass $this", e) } return null } private suspend fun Class<out Fragment>.toActionTarget(extras: Bundle?): ActionTarget? { if ( !PreferenceScreenProvider::class.java.isAssignableFrom(this) && !PreferenceScreenBindingKeyProvider::class.java.isAssignableFrom(this) ) { return null } val fragment = withContext(Dispatchers.Main) { return@withContext try { newInstance().apply { arguments = extras } } catch (e: Exception) { Log.e(TAG, "Fail to instantiate fragment ${this@toActionTarget}", e) null } } if (fragment is PreferenceScreenBindingKeyProvider) { val screenKey = fragment.getPreferenceScreenBindingKey(context) if (screenKey != null && addPreferenceScreenFromRegistry(screenKey)) { return actionTargetProto { key = screenKey } } } if (fragment is PreferenceScreenProvider) { try { val screen = fragment.createPreferenceScreen(preferenceScreenFactory) val screenKey = screen?.key if (!screenKey.isNullOrEmpty()) { @Suppress("CheckReturnValue") addPreferenceScreen(screenKey) { screen.toProto(null) } return actionTargetProto { key = screenKey } } } catch (e: Exception) { Log.e(TAG, "Fail to createPreferenceScreen for $fragment", e) } } return null } private suspend fun Intent.toActionTarget(): ActionTarget { private fun Intent.toActionTarget(context: Context): ActionTarget { if (component?.packageName == "") { setClassName(context, component!!.className) } resolveActivity(context.packageManager)?.let { if (it.packageName == context.packageName) { add(it.className) } } return actionTargetProto { intent = toProto() } } companion object { suspend fun of(context: Context, request: GetPreferenceGraphRequest) = PreferenceGraphBuilder(context, request).also { it.init() } } } @SuppressLint("AppBundleLocaleChanges") internal fun Context.ofLocale(locale: Locale?): Context { if (locale == null) return this Loading Loading
packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt +7 −3 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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 { Loading @@ -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> { Loading
packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGetterFlags.kt 0 → 100644 +31 −0 Original line number Diff line number Diff line /* * 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 }
packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt +138 −99 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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) { Loading Loading @@ -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 { Loading @@ -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) } } ) Loading @@ -259,12 +265,103 @@ private constructor(private val context: Context, private val request: GetPrefer private suspend fun toProto( screenMetadata: PreferenceScreenMetadata, node: PreferenceHierarchyNode, metadata: PreferenceMetadata, isRoot: Boolean, ) = metadata.toProto(context, myUid, callingUid, screenMetadata, isRoot, request.flags).also { if (metadata is PreferenceScreenMetadata) { @Suppress("CheckReturnValue") addPreferenceScreenMetadata(metadata) } metadata.intent(context)?.resolveActivity(context.packageManager)?.let { if (it.packageName == context.packageName) { add(it.className) } } } private suspend fun String?.toActionTarget(extras: Bundle?): ActionTarget? { if (this.isNullOrEmpty()) return null try { val fragmentClass = context.classLoader.loadClass(this) if (Fragment::class.java.isAssignableFrom(fragmentClass)) { @Suppress("UNCHECKED_CAST") return (fragmentClass as Class<out Fragment>).toActionTarget(extras) } } catch (e: Exception) { Log.e(TAG, "Cannot loadClass $this", e) } return null } private suspend fun Class<out Fragment>.toActionTarget(extras: Bundle?): ActionTarget? { if ( !PreferenceScreenProvider::class.java.isAssignableFrom(this) && !PreferenceScreenBindingKeyProvider::class.java.isAssignableFrom(this) ) { return null } val fragment = withContext(Dispatchers.Main) { return@withContext try { newInstance().apply { arguments = extras } } catch (e: Exception) { Log.e(TAG, "Fail to instantiate fragment ${this@toActionTarget}", e) null } } if (fragment is PreferenceScreenBindingKeyProvider) { val screenKey = fragment.getPreferenceScreenBindingKey(context) if (screenKey != null && addPreferenceScreenFromRegistry(screenKey)) { return actionTargetProto { key = screenKey } } } if (fragment is PreferenceScreenProvider) { try { val screen = fragment.createPreferenceScreen(preferenceScreenFactory) val screenKey = screen?.key if (!screenKey.isNullOrEmpty()) { @Suppress("CheckReturnValue") addPreferenceScreen(screenKey) { screen.toProto(null) } return actionTargetProto { key = screenKey } } } catch (e: Exception) { Log.e(TAG, "Fail to createPreferenceScreen for $fragment", e) } } return null } private suspend fun Intent.toActionTarget() = toActionTarget(context).also { 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 = node.metadata val metadata = this@toProto key = metadata.key metadata.getTitleTextProto(isRoot)?.let { title = it } if (flags.includeMetadata()) { metadata.getTitleTextProto(context, isRoot)?.let { title = it } if (metadata.summary != 0) { summary = textProto { resourceId = metadata.summary } } else { Loading @@ -285,9 +382,19 @@ private constructor(private val context: Context, private val request: GetPrefer 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 (includeValue && metadata is PersistentPreference<*>) { if ( flags.includeValue() && enabled && (!hasAvailable() || available) && (!hasRestricted() || !restricted) && metadata is PersistentPreference<*> && metadata.getReadPermit(context, myUid, callingUid) == ReadWritePermit.ALLOW ) { value = preferenceValueProto { when (metadata) { is BooleanValue -> Loading @@ -305,7 +412,7 @@ private constructor(private val context: Context, private val request: GetPrefer } } } if (includeValueDescriptor) { if (flags.includeValueDescriptor()) { valueDescriptor = preferenceValueDescriptorProto { when (metadata) { is BooleanValue -> booleanType = true Loading @@ -319,14 +426,9 @@ private constructor(private val context: Context, private val request: GetPrefer } } } 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? { private fun PreferenceMetadata.getTitleTextProto(context: Context, isRoot: Boolean): TextProto? { if (isRoot && this is PreferenceScreenMetadata) { val titleRes = screenTitle if (titleRes != 0) { Loading @@ -347,76 +449,13 @@ private constructor(private val context: Context, private val request: GetPrefer } } private suspend fun String?.toActionTarget(extras: Bundle?): ActionTarget? { if (this.isNullOrEmpty()) return null try { val fragmentClass = context.classLoader.loadClass(this) if (Fragment::class.java.isAssignableFrom(fragmentClass)) { @Suppress("UNCHECKED_CAST") return (fragmentClass as Class<out Fragment>).toActionTarget(extras) } } catch (e: Exception) { Log.e(TAG, "Cannot loadClass $this", e) } return null } private suspend fun Class<out Fragment>.toActionTarget(extras: Bundle?): ActionTarget? { if ( !PreferenceScreenProvider::class.java.isAssignableFrom(this) && !PreferenceScreenBindingKeyProvider::class.java.isAssignableFrom(this) ) { return null } val fragment = withContext(Dispatchers.Main) { return@withContext try { newInstance().apply { arguments = extras } } catch (e: Exception) { Log.e(TAG, "Fail to instantiate fragment ${this@toActionTarget}", e) null } } if (fragment is PreferenceScreenBindingKeyProvider) { val screenKey = fragment.getPreferenceScreenBindingKey(context) if (screenKey != null && addPreferenceScreenFromRegistry(screenKey)) { return actionTargetProto { key = screenKey } } } if (fragment is PreferenceScreenProvider) { try { val screen = fragment.createPreferenceScreen(preferenceScreenFactory) val screenKey = screen?.key if (!screenKey.isNullOrEmpty()) { @Suppress("CheckReturnValue") addPreferenceScreen(screenKey) { screen.toProto(null) } return actionTargetProto { key = screenKey } } } catch (e: Exception) { Log.e(TAG, "Fail to createPreferenceScreen for $fragment", e) } } return null } private suspend fun Intent.toActionTarget(): ActionTarget { private fun Intent.toActionTarget(context: Context): ActionTarget { if (component?.packageName == "") { setClassName(context, component!!.className) } resolveActivity(context.packageManager)?.let { if (it.packageName == context.packageName) { add(it.className) } } return actionTargetProto { intent = toProto() } } companion object { suspend fun of(context: Context, request: GetPreferenceGraphRequest) = PreferenceGraphBuilder(context, request).also { it.init() } } } @SuppressLint("AppBundleLocaleChanges") internal fun Context.ofLocale(locale: Locale?): Context { if (locale == null) return this Loading