1 /* <lambda>null2 * Copyright (C) 2020 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.permissioncontroller.permission.data 18 19 import android.content.pm.PackageInfo 20 import android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED 21 import android.os.Build 22 import android.os.UserHandle 23 import android.util.Log 24 import com.android.permissioncontroller.permission.utils.KotlinUtils 25 import com.android.permissioncontroller.permission.utils.PermissionMapping 26 import kotlinx.coroutines.Dispatchers.Main 27 import kotlinx.coroutines.GlobalScope 28 import kotlinx.coroutines.Job 29 import kotlinx.coroutines.launch 30 31 /** 32 * Tracks which packages have been auto-revoked, and which groups have been auto revoked for those 33 * packages. 34 * 35 * ```(packageName, user) -> [groupName]``` 36 */ 37 object AutoRevokedPackagesLiveData : 38 SmartAsyncMediatorLiveData<Map<Pair<String, UserHandle>, Set<String>>>() { 39 40 private val LOG_TAG = AutoRevokedPackagesLiveData::class.java.simpleName 41 42 init { 43 addSource(AllPackageInfosLiveData) { update() } 44 } 45 46 private val permStateLiveDatas = 47 mutableMapOf<Triple<String, String, UserHandle>, PermStateLiveData>() 48 private val packageAutoRevokedPermsList = 49 mutableMapOf<Pair<String, UserHandle>, MutableSet<String>>() 50 51 override suspend fun loadDataAndPostValue(job: Job) { 52 if (!AllPackageInfosLiveData.isInitialized) { 53 return 54 } 55 56 val allPackageGroups = mutableSetOf<Triple<String, String, UserHandle>>() 57 for ((user, packageList) in AllPackageInfosLiveData.value ?: emptyMap()) { 58 for (pkg in packageList) { 59 if (job.isCancelled) { 60 return 61 } 62 63 val pkgGroups = mutableSetOf<Triple<String, String, UserHandle>>() 64 for ((idx, requestedPerm) in pkg.requestedPermissions.withIndex()) { 65 val group = 66 PermissionMapping.getGroupOfPlatformPermission(requestedPerm) ?: continue 67 val granted = 68 (pkg.requestedPermissionsFlags[idx] and 69 PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0 70 if (pkg.targetSdkVersion < Build.VERSION_CODES.M || !granted) { 71 pkgGroups.add(Triple(pkg.packageName, group, user)) 72 } 73 } 74 allPackageGroups.addAll(pkgGroups) 75 } 76 } 77 78 if (allPackageGroups.isEmpty()) { 79 postCopyOfMap() 80 } else { 81 observePermStateLiveDatas(allPackageGroups) 82 } 83 } 84 85 private fun observePermStateLiveDatas(packageGroups: Set<Triple<String, String, UserHandle>>) { 86 GlobalScope.launch(Main.immediate) { 87 val (toAdd, toRemove) = 88 KotlinUtils.getMapAndListDifferences(packageGroups, permStateLiveDatas) 89 90 for (packagePermGroup in toRemove) { 91 removeSource(permStateLiveDatas.remove(packagePermGroup) ?: continue) 92 val packageUser = packagePermGroup.first to packagePermGroup.third 93 packageAutoRevokedPermsList[packageUser]?.remove(packagePermGroup.second) 94 if (packageAutoRevokedPermsList[packageUser]?.isEmpty() == true) { 95 packageAutoRevokedPermsList.remove(packageUser) 96 } 97 } 98 99 if (toRemove.isNotEmpty()) { 100 postCopyOfMap() 101 } 102 103 for (packagePermGroup in toAdd) { 104 permStateLiveDatas[packagePermGroup] = PermStateLiveData[packagePermGroup] 105 } 106 107 for (packagePermGroup in toAdd) { 108 val permStateLiveData = permStateLiveDatas[packagePermGroup]!! 109 val packageUser = packagePermGroup.first to packagePermGroup.third 110 111 addSource(permStateLiveData) { permState -> 112 var added = false 113 if (permState == null && permStateLiveData.isInitialized) { 114 permStateLiveDatas.remove(packagePermGroup) 115 removeSource(permStateLiveData) 116 } else if (permState != null) { 117 for ((_, state) in permState) { 118 if (state.permFlags and FLAG_PERMISSION_AUTO_REVOKED != 0) { 119 packageAutoRevokedPermsList 120 .getOrPut(packageUser) { mutableSetOf() } 121 .add(packagePermGroup.second) 122 added = true 123 break 124 } 125 } 126 } 127 128 if (!added) { 129 packageAutoRevokedPermsList[packageUser]?.remove(packagePermGroup.second) 130 if (packageAutoRevokedPermsList[packageUser]?.isEmpty() == true) { 131 packageAutoRevokedPermsList.remove(packageUser) 132 } 133 } 134 135 if (permStateLiveDatas.all { it.value.isInitialized }) { 136 postCopyOfMap() 137 } 138 } 139 } 140 } 141 } 142 143 private fun postCopyOfMap() { 144 val autoRevokedCopy = mutableMapOf<Pair<String, UserHandle>, Set<String>>() 145 for ((userPackage, permGroups) in packageAutoRevokedPermsList) { 146 autoRevokedCopy[userPackage] = permGroups.toSet() 147 } 148 Log.i(LOG_TAG, "postValue: $autoRevokedCopy") 149 postValue(autoRevokedCopy) 150 } 151 } 152 153 private val autoRevokedPackagesSetLiveData = 154 object : SmartUpdateMediatorLiveData<Set<Pair<String, UserHandle>>>() { 155 init { <lambda>null156 addSource(AutoRevokedPackagesLiveData) { update() } 157 } 158 onUpdatenull159 override fun onUpdate() { 160 if (!AutoRevokedPackagesLiveData.isInitialized) { 161 return 162 } 163 value = AutoRevokedPackagesLiveData.value!!.keys 164 } 165 } 166 167 val unusedAutoRevokePackagesLiveData = UnusedPackagesLiveData(autoRevokedPackagesSetLiveData) 168