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