1 /* <lambda>null2 * 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.settings.spa.app.specialaccess 18 19 import android.Manifest 20 import android.app.AppGlobals 21 import android.app.AppOpsManager 22 import android.app.AppOpsManager.MODE_DEFAULT 23 import android.content.Context 24 import android.content.pm.ApplicationInfo 25 import android.os.UserManager 26 import androidx.compose.runtime.Composable 27 import com.android.settings.R 28 import com.android.settingslib.spa.lifecycle.collectAsCallbackWithLifecycle 29 import com.android.settingslib.spaprivileged.model.app.AppOps 30 import com.android.settingslib.spaprivileged.model.app.AppOpsController 31 import com.android.settingslib.spaprivileged.model.app.AppRecord 32 import com.android.settingslib.spaprivileged.model.app.userId 33 import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListModel 34 import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider 35 import kotlinx.coroutines.flow.Flow 36 import kotlinx.coroutines.flow.combine 37 import kotlinx.coroutines.flow.map 38 39 object InstallUnknownAppsListProvider : TogglePermissionAppListProvider { 40 override val permissionType = "InstallUnknownApps" 41 override fun createModel(context: Context) = InstallUnknownAppsListModel(context) 42 } 43 44 data class InstallUnknownAppsRecord( 45 override val app: ApplicationInfo, 46 val appOpsController: AppOpsController, 47 ) : AppRecord 48 49 class InstallUnknownAppsListModel(private val context: Context) : 50 TogglePermissionAppListModel<InstallUnknownAppsRecord> { 51 override val pageTitleResId = com.android.settingslib.R.string.install_other_apps 52 override val switchTitleResId = R.string.external_source_switch_title 53 override val footerResId = R.string.install_all_warning 54 override val switchRestrictionKeys = 55 listOf( 56 UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, 57 UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, 58 ) 59 override val enhancedConfirmationKey: String = AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES 60 transformItemnull61 override fun transformItem(app: ApplicationInfo) = 62 InstallUnknownAppsRecord( 63 app = app, 64 appOpsController = AppOpsController(context = context, app = app, appOps = APP_OPS), 65 ) 66 67 override fun filter( 68 userIdFlow: Flow<Int>, 69 recordListFlow: Flow<List<InstallUnknownAppsRecord>>, 70 ) = 71 userIdFlow.map(::getPotentialPackageNames).combine(recordListFlow) { 72 potentialPackageNames, 73 recordList -> 74 recordList.filter { record -> isChangeable(record, potentialPackageNames) } 75 } 76 77 @Composable isAllowednull78 override fun isAllowed(record: InstallUnknownAppsRecord) = 79 record.appOpsController.isAllowed.collectAsCallbackWithLifecycle() 80 81 override fun isChangeable(record: InstallUnknownAppsRecord) = 82 isChangeable(record, getPotentialPackageNames(record.app.userId)) 83 84 override fun setAllowed(record: InstallUnknownAppsRecord, newAllowed: Boolean) { 85 record.appOpsController.setAllowed(newAllowed) 86 } 87 88 companion object { 89 private val APP_OPS = AppOps(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES) 90 isChangeablenull91 private fun isChangeable( 92 record: InstallUnknownAppsRecord, 93 potentialPackageNames: Set<String>, 94 ) = record.appOpsController.getMode() != MODE_DEFAULT || 95 record.app.packageName in potentialPackageNames 96 97 private fun getPotentialPackageNames(userId: Int): Set<String> = 98 AppGlobals.getPackageManager() 99 .getAppOpPermissionPackages(Manifest.permission.REQUEST_INSTALL_PACKAGES, userId) 100 .toSet() 101 } 102 } 103