1 /* 2 * Copyright (C) 2022 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.spaprivileged.template.app 18 19 import android.content.Context 20 import android.content.pm.ApplicationInfo 21 import androidx.compose.runtime.Composable 22 import androidx.compose.runtime.State 23 import androidx.compose.ui.text.AnnotatedString 24 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder 25 import com.android.settingslib.spa.framework.common.SettingsPageProvider 26 import com.android.settingslib.spa.framework.compose.rememberContext 27 import com.android.settingslib.spa.framework.util.asyncMapItem 28 import com.android.settingslib.spaprivileged.model.app.AppRecord 29 import kotlinx.coroutines.flow.Flow 30 31 /** 32 * Implement this interface to build an App List which toggles a permission on / off. 33 */ 34 interface TogglePermissionAppListModel<T : AppRecord> { 35 val pageTitleResId: Int 36 val switchTitleResId: Int 37 val footerResId: Int 38 val switchRestrictionKeys: List<String> 39 get() = emptyList() 40 @Composable 41 fun footerContent(): (@Composable () -> Unit)? { 42 return null 43 } 44 /** 45 * Loads the extra info for the App List, and generates the [AppRecord] List. 46 * 47 * Default is implemented by [transformItem] 48 */ 49 fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>): Flow<List<T>> = 50 appListFlow.asyncMapItem(::transformItem) 51 52 /** 53 * Loads the extra info for one app, and generates the [AppRecord]. 54 * 55 * This must be implemented, because when show the App Info page for single app, this will be 56 * used instead of [transform]. 57 */ 58 fun transformItem(app: ApplicationInfo): T 59 60 /** 61 * Filters the [AppRecord] list. 62 * 63 * @return the [AppRecord] list which will be displayed. 64 */ 65 fun filter(userIdFlow: Flow<Int>, recordListFlow: Flow<List<T>>): Flow<List<T>> 66 67 /** 68 * Gets whether the permission is allowed for the given app. 69 */ 70 @Composable 71 fun isAllowed(record: T): State<Boolean?> 72 73 /** 74 * Gets whether the permission on / off is changeable for the given app. 75 */ 76 fun isChangeable(record: T): Boolean 77 78 /** 79 * Sets whether the permission is allowed for the given app. 80 */ 81 fun setAllowed(record: T, newAllowed: Boolean) 82 } 83 84 interface TogglePermissionAppListProvider { 85 val permissionType: String 86 87 fun createModel(context: Context): TogglePermissionAppListModel<out AppRecord> 88 89 fun buildAppListInjectEntry(): SettingsEntryBuilder = 90 TogglePermissionAppListPageProvider.buildInjectEntry(permissionType) { createModel(it) } 91 92 /** 93 * Gets the route to the toggle permission App List page. 94 * 95 * Expose route to enable enter from non-SPA pages. 96 */ 97 fun getAppListRoute(): String = 98 TogglePermissionAppListPageProvider.getRoute(permissionType) 99 100 /** 101 * Gets the route prefix to the toggle permission App Info page. 102 * 103 * Expose route prefix to enable enter from non-SPA pages. 104 */ 105 fun getAppInfoRoutePrefix(): String = 106 TogglePermissionAppInfoPageProvider.getRoutePrefix(permissionType) 107 108 @Composable 109 fun InfoPageEntryItem(app: ApplicationInfo) { 110 val listModel = rememberContext(::createModel) 111 listModel.TogglePermissionAppInfoPageEntryItem(permissionType, app) 112 } 113 } 114 115 class TogglePermissionAppListTemplate( 116 allProviders: List<TogglePermissionAppListProvider>, 117 ) { 118 private val listModelProviderMap = allProviders.associateBy { it.permissionType } 119 120 fun createPageProviders(): List<SettingsPageProvider> = listOf( 121 TogglePermissionAppListPageProvider(this), 122 TogglePermissionAppInfoPageProvider(this), 123 ) 124 125 @Composable 126 internal fun rememberModel(permissionType: String) = rememberContext { context -> 127 listModelProviderMap.getValue(permissionType).createModel(context) 128 } 129 } 130