1 /* 2 * Copyright (C) 2015 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.packageinstaller.permission.model; 18 19 import android.content.pm.PackageManager; 20 import android.content.pm.PermissionInfo; 21 22 import androidx.annotation.NonNull; 23 24 import java.util.ArrayList; 25 26 /** 27 * A permission and it's properties. 28 * 29 * @see AppPermissionGroup 30 */ 31 public final class Permission { 32 private final @NonNull PermissionInfo mPermissionInfo; 33 private final String mName; 34 private final String mBackgroundPermissionName; 35 private final String mAppOp; 36 37 private boolean mGranted; 38 private boolean mAppOpAllowed; 39 private int mFlags; 40 private boolean mIsEphemeral; 41 private boolean mIsRuntimeOnly; 42 private Permission mBackgroundPermission; 43 private ArrayList<Permission> mForegroundPermissions; 44 private boolean mWhitelisted; 45 Permission(String name, @NonNull PermissionInfo permissionInfo, boolean granted, String appOp, boolean appOpAllowed, int flags)46 public Permission(String name, @NonNull PermissionInfo permissionInfo, boolean granted, 47 String appOp, boolean appOpAllowed, int flags) { 48 mPermissionInfo = permissionInfo; 49 mName = name; 50 mBackgroundPermissionName = permissionInfo.backgroundPermission; 51 mGranted = granted; 52 mAppOp = appOp; 53 mAppOpAllowed = appOpAllowed; 54 mFlags = flags; 55 mIsEphemeral = 56 (permissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0; 57 mIsRuntimeOnly = 58 (permissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0; 59 } 60 61 /** 62 * Mark this permission as background permission for {@code foregroundPermissions}. 63 * 64 * @param foregroundPermission The foreground permission 65 */ addForegroundPermissions(Permission foregroundPermission)66 public void addForegroundPermissions(Permission foregroundPermission) { 67 if (mForegroundPermissions == null) { 68 mForegroundPermissions = new ArrayList<>(1); 69 } 70 mForegroundPermissions.add(foregroundPermission); 71 } 72 73 /** 74 * Mark this permission as foreground permission for {@code backgroundPermission}. 75 * 76 * @param backgroundPermission The background permission 77 */ setBackgroundPermission(Permission backgroundPermission)78 public void setBackgroundPermission(Permission backgroundPermission) { 79 mBackgroundPermission = backgroundPermission; 80 } 81 getPermissionInfo()82 public PermissionInfo getPermissionInfo() { 83 return mPermissionInfo; 84 } 85 getName()86 public String getName() { 87 return mName; 88 } 89 getAppOp()90 public String getAppOp() { 91 return mAppOp; 92 } 93 getFlags()94 public int getFlags() { 95 return mFlags; 96 } 97 isHardRestricted()98 boolean isHardRestricted() { 99 return (mPermissionInfo.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0; 100 } 101 isSoftRestricted()102 boolean isSoftRestricted() { 103 return (mPermissionInfo.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0; 104 } 105 106 /** 107 * Does this permission affect app ops. 108 * 109 * <p>I.e. does this permission have a matching app op or is this a background permission. All 110 * background permissions affect the app op of it's assigned foreground permission. 111 * 112 * @return {@code true} if this permission affects app ops 113 */ affectsAppOp()114 public boolean affectsAppOp() { 115 return mAppOp != null || isBackgroundPermission(); 116 } 117 118 /** 119 * Check if the permission is granted. 120 * 121 * <p>This ignores the state of the app-op. I.e. for apps not handling runtime permissions, this 122 * always returns {@code true}. 123 * 124 * @return If the permission is granted 125 */ isGranted()126 public boolean isGranted() { 127 return mGranted; 128 } 129 130 /** 131 * Check if the permission is granted, also considering the state of the app-op. 132 * 133 * <p>For the UI, check the grant state of the whole group via 134 * {@link AppPermissionGroup#areRuntimePermissionsGranted}. 135 * 136 * @return {@code true} if the permission (and the app-op) is granted. 137 */ isGrantedIncludingAppOp()138 public boolean isGrantedIncludingAppOp() { 139 return mGranted && (!affectsAppOp() || isAppOpAllowed()) && !isReviewRequired(); 140 } 141 isReviewRequired()142 public boolean isReviewRequired() { 143 return (mFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0; 144 } 145 unsetReviewRequired()146 public void unsetReviewRequired() { 147 mFlags &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; 148 } 149 setGranted(boolean mGranted)150 public void setGranted(boolean mGranted) { 151 this.mGranted = mGranted; 152 } 153 isAppOpAllowed()154 public boolean isAppOpAllowed() { 155 return mAppOpAllowed; 156 } 157 isUserFixed()158 public boolean isUserFixed() { 159 return (mFlags & PackageManager.FLAG_PERMISSION_USER_FIXED) != 0; 160 } 161 setUserFixed(boolean userFixed)162 public void setUserFixed(boolean userFixed) { 163 if (userFixed) { 164 mFlags |= PackageManager.FLAG_PERMISSION_USER_FIXED; 165 } else { 166 mFlags &= ~PackageManager.FLAG_PERMISSION_USER_FIXED; 167 } 168 } 169 isSystemFixed()170 public boolean isSystemFixed() { 171 return (mFlags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0; 172 } 173 isPolicyFixed()174 public boolean isPolicyFixed() { 175 return (mFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0; 176 } 177 isUserSet()178 public boolean isUserSet() { 179 return (mFlags & PackageManager.FLAG_PERMISSION_USER_SET) != 0; 180 } 181 isGrantedByDefault()182 public boolean isGrantedByDefault() { 183 return (mFlags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0; 184 } 185 186 /** 187 * Is the permission user sensitive, i.e. should it always be shown to the user. 188 * 189 * <p>Non-sensitive permission are usually hidden behind a setting in an overflow menu or 190 * some other kind of flag. 191 * 192 * @return {@code true} if the permission is user sensitive. 193 */ isUserSensitive()194 public boolean isUserSensitive() { 195 if (isGrantedIncludingAppOp()) { 196 return (mFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) != 0; 197 } else { 198 return (mFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) != 0; 199 } 200 } 201 202 /** 203 * If this permission is split into a foreground and background permission, this is the name 204 * of the background permission. 205 * 206 * @return The name of the background permission or {@code null} if the permission is not split 207 */ getBackgroundPermissionName()208 public String getBackgroundPermissionName() { 209 return mBackgroundPermissionName; 210 } 211 212 /** 213 * @return If this permission is split into a foreground and background permission, 214 * returns the background permission 215 */ getBackgroundPermission()216 public Permission getBackgroundPermission() { 217 return mBackgroundPermission; 218 } 219 220 /** 221 * @return If this permission is split into a foreground and background permission, 222 * returns the foreground permission 223 */ getForegroundPermissions()224 public ArrayList<Permission> getForegroundPermissions() { 225 return mForegroundPermissions; 226 } 227 228 /** 229 * @return {@code true} iff this is the foreground permission of a background-foreground-split 230 * permission 231 */ hasBackgroundPermission()232 public boolean hasBackgroundPermission() { 233 return mBackgroundPermissionName != null; 234 } 235 236 /** 237 * @return {@code true} iff this is the background permission of a background-foreground-split 238 * permission 239 */ isBackgroundPermission()240 public boolean isBackgroundPermission() { 241 return mForegroundPermissions != null; 242 } 243 setUserSet(boolean userSet)244 public void setUserSet(boolean userSet) { 245 if (userSet) { 246 mFlags |= PackageManager.FLAG_PERMISSION_USER_SET; 247 } else { 248 mFlags &= ~PackageManager.FLAG_PERMISSION_USER_SET; 249 } 250 } 251 setPolicyFixed(boolean policyFixed)252 public void setPolicyFixed(boolean policyFixed) { 253 if (policyFixed) { 254 mFlags |= PackageManager.FLAG_PERMISSION_POLICY_FIXED; 255 } else { 256 mFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED; 257 } 258 } 259 shouldRevokeOnUpgrade()260 public boolean shouldRevokeOnUpgrade() { 261 return (mFlags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0; 262 } 263 setRevokeOnUpgrade(boolean revokeOnUpgrade)264 public void setRevokeOnUpgrade(boolean revokeOnUpgrade) { 265 if (revokeOnUpgrade) { 266 mFlags |= PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE; 267 } else { 268 mFlags &= ~PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE; 269 } 270 } 271 setAppOpAllowed(boolean mAppOpAllowed)272 public void setAppOpAllowed(boolean mAppOpAllowed) { 273 this.mAppOpAllowed = mAppOpAllowed; 274 } 275 isEphemeral()276 public boolean isEphemeral() { 277 return mIsEphemeral; 278 } 279 isRuntimeOnly()280 public boolean isRuntimeOnly() { 281 return mIsRuntimeOnly; 282 } 283 isGrantingAllowed(boolean isEphemeralApp, boolean supportsRuntimePermissions)284 public boolean isGrantingAllowed(boolean isEphemeralApp, boolean supportsRuntimePermissions) { 285 return (!isEphemeralApp || isEphemeral()) 286 && (supportsRuntimePermissions || !isRuntimeOnly()); 287 } 288 } 289