• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.PermissionMapping
25 import com.android.permissioncontroller.permission.utils.KotlinUtils
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) {
44             update()
45         }
46     }
47 
48     private val permStateLiveDatas =
49         mutableMapOf<Triple<String, String, UserHandle>, PermStateLiveData>()
50     private val packageAutoRevokedPermsList =
51         mutableMapOf<Pair<String, UserHandle>, MutableSet<String>>()
52 
53     override suspend fun loadDataAndPostValue(job: Job) {
54         if (!AllPackageInfosLiveData.isInitialized) {
55             return
56         }
57 
58         val allPackageGroups = mutableSetOf<Triple<String, String, UserHandle>>()
59         for ((user, packageList) in AllPackageInfosLiveData.value ?: emptyMap()) {
60             for (pkg in packageList) {
61                 if (job.isCancelled) {
62                     return
63                 }
64 
65                 val pkgGroups = mutableSetOf<Triple<String, String, UserHandle>>()
66                 for ((idx, requestedPerm) in pkg.requestedPermissions.withIndex()) {
67                     val group =
68                         PermissionMapping.getGroupOfPlatformPermission(requestedPerm) ?: continue
69                     val granted = (pkg.requestedPermissionsFlags[idx] and
70                             PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0
71                     if (pkg.targetSdkVersion < Build.VERSION_CODES.M || !granted) {
72                         pkgGroups.add(Triple(pkg.packageName, group, user))
73                     }
74                 }
75                 allPackageGroups.addAll(pkgGroups)
76             }
77         }
78 
79         if (allPackageGroups.isEmpty()) {
80             postCopyOfMap()
81         } else {
82             observePermStateLiveDatas(allPackageGroups)
83         }
84     }
85 
86     private fun observePermStateLiveDatas(packageGroups: Set<Triple<String, String, UserHandle>>) {
87         GlobalScope.launch(Main.immediate) {
88 
89             val (toAdd, toRemove) =
90                 KotlinUtils.getMapAndListDifferences(packageGroups, permStateLiveDatas)
91 
92             for (packagePermGroup in toRemove) {
93                 removeSource(permStateLiveDatas.remove(packagePermGroup) ?: continue)
94                 val packageUser = packagePermGroup.first to packagePermGroup.third
95                 packageAutoRevokedPermsList[packageUser]?.remove(packagePermGroup.second)
96                 if (packageAutoRevokedPermsList[packageUser]?.isEmpty() == true) {
97                     packageAutoRevokedPermsList.remove(packageUser)
98                 }
99             }
100 
101             if (toRemove.isNotEmpty()) {
102                 postCopyOfMap()
103             }
104 
105             for (packagePermGroup in toAdd) {
106                 permStateLiveDatas[packagePermGroup] = PermStateLiveData[packagePermGroup]
107             }
108 
109             for (packagePermGroup in toAdd) {
110                 val permStateLiveData = permStateLiveDatas[packagePermGroup]!!
111                 val packageUser = packagePermGroup.first to packagePermGroup.third
112 
113                 addSource(permStateLiveData) { permState ->
114                     var added = false
115                     if (permState == null && permStateLiveData.isInitialized) {
116                         permStateLiveDatas.remove(packagePermGroup)
117                         removeSource(permStateLiveData)
118                     } else if (permState != null) {
119                         for ((_, state) in permState) {
120                             if (state.permFlags and FLAG_PERMISSION_AUTO_REVOKED != 0) {
121                                 packageAutoRevokedPermsList.getOrPut(packageUser) { mutableSetOf() }
122                                     .add(packagePermGroup.second)
123                                 added = true
124                                 break
125                             }
126                         }
127                     }
128 
129                     if (!added) {
130                         packageAutoRevokedPermsList[packageUser]?.remove(packagePermGroup.second)
131                         if (packageAutoRevokedPermsList[packageUser]?.isEmpty() == true) {
132                             packageAutoRevokedPermsList.remove(packageUser)
133                         }
134                     }
135 
136                     if (permStateLiveDatas.all { it.value.isInitialized }) {
137                         postCopyOfMap()
138                     }
139                 }
140             }
141         }
142     }
143 
144     private fun postCopyOfMap() {
145         val autoRevokedCopy =
146             mutableMapOf<Pair<String, UserHandle>, Set<String>>()
147         for ((userPackage, permGroups) in packageAutoRevokedPermsList) {
148             autoRevokedCopy[userPackage] = permGroups.toSet()
149         }
150         Log.i(LOG_TAG, "postValue: $autoRevokedCopy")
151         postValue(autoRevokedCopy)
152     }
153 }
154 
155 private val autoRevokedPackagesSetLiveData =
156     object : SmartUpdateMediatorLiveData<Set<Pair<String, UserHandle>>>() {
157         init {
<lambda>null158             addSource(AutoRevokedPackagesLiveData) {
159                 update()
160             }
161         }
162 
onUpdatenull163         override fun onUpdate() {
164             if (!AutoRevokedPackagesLiveData.isInitialized) {
165                 return
166             }
167             value = AutoRevokedPackagesLiveData.value!!.keys
168         }
169     }
170 
171 val unusedAutoRevokePackagesLiveData = UnusedPackagesLiveData(autoRevokedPackagesSetLiveData)