• 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.model.livedatatypes
18 
19 import android.Manifest
20 import android.Manifest.permission.ACCESS_COARSE_LOCATION
21 import android.os.Build
22 import android.os.UserHandle
23 import com.android.permissioncontroller.permission.utils.Utils
24 
25 /**
26  * A lightweight version of the AppPermissionGroup data structure. Represents information about a
27  * package, and all permissions in a particular permission group this package requests.
28  *
29  * @param packageInfo Information about the package
30  * @param permGroupInfo Information about the permission group
31  * @param allPermissions The permissions in the permission group that the package requests
32  *   (including restricted ones).
33  * @param hasInstallToRuntimeSplit If this group contains a permission that was previously an
34  *   install permission, but is currently a runtime permission
35  * @param specialLocationGrant If this package is the location provider, or the extra location
36  *   package, then the grant state of the group is not determined by the grant state of individual
37  *   permissions, but by other system properties
38  * @param specialFixedStorageGrant If this package holds the SYSTEM_GALLERY role, and has the
39  *   WRITE_MEDIA_IMAGES app op granted, then we should show the grant state of the storage
40  *   permissions as system fixed and granted.
41  *
42  */
43 data class LightAppPermGroup(
44     val packageInfo: LightPackageInfo,
45     val permGroupInfo: LightPermGroupInfo,
46     val allPermissions: Map<String, LightPermission>,
47     val hasInstallToRuntimeSplit: Boolean,
48     val specialLocationGrant: Boolean?,
49     val specialFixedStorageGrant: Boolean,
50 ) {
51     constructor(
52         pI: LightPackageInfo,
53         pGI: LightPermGroupInfo,
54         perms: Map<String, LightPermission>
55     ) : this(pI, pGI, perms, false, null, false)
56 
57     /** All unrestricted permissions. Usually restricted permissions are ignored */
58     val permissions: Map<String, LightPermission> =
59         allPermissions.filter { (_, permission) -> !permission.isRestricted }
60 
61     /** The package name of this group */
62     val packageName = packageInfo.packageName
63 
64     /** The permission group name of this group */
65     val permGroupName = permGroupInfo.name
66 
67     /** The current userHandle of this AppPermGroup. */
68     val userHandle: UserHandle = UserHandle.getUserHandleForUid(packageInfo.uid)
69 
70     /** The device ID of this group, inferred from LightPackageInfo */
71     val deviceId = packageInfo.deviceId
72 
73     /**
74      * The names of all background permissions in the permission group which are requested by the
75      * package.
76      */
77     val backgroundPermNames = permissions.mapNotNull { it.value.backgroundPermission }
78 
79     /** All foreground permissions in the permission group which are requested by the package. */
80     val foregroundPermNames
81         get() =
82             permissions.mapNotNull { (name, _) -> if (name !in backgroundPermNames) name else null }
83 
84     val isPlatformPermissionGroup = permGroupInfo.packageName == Utils.OS_PKG
85 
86     val foreground =
87         AppPermSubGroup(
88             permissions.filter { it.key in foregroundPermNames },
89             packageInfo,
90             isPlatformPermissionGroup,
91             specialLocationGrant,
92             specialFixedStorageGrant
93         )
94 
95     val background =
96         AppPermSubGroup(
97             permissions.filter { it.key in backgroundPermNames },
98             packageInfo,
99             isPlatformPermissionGroup,
100             specialLocationGrant,
101             specialFixedStorageGrant
102         )
103 
104     /** Whether or not this App Permission Group has a permission which has a background mode */
105     val hasPermWithBackgroundMode = backgroundPermNames.isNotEmpty()
106 
107     /** Whether or not this App Permission Group requests a background permission */
108     val hasBackgroundGroup = backgroundPermNames.any { permissions.contains(it) }
109 
110     /**
111      * Whether this App Permission Group's background and foreground permissions are fixed by policy
112      */
113     val isPolicyFullyFixed =
114         foreground.isPolicyFixed && (!hasBackgroundGroup || background.isPolicyFixed)
115 
116     /**
117      * Whether this App Permission Group's background permissions are fixed by the system or policy
118      */
119     val isBackgroundFixed = background.isPolicyFixed || background.isSystemFixed
120 
121     /**
122      * Whether this App Permission Group's foreground permissions are fixed by the system or policy
123      */
124     val isForegroundFixed = foreground.isPolicyFixed || foreground.isSystemFixed
125 
126     /** Whether or not this group supports runtime permissions */
127     val supportsRuntimePerms = packageInfo.targetSdkVersion >= Build.VERSION_CODES.M
128 
129     /**
130      * Whether this App Permission Group is one-time. 2 cases:
131      * 1. If the perm group is not LOCATION, check if any of the permissions is one-time and none of
132      *    the granted permissions are not one-time.
133      * 2. If the perm group is LOCATION, check if ACCESS_COARSE_LOCATION is one-time.
134      */
135     val isOneTime =
136         (permGroupName != Manifest.permission_group.LOCATION &&
137             permissions.any { it.value.isOneTime } &&
138             permissions.none { !it.value.isOneTime && it.value.isGranted }) ||
139             (permGroupName == Manifest.permission_group.LOCATION &&
140                 permissions[ACCESS_COARSE_LOCATION]?.isOneTime == true)
141 
142     /** Whether any permissions in this group are granted by default (pregrant) */
143     val isGrantedByDefault = foreground.isGrantedByDefault || background.isGrantedByDefault
144 
145     /** Whether any permissions in this group are granted by being a role holder */
146     val isGrantedByRole = foreground.isGrantedByRole || background.isGrantedByRole
147 
148     /** Whether any of the permission (foreground/background) is fixed by the system */
149     val isSystemFixed = foreground.isSystemFixed || background.isSystemFixed
150 
151     /** Whether any of the permission (foreground/background) in this group requires a review */
152     val isReviewRequired = foreground.isReviewRequired || background.isReviewRequired
153 
154     /** Whether any of the permission (foreground/background) is granted in this permission group */
155     var isGranted = foreground.isGranted || background.isGranted
156 
157     /** Whether any permissions in this group are user sensitive */
158     val isUserSensitive = permissions.any { it.value.isUserSensitive }
159 
160     /** Whether any permissions in this group are revoke-when-requested */
161     val isRevokeWhenRequested = permissions.any { it.value.isRevokeWhenRequested }
162 
163     /** Whether any of this App Permission Groups permissions are fixed by the user */
164     val isUserFixed = foreground.isUserFixed || background.isUserFixed
165 
166     /** Whether any of this App Permission Group's permissions are set by the user */
167     val isUserSet = foreground.isUserSet || background.isUserSet
168 
169     /**
170      * A subset of the AppPermissionGroup, representing either the background or foreground
171      * permissions of the full group.
172      *
173      * @param permissions The permissions contained within this subgroup, a subset of those
174      *   contained in the full group
175      * @param isPlatformPermissionGroup Whether this is a platform permission group
176      * @param specialLocationGrant Whether this is a special location package
177      * @param specialFixedStorageGrant Whether this is a special storage grant
178      */
179     data class AppPermSubGroup
180     internal constructor(
181         private val permissions: Map<String, LightPermission>,
182         private val packageInfo: LightPackageInfo,
183         private val isPlatformPermissionGroup: Boolean,
184         private val specialLocationGrant: Boolean?,
185         private val specialFixedStorageGrant: Boolean
186     ) {
187         /** Whether any of this App Permission SubGroup's permissions are granted */
188         val isGranted =
189             specialLocationGrant
190                 ?: specialFixedStorageGrant || permissions.any {
191                     val mayGrantByPlatformOrSystem =
192                         !isPlatformPermissionGroup || it.value.isPlatformOrSystem
193                     it.value.isGranted && mayGrantByPlatformOrSystem
194                 }
195 
196         /**
197          * Whether this App Permission SubGroup should be treated as granted. This means either:
198          * 1) At least one permission was granted excluding auto-granted permissions (i.e., granted
199          *    during install time with flag RevokeWhenRequested.) Or,
200          * 2) All permissions were auto-granted (all permissions are all granted and all
201          *    RevokeWhenRequested.)
202          */
203         val allowFullGroupGrant =
204             specialLocationGrant
205                 ?: (permissions.any {
206                     val mayGrantByPlatformOrSystem =
207                         !isPlatformPermissionGroup || it.value.isPlatformOrSystem
208                     it.value.allowFullGroupGrant && mayGrantByPlatformOrSystem
209                 } || permissions.all { it.value.isGranted && it.value.isRevokeWhenRequested })
210 
211         /** Whether any of this App Permission SubGroup's permissions are granted by default */
212         val isGrantedByDefault = permissions.any { it.value.isGrantedByDefault }
213 
214         /**
215          * Whether at least one of this App Permission SubGroup's permissions is one-time and none
216          * of the granted permissions are not one-time.
217          */
218         val isOneTime =
219             permissions.any { it.value.isOneTime } &&
220                 permissions.none { it.value.isGranted && !it.value.isOneTime }
221 
222         /**
223          * Whether any of this App Permission Subgroup's foreground permissions are fixed by policy
224          */
225         val isPolicyFixed = permissions.any { it.value.isPolicyFixed }
226 
227         /** Whether any of this App Permission Subgroup's permissions are fixed by the system */
228         val isSystemFixed = permissions.any { it.value.isSystemFixed } || specialFixedStorageGrant
229 
230         /** Whether any of this App Permission Subgroup's permissions are fixed by the user */
231         val isUserFixed = permissions.any { it.value.isUserFixed }
232 
233         /** Whether any of this App Permission Subgroup's permissions are set by the user */
234         val isUserSet = permissions.any { it.value.isUserSet }
235 
236         /** whether review is required or not for the permission group */
237         val isReviewRequired = permissions.any { it.value.isReviewRequired }
238 
239         /**
240          * Whether any of this App Permission Subgroup's permissions are set by the role of this app
241          */
242         val isGrantedByRole = permissions.any { it.value.isGrantedByRole }
243 
244         private val hasPreRuntimePerm = permissions.any { (_, perm) -> !perm.isRuntimeOnly }
245 
246         private val hasInstantPerm = permissions.any { (_, perm) -> perm.isInstantPerm }
247 
248         /** Whether or not any permissions in this App Permission Subgroup can be granted */
249         val isGrantable =
250             (!packageInfo.isInstantApp || hasInstantPerm) &&
251                 (packageInfo.targetSdkVersion >= Build.VERSION_CODES.M || hasPreRuntimePerm)
252     }
253 }
254