1 /*
2  * 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.content.pm.PackageInfo
20 import android.content.pm.PackageManager
21 import android.content.pm.PermissionInfo
22 import com.android.permissioncontroller.permission.utils.PermissionMapping.isRuntimePlatformPermission
23 import com.android.permissioncontroller.permission.utils.SoftRestrictedPermissionPolicy
24 import com.android.permissioncontroller.permission.utils.Utils
25 
26 /**
27  * Represents a single permission, and its state
28  *
29  * @param pkgInfo The package requesting the permission
30  * @param permInfo The permissionInfo this represents
31  * @param isGrantedIncludingAppOp Whether or not this permission is functionally granted. A
32  *   non-granted app op but granted permission is counted as not granted
33  * @param flags The PermissionController flags for this permission
34  * @param foregroundPerms The foreground permission names corresponding to this permission, if this
35  *   permission is a background permission
36  */
37 data class LightPermission(
38     val pkgInfo: LightPackageInfo,
39     val permInfo: LightPermInfo,
40     val isGrantedIncludingAppOp: Boolean,
41     val flags: Int,
42     val foregroundPerms: List<String>?
43 ) {
44 
45     constructor(
46         pkgInfo: LightPackageInfo,
47         permInfo: LightPermInfo,
48         permState: PermState,
49         foregroundPerms: List<String>?
50     ) : this(pkgInfo, permInfo, permState.granted, permState.permFlags, foregroundPerms)
51 
52     /** The name of this permission */
53     val name = permInfo.name
54     /** The background permission name of this permission, if it exists */
55     val backgroundPermission: String? = permInfo.backgroundPermission
56     /** If this is a background permission */
57     val isBackgroundPermission = foregroundPerms?.isNotEmpty() ?: false
58     /** Whether this permission is fixed by policy */
59     val isPolicyFixed = flags and PackageManager.FLAG_PERMISSION_POLICY_FIXED != 0
60     /** Whether this permission is fixed by the system */
61     val isSystemFixed = flags and PackageManager.FLAG_PERMISSION_SYSTEM_FIXED != 0
62     /** Whether this permission is fixed by the system */
63     val isUserFixed = flags and PackageManager.FLAG_PERMISSION_USER_FIXED != 0
64     /** Whether this permission is user set */
65     val isUserSet = flags and PackageManager.FLAG_PERMISSION_USER_SET != 0
66     /** Whether this permission is granted, but its app op is revoked */
67     val isCompatRevoked = flags and PackageManager.FLAG_PERMISSION_REVOKED_COMPAT != 0
68     /** Whether this permission requires review (only relevant for pre-M apps) */
69     val isReviewRequired = flags and PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED != 0
70     /** Whether this permission is one-time */
71     val isOneTime = flags and PackageManager.FLAG_PERMISSION_ONE_TIME != 0
72     /** Whether this permission is an instant app permission */
73     val isInstantPerm = permInfo.protectionFlags and PermissionInfo.PROTECTION_FLAG_INSTANT != 0
74     /** Whether this permission is implicitly added to the package */
75     val isImplicit: Boolean by lazy {
76         var implicit = false
77         for ((permName, permFlags) in
78             pkgInfo.requestedPermissions.zip(pkgInfo.requestedPermissionsFlags)) {
79             if (
80                 permName == permInfo.name &&
81                     (permFlags and PackageInfo.REQUESTED_PERMISSION_IMPLICIT) != 0
82             ) {
83                 implicit = true
84                 break
85             }
86         }
87         implicit
88     }
89     /** Whether this permission is a runtime only permission */
90     val isRuntimeOnly =
91         permInfo.protectionFlags and PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY != 0
92     /** Whether this permission is granted by default */
93     val isGrantedByDefault = flags and PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT != 0
94     /** Whether this permission is granted by role */
95     val isGrantedByRole = flags and PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE != 0
96     /** Whether this permission is set to be revoked upon being requested */
97     val isRevokeWhenRequested = flags and PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED != 0
98     /** Whether this permission is user sensitive in its current grant state */
99     val isUserSensitive =
100         !isRuntimePlatformPermission(permInfo.name) ||
101             (isGrantedIncludingAppOp &&
102                 (flags and PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) != 0) ||
103             (!isGrantedIncludingAppOp &&
104                 (flags and PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) != 0)
105     /** Whether the permission is restricted */
106     val isRestricted =
107         when {
108             (permInfo.flags and PermissionInfo.FLAG_HARD_RESTRICTED) != 0 -> {
109                 flags and Utils.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT == 0
110             }
111             (permInfo.flags and PermissionInfo.FLAG_SOFT_RESTRICTED) != 0 -> {
112                 !SoftRestrictedPermissionPolicy.shouldShow(pkgInfo, permInfo.name, flags)
113             }
114             else -> {
115                 false
116             }
117         }
118     /** Whether the permission is auto revoked */
119     val isAutoRevoked = flags and PackageManager.FLAG_PERMISSION_AUTO_REVOKED != 0
120     /**
121      * Whether the location permission is selected as the level of granularity of location accuracy
122      */
123     val isSelectedLocationAccuracy =
124         flags and PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY != 0
125 
<lambda>null126     override fun toString() = buildString {
127         append(name)
128         if (isGrantedIncludingAppOp) append(", Granted") else append(", NotGranted")
129         if (isPolicyFixed) append(", PolicyFixed")
130         if (isSystemFixed) append(", SystemFixed")
131         if (isUserFixed) append(", UserFixed")
132         if (isUserSet) append(", UserSet")
133         if (isRevokeWhenRequested) append(", RevokeWhenRequested")
134         if (isCompatRevoked) append(", CompatRevoked")
135         if (isReviewRequired) append(", ReviewRequired")
136         if (isOneTime) append(", OneTime")
137         if (isGrantedByDefault) append(", GrantedByDefault")
138         if (isGrantedByRole) append(", GrantedByRole")
139         if (isUserSensitive) append(", UserSensitive")
140         if (isRestricted) append(", Restricted")
141         if (isAutoRevoked) append(", AutoRevoked")
142         if (isSelectedLocationAccuracy) append(", SelectedLocationAccuracy")
143     }
144 }
145