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