• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2019 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.app.Application
20 import android.content.pm.PackageInfo
21 import android.content.pm.PackageManager
22 import android.os.UserHandle
23 import com.android.permissioncontroller.PermissionControllerApplication
24 import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
25 import com.android.permissioncontroller.permission.model.livedatatypes.PermState
26 import com.android.permissioncontroller.permission.utils.Utils
27 import kotlinx.coroutines.Job
28 
29 /**
30  * A LiveData which tracks the permission state for one permission group for one package. It
31  * includes both the granted state of every permission in the group, and the flags stored
32  * in the PermissionController service.
33  *
34  * @param app The current application
35  * @param packageName The name of the package this LiveData will watch for mode changes for
36  * @param permGroupName The name of the permission group whose app ops this LiveData
37  * will watch
38  * @param user The user of the package
39  */
40 class PermStateLiveData private constructor(
41     private val app: Application,
42     private val packageName: String,
43     private val permGroupName: String,
44     private val user: UserHandle
45 ) : SmartAsyncMediatorLiveData<Map<String, PermState>>(),
46     PermissionListenerMultiplexer.PermissionChangeCallback {
47 
48     private val context = Utils.getUserContext(app, user)
49     private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user]
50     private val groupLiveData = PermGroupLiveData[permGroupName]
51 
52     private var uid: Int? = null
53     private var registeredUid: Int? = null
54 
55     init {
56         addSource(packageInfoLiveData) {
57             checkForUidUpdate(it)
58             updateAsync()
59         }
60 
61         addSource(groupLiveData) {
62             updateAsync()
63         }
64     }
65 
66     /**
67      * Gets the system flags from the package manager, and the grant state from those flags, plus
68      * the RequestedPermissionFlags of the PermState.
69      */
70     override suspend fun loadDataAndPostValue(job: Job) {
71         if (!packageInfoLiveData.isInitialized || !groupLiveData.isInitialized) {
72             return
73         }
74 
75         val packageInfo = packageInfoLiveData.value
76         val permissionGroup = groupLiveData.value
77         if (packageInfo == null || permissionGroup == null) {
78             invalidateSingle(Triple(packageName, permGroupName, user))
79             postValue(null)
80             return
81         }
82         val permissionStates = mutableMapOf<String, PermState>()
83         for ((index, permissionName) in packageInfo.requestedPermissions.withIndex()) {
84 
85             permissionGroup.permissionInfos[permissionName]?.let { permInfo ->
86                 val packageFlags = packageInfo.requestedPermissionsFlags[index]
87                 val permFlags = context.packageManager.getPermissionFlags(permInfo.name,
88                     packageName, user)
89                 val granted = packageFlags and PackageInfo.REQUESTED_PERMISSION_GRANTED != 0 &&
90                     permFlags and PackageManager.FLAG_PERMISSION_REVOKED_COMPAT == 0
91 
92                 if (job.isCancelled) {
93                     return
94                 }
95                 permissionStates[permissionName] = PermState(permFlags, granted)
96             }
97         }
98 
99         postValue(permissionStates)
100     }
101 
102     override fun onPermissionChange() {
103         updateAsync()
104     }
105 
106     private fun checkForUidUpdate(packageInfo: LightPackageInfo?) {
107         if (packageInfo == null) {
108             registeredUid?.let {
109                 PermissionListenerMultiplexer.removeCallback(it, this)
110             }
111             return
112         }
113         uid = packageInfo.uid
114         if (uid != registeredUid && hasActiveObservers()) {
115             PermissionListenerMultiplexer.addOrReplaceCallback(
116                 registeredUid, packageInfo.uid, this)
117             registeredUid = uid
118         }
119     }
120 
121     override fun onInactive() {
122         super.onInactive()
123         registeredUid?.let {
124             PermissionListenerMultiplexer.removeCallback(it, this)
125             registeredUid = null
126         }
127     }
128 
129     override fun onActive() {
130         super.onActive()
131         uid?.let {
132             PermissionListenerMultiplexer.addCallback(it, this)
133             registeredUid = uid
134         }
135     }
136 
137     /**
138      * Repository for PermStateLiveDatas.
139      * <p> Key value is a triple of string package name, string permission group name, and UserHandle,
140      * value is its corresponding LiveData.
141      */
142     companion object : DataRepositoryForPackage<Triple<String, String, UserHandle>,
143         PermStateLiveData>() {
144         override fun newValue(key: Triple<String, String, UserHandle>): PermStateLiveData {
145             return PermStateLiveData(PermissionControllerApplication.get(),
146                 key.first, key.second, key.third)
147         }
148     }
149 }
150