Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0bf708e authored by Chris Antol's avatar Chris Antol
Browse files

Support async hierarchy in DeviceState

Also populate all child preferences

Bug: 405344827
Test: none
Flag: com.android.settings.flags.device_state
Change-Id: I298a62723d5433930f0b0d1ac8c313df2b5c2827
parent 918cf7c9
Loading
Loading
Loading
Loading
+82 −29
Original line number Diff line number Diff line
@@ -35,8 +35,14 @@ import com.android.extensions.appfunctions.ExecuteAppFunctionRequest
import com.android.extensions.appfunctions.ExecuteAppFunctionResponse
import com.android.settings.utils.getLocale
import com.android.settingslib.metadata.PersistentPreference
import com.android.settingslib.metadata.PreferenceHierarchy
import com.android.settingslib.metadata.PreferenceScreenCoordinate
import com.android.settingslib.metadata.PreferenceHierarchyGenerator
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceScreenMetadata
import com.android.settingslib.metadata.PreferenceScreenRegistry
import com.android.settingslib.metadata.PreferenceSummaryProvider
import com.android.settingslib.metadata.PreferenceTitleProvider
import com.google.android.appfunctions.schema.common.v1.devicestate.DeviceStateItem
import com.google.android.appfunctions.schema.common.v1.devicestate.DeviceStateResponse
import com.google.android.appfunctions.schema.common.v1.devicestate.LocalizedString
@@ -119,7 +125,7 @@ class DeviceStateAppFunctionService : AppFunctionService() {
        )
    }

    private fun buildPerScreenDeviceStates(
    private suspend fun buildPerScreenDeviceStates(
        screenKey: String,
        requestCategory: DeviceStateCategory,
    ): PerScreenDeviceStates? {
@@ -136,55 +142,102 @@ class DeviceStateAppFunctionService : AppFunctionService() {
            return null
        }
        val deviceStateItemList: MutableList<DeviceStateItem> = ArrayList()
        // TODO(b/405344827): support PreferenceHierarchyGenerator
        val hierarchy = screenMetaData.getPreferenceHierarchy(applicationContext)
        hierarchy.forEach {
            val metadata = it.metadata as? PersistentPreference<*> ?: return@forEach
        val hierarchy = (screenMetaData as? PreferenceHierarchyGenerator<*>)
            ?.asyncHierarchy(perScreenConfig)
            ?: screenMetaData.getPreferenceHierarchy(applicationContext)
        hierarchy.forEachRecursively {
            val metadata = it.metadata
            val config = settingConfigMap[metadata.key]
            if (config == null || !config.enabled) {
                return@forEach
            // skip over explicitly disabled preferences
            if (!(config?.enabled ?: true)) {
                return@forEachRecursively
            }
            val valueType = metadata.valueType
            var jasonValue: String? = when (valueType) {
            val jsonValue = (metadata as? PersistentPreference<*>)?.let {
                when (metadata.valueType) {
                    Int::class.javaObjectType -> metadata.storage(applicationContext)
                    ?.getInt("")
                        .getInt("")
                        .toString()

                    Boolean::class.javaObjectType -> metadata.storage(applicationContext)
                    ?.getBoolean("").toString()
                        .getBoolean("").toString()

                    Long::class.javaObjectType -> metadata.storage(applicationContext)
                    ?.getLong("")
                        .getLong("")
                        .toString()

                    Float::class.javaObjectType -> metadata.storage(applicationContext)
                    ?.getLong("")
                        .getLong("")
                        .toString()

                String::class.javaObjectType -> metadata.storage(applicationContext)?.getString("")
                else -> null
            }
            if (jasonValue == null) {
                jasonValue = tryGetStringRes(metadata.summary)
                    String::class.javaObjectType -> metadata.storage(applicationContext)
                        .getString("")
                    else -> getSummary(applicationContext, metadata)
                }
            } ?: getSummary(applicationContext, metadata)
            deviceStateItemList.add(
                DeviceStateItem(
                    key = metadata.key,
                    // TODO check dynamic title
                    name = getLocalizedString(metadata.title),
                    jsonValue = jasonValue,
                    hintText = config.hintText
                    jsonValue = jsonValue,
                    hintText = config?.hintText ?: ""
                )
            )
        }

        val launchingIntent = screenMetaData.getLaunchIntent(applicationContext, null)
        return PerScreenDeviceStates(
            description = tryGetStringRes(screenMetaData.title),
            description = getScreenTitle(screenMetaData) ?: "",
            deviceStateItems = deviceStateItemList,
            intentUri = launchingIntent?.toUri(Intent.URI_INTENT_SCHEME)
        )
    }

    private suspend fun PreferenceHierarchyGenerator<*>.asyncHierarchy(
        config: PerScreenConfig
    ): PreferenceHierarchy {
        return when (config.defaultType) {
            Boolean::class.java -> (this as PreferenceHierarchyGenerator<Boolean>)
                .generatePreferenceHierarchy(
                    applicationContext,
                    config.defaultTypeValue as Boolean
                )
            Int::class.java -> (this as PreferenceHierarchyGenerator<Int>)
                .generatePreferenceHierarchy(
                    applicationContext,
                    config.defaultTypeValue as Int
                )
            else -> generatePreferenceHierarchy(applicationContext)
        }
    }

    private fun getScreenTitle(metadata: PreferenceScreenMetadata): String? {
        val screenTitleRes = metadata.screenTitle
        if (screenTitleRes != 0) {
            return tryGetStringRes(screenTitleRes)
        }
        metadata.getScreenTitle(applicationContext)?.let {
            return it.toString()
        }
        val dynamicTitle = (metadata as? PreferenceTitleProvider)?.getTitle(applicationContext)
        if (dynamicTitle != null) {
            return dynamicTitle.toString()
        }
        val titleRes = metadata.title
        if (titleRes != 0) {
            return tryGetStringRes(titleRes)
        }
        return null
    }

    private fun getSummary(context: Context, metadata: PreferenceMetadata): String? {
        return if (metadata.summary != 0) {
            tryGetStringRes(metadata.summary)
        } else {
            (metadata as? PreferenceSummaryProvider)?.getSummary(context).toString()
        }
    }

    private fun tryGetStringRes(resId: Int): String {
        return try {
            applicationContext.getString(resId)
+27 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoScreen
import com.android.settings.deviceinfo.firmwareversion.FirmwareVersionScreen
import com.android.settings.deviceinfo.legal.LegalSettingsScreen
import com.android.settings.deviceinfo.legal.ModuleLicensesScreen
import com.android.settings.deviceinfo.storage.StoragePreferenceScreen
import com.android.settings.display.AutoBrightnessScreen
import com.android.settings.display.DisplayScreen
import com.android.settings.display.ScreenTimeoutScreen
@@ -40,8 +41,11 @@ import com.android.settings.network.NetworkProviderScreen
import com.android.settings.network.tether.TetherScreen
import com.android.settings.notification.SoundScreen
import com.android.settings.security.LockScreenPreferenceScreen
import com.android.settings.spa.app.catalyst.AllAppsScreen
import com.android.settings.spa.app.catalyst.AppStorageAppListScreen
import com.android.settings.supervision.SupervisionDashboardScreen
import com.android.settings.supervision.SupervisionPinManagementScreen
import com.android.settingslib.metadata.PreferenceHierarchyGenerator

enum class DeviceStateCategory(val functionId: String) {
    UNCATEGORIZED("getUncategorizedDeviceState"),
@@ -67,7 +71,7 @@ enum class DeviceStateCategory(val functionId: String) {
 * @param hintText additional context about the device state
 */
data class DeviceStateItemConfig(
    val enabled: Boolean,
    val enabled: Boolean = true,
    val settingKey: String,
    val settingScreenKey: String,
    val hintText: String = "",
@@ -79,12 +83,16 @@ data class DeviceStateItemConfig(
 * @param enabled whether expose device states on this screen to App Functions.
 * @param screenKey the unique ID for the screen.
 * @param category the device state category of the screen. The default is UNCATEGORIZED.
 * @param defaultType class type associated with [PreferenceHierarchyGenerator] for PreferenceScreen
 * @param defaultTypeValue value to pass in to [PreferenceHierarchyGenerator.generatePreferenceHierarchy]
 */
data class PerScreenConfig(
    val enabled: Boolean,
    val screenKey: String,
    // TODO(b/405344827): map categories to PreferenceMetadata#tags
    val category: Set<DeviceStateCategory> = setOf(DeviceStateCategory.UNCATEGORIZED)
    val category: Set<DeviceStateCategory> = setOf(DeviceStateCategory.UNCATEGORIZED),
    val defaultType: Class<*>? = null,
    val defaultTypeValue: Any? = null
)

fun getScreenConfigs() = listOf(
@@ -210,6 +218,23 @@ fun getScreenConfigs() = listOf(
    PerScreenConfig(
        enabled = true,
        screenKey = VibrationScreen.KEY,
    ),
    PerScreenConfig(
        enabled = true,
        screenKey = AppStorageAppListScreen.KEY,
        category = setOf(DeviceStateCategory.STORAGE),
        defaultType = Boolean::class.java,
        defaultTypeValue = false, // do not include system apps
    ),
    PerScreenConfig(
        enabled = true,
        screenKey = AllAppsScreen.KEY,
        category = setOf(DeviceStateCategory.STORAGE)
    ),
    PerScreenConfig(
        enabled = true,
        screenKey = StoragePreferenceScreen.KEY,
        category = setOf(DeviceStateCategory.STORAGE)
    )
)

+1 −1
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ class AppStorageAppListScreen : PreferenceScreenCreator, PreferenceHierarchyGene

    override fun tags(context: Context) = arrayOf(TAG_DEVICE_STATE_SCREEN)

    override fun isFlagEnabled(context: Context) = Flags.catalystAppList()
    override fun isFlagEnabled(context: Context) = Flags.catalystAppList() || Flags.deviceState()

    override fun hasCompleteHierarchy() = false