1 /* 2 * Copyright (C) 2008 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 android.content.pm; 18 19 import android.annotation.IntDef; 20 import android.annotation.SystemApi; 21 import android.annotation.TestApi; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 import android.text.TextUtils; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 29 /** 30 * Information you can retrieve about a particular security permission 31 * known to the system. This corresponds to information collected from the 32 * AndroidManifest.xml's <permission> tags. 33 */ 34 public class PermissionInfo extends PackageItemInfo implements Parcelable { 35 /** 36 * A normal application value for {@link #protectionLevel}, corresponding 37 * to the <code>normal</code> value of 38 * {@link android.R.attr#protectionLevel}. 39 */ 40 public static final int PROTECTION_NORMAL = 0; 41 42 /** 43 * Dangerous value for {@link #protectionLevel}, corresponding 44 * to the <code>dangerous</code> value of 45 * {@link android.R.attr#protectionLevel}. 46 */ 47 public static final int PROTECTION_DANGEROUS = 1; 48 49 /** 50 * System-level value for {@link #protectionLevel}, corresponding 51 * to the <code>signature</code> value of 52 * {@link android.R.attr#protectionLevel}. 53 */ 54 public static final int PROTECTION_SIGNATURE = 2; 55 56 /** 57 * @deprecated Use {@link #PROTECTION_SIGNATURE}|{@link #PROTECTION_FLAG_PRIVILEGED} 58 * instead. 59 */ 60 @Deprecated 61 public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; 62 63 /** @hide */ 64 @IntDef(flag = false, prefix = { "PROTECTION_" }, value = { 65 PROTECTION_NORMAL, 66 PROTECTION_DANGEROUS, 67 PROTECTION_SIGNATURE, 68 PROTECTION_SIGNATURE_OR_SYSTEM, 69 }) 70 @Retention(RetentionPolicy.SOURCE) 71 public @interface Protection {} 72 73 /** 74 * Additional flag for {@link #protectionLevel}, corresponding 75 * to the <code>privileged</code> value of 76 * {@link android.R.attr#protectionLevel}. 77 */ 78 public static final int PROTECTION_FLAG_PRIVILEGED = 0x10; 79 80 /** 81 * @deprecated Old name for {@link #PROTECTION_FLAG_PRIVILEGED}, which 82 * is now very confusing because it only applies to privileged apps, not all 83 * apps on the system image. 84 */ 85 @Deprecated 86 public static final int PROTECTION_FLAG_SYSTEM = 0x10; 87 88 /** 89 * Additional flag for {@link #protectionLevel}, corresponding 90 * to the <code>development</code> value of 91 * {@link android.R.attr#protectionLevel}. 92 */ 93 public static final int PROTECTION_FLAG_DEVELOPMENT = 0x20; 94 95 /** 96 * Additional flag for {@link #protectionLevel}, corresponding 97 * to the <code>appop</code> value of 98 * {@link android.R.attr#protectionLevel}. 99 */ 100 public static final int PROTECTION_FLAG_APPOP = 0x40; 101 102 /** 103 * Additional flag for {@link #protectionLevel}, corresponding 104 * to the <code>pre23</code> value of 105 * {@link android.R.attr#protectionLevel}. 106 */ 107 public static final int PROTECTION_FLAG_PRE23 = 0x80; 108 109 /** 110 * Additional flag for {@link #protectionLevel}, corresponding 111 * to the <code>installer</code> value of 112 * {@link android.R.attr#protectionLevel}. 113 */ 114 public static final int PROTECTION_FLAG_INSTALLER = 0x100; 115 116 /** 117 * Additional flag for {@link #protectionLevel}, corresponding 118 * to the <code>verifier</code> value of 119 * {@link android.R.attr#protectionLevel}. 120 */ 121 public static final int PROTECTION_FLAG_VERIFIER = 0x200; 122 123 /** 124 * Additional flag for {@link #protectionLevel}, corresponding 125 * to the <code>preinstalled</code> value of 126 * {@link android.R.attr#protectionLevel}. 127 */ 128 public static final int PROTECTION_FLAG_PREINSTALLED = 0x400; 129 130 /** 131 * Additional flag for {@link #protectionLevel}, corresponding 132 * to the <code>setup</code> value of 133 * {@link android.R.attr#protectionLevel}. 134 */ 135 public static final int PROTECTION_FLAG_SETUP = 0x800; 136 137 /** 138 * Additional flag for {@link #protectionLevel}, corresponding 139 * to the <code>instant</code> value of 140 * {@link android.R.attr#protectionLevel}. 141 */ 142 public static final int PROTECTION_FLAG_INSTANT = 0x1000; 143 144 /** 145 * Additional flag for {@link #protectionLevel}, corresponding 146 * to the <code>runtime</code> value of 147 * {@link android.R.attr#protectionLevel}. 148 */ 149 public static final int PROTECTION_FLAG_RUNTIME_ONLY = 0x2000; 150 151 /** 152 * Additional flag for {@link #protectionLevel}, corresponding 153 * to the <code>oem</code> value of 154 * {@link android.R.attr#protectionLevel}. 155 * 156 * @hide 157 */ 158 @SystemApi 159 public static final int PROTECTION_FLAG_OEM = 0x4000; 160 161 /** 162 * Additional flag for {${link #protectionLevel}, corresponding 163 * to the <code>vendorPrivileged</code> value of 164 * {@link android.R.attr#protectionLevel}. 165 * 166 * @hide 167 */ 168 @TestApi 169 public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000; 170 171 /** 172 * Additional flag for {@link #protectionLevel}, corresponding 173 * to the <code>text_classifier</code> value of 174 * {@link android.R.attr#protectionLevel}. 175 * 176 * @hide 177 */ 178 @SystemApi 179 @TestApi 180 public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 0x10000; 181 182 /** @hide */ 183 @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = { 184 PROTECTION_FLAG_PRIVILEGED, 185 PROTECTION_FLAG_SYSTEM, 186 PROTECTION_FLAG_DEVELOPMENT, 187 PROTECTION_FLAG_APPOP, 188 PROTECTION_FLAG_PRE23, 189 PROTECTION_FLAG_INSTALLER, 190 PROTECTION_FLAG_VERIFIER, 191 PROTECTION_FLAG_PREINSTALLED, 192 PROTECTION_FLAG_SETUP, 193 PROTECTION_FLAG_INSTANT, 194 PROTECTION_FLAG_RUNTIME_ONLY, 195 PROTECTION_FLAG_OEM, 196 PROTECTION_FLAG_VENDOR_PRIVILEGED, 197 PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER, 198 }) 199 @Retention(RetentionPolicy.SOURCE) 200 public @interface ProtectionFlags {} 201 202 /** 203 * Mask for {@link #protectionLevel}: the basic protection type. 204 * 205 * @deprecated Use #getProtection() instead. 206 */ 207 @Deprecated 208 public static final int PROTECTION_MASK_BASE = 0xf; 209 210 /** 211 * Mask for {@link #protectionLevel}: additional flag bits. 212 * 213 * @deprecated Use #getProtectionFlags() instead. 214 */ 215 @Deprecated 216 public static final int PROTECTION_MASK_FLAGS = 0xfff0; 217 218 /** 219 * The level of access this permission is protecting, as per 220 * {@link android.R.attr#protectionLevel}. Consists of 221 * a base permission type and zero or more flags. Use the following functions 222 * to extract them. 223 * 224 * <pre> 225 * int basePermissionType = permissionInfo.getProtection(); 226 * int permissionFlags = permissionInfo.getProtectionFlags(); 227 * </pre> 228 * 229 * <p></p>Base permission types are {@link #PROTECTION_NORMAL}, 230 * {@link #PROTECTION_DANGEROUS}, {@link #PROTECTION_SIGNATURE} 231 * and the deprecated {@link #PROTECTION_SIGNATURE_OR_SYSTEM}. 232 * Flags are listed under {@link android.R.attr#protectionLevel}. 233 * 234 * @deprecated Use #getProtection() and #getProtectionFlags() instead. 235 */ 236 @Deprecated 237 public int protectionLevel; 238 239 /** 240 * The group this permission is a part of, as per 241 * {@link android.R.attr#permissionGroup}. 242 */ 243 public String group; 244 245 /** 246 * Flag for {@link #flags}, corresponding to <code>costsMoney</code> 247 * value of {@link android.R.attr#permissionFlags}. 248 */ 249 public static final int FLAG_COSTS_MONEY = 1<<0; 250 251 /** 252 * Flag for {@link #flags}, corresponding to <code>removed</code> 253 * value of {@link android.R.attr#permissionFlags}. 254 * @hide 255 */ 256 @SystemApi 257 public static final int FLAG_REMOVED = 1<<1; 258 259 /** 260 * Flag for {@link #flags}, indicating that this permission has been 261 * installed into the system's globally defined permissions. 262 */ 263 public static final int FLAG_INSTALLED = 1<<30; 264 265 /** 266 * Additional flags about this permission as given by 267 * {@link android.R.attr#permissionFlags}. 268 */ 269 public int flags; 270 271 /** 272 * A string resource identifier (in the package's resources) of this 273 * permission's description. From the "description" attribute or, 274 * if not set, 0. 275 */ 276 public int descriptionRes; 277 278 /** 279 * A string resource identifier (in the package's resources) used to request the permissions. 280 * From the "request" attribute or, if not set, 0. 281 * 282 * @hide 283 */ 284 @SystemApi 285 public int requestRes; 286 287 /** 288 * The description string provided in the AndroidManifest file, if any. You 289 * probably don't want to use this, since it will be null if the description 290 * is in a resource. You probably want 291 * {@link PermissionInfo#loadDescription} instead. 292 */ 293 public CharSequence nonLocalizedDescription; 294 295 /** @hide */ fixProtectionLevel(int level)296 public static int fixProtectionLevel(int level) { 297 if (level == PROTECTION_SIGNATURE_OR_SYSTEM) { 298 level = PROTECTION_SIGNATURE | PROTECTION_FLAG_PRIVILEGED; 299 } 300 if ((level & PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0 301 && (level & PROTECTION_FLAG_PRIVILEGED) == 0) { 302 // 'vendorPrivileged' must be 'privileged'. If not, 303 // drop the vendorPrivileged. 304 level = level & ~PROTECTION_FLAG_VENDOR_PRIVILEGED; 305 } 306 return level; 307 } 308 309 /** @hide */ protectionToString(int level)310 public static String protectionToString(int level) { 311 String protLevel = "????"; 312 switch (level & PROTECTION_MASK_BASE) { 313 case PermissionInfo.PROTECTION_DANGEROUS: 314 protLevel = "dangerous"; 315 break; 316 case PermissionInfo.PROTECTION_NORMAL: 317 protLevel = "normal"; 318 break; 319 case PermissionInfo.PROTECTION_SIGNATURE: 320 protLevel = "signature"; 321 break; 322 case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM: 323 protLevel = "signatureOrSystem"; 324 break; 325 } 326 if ((level & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) { 327 protLevel += "|privileged"; 328 } 329 if ((level & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) { 330 protLevel += "|development"; 331 } 332 if ((level & PermissionInfo.PROTECTION_FLAG_APPOP) != 0) { 333 protLevel += "|appop"; 334 } 335 if ((level & PermissionInfo.PROTECTION_FLAG_PRE23) != 0) { 336 protLevel += "|pre23"; 337 } 338 if ((level & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0) { 339 protLevel += "|installer"; 340 } 341 if ((level & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0) { 342 protLevel += "|verifier"; 343 } 344 if ((level & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0) { 345 protLevel += "|preinstalled"; 346 } 347 if ((level & PermissionInfo.PROTECTION_FLAG_SETUP) != 0) { 348 protLevel += "|setup"; 349 } 350 if ((level & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0) { 351 protLevel += "|instant"; 352 } 353 if ((level & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0) { 354 protLevel += "|runtime"; 355 } 356 if ((level & PermissionInfo.PROTECTION_FLAG_OEM) != 0) { 357 protLevel += "|oem"; 358 } 359 if ((level & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0) { 360 protLevel += "|vendorPrivileged"; 361 } 362 if ((level & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) != 0) { 363 protLevel += "|textClassifier"; 364 } 365 return protLevel; 366 } 367 PermissionInfo()368 public PermissionInfo() { 369 } 370 PermissionInfo(PermissionInfo orig)371 public PermissionInfo(PermissionInfo orig) { 372 super(orig); 373 protectionLevel = orig.protectionLevel; 374 flags = orig.flags; 375 group = orig.group; 376 descriptionRes = orig.descriptionRes; 377 requestRes = orig.requestRes; 378 nonLocalizedDescription = orig.nonLocalizedDescription; 379 } 380 381 /** 382 * Retrieve the textual description of this permission. This 383 * will call back on the given PackageManager to load the description from 384 * the application. 385 * 386 * @param pm A PackageManager from which the label can be loaded; usually 387 * the PackageManager from which you originally retrieved this item. 388 * 389 * @return Returns a CharSequence containing the permission's description. 390 * If there is no description, null is returned. 391 */ loadDescription(PackageManager pm)392 public CharSequence loadDescription(PackageManager pm) { 393 if (nonLocalizedDescription != null) { 394 return nonLocalizedDescription; 395 } 396 if (descriptionRes != 0) { 397 CharSequence label = pm.getText(packageName, descriptionRes, null); 398 if (label != null) { 399 return label; 400 } 401 } 402 return null; 403 } 404 405 /** 406 * Return the base permission type. 407 */ 408 @Protection getProtection()409 public int getProtection() { 410 return protectionLevel & PROTECTION_MASK_BASE; 411 } 412 413 /** 414 * Return the additional flags in {@link #protectionLevel}. 415 */ 416 @ProtectionFlags getProtectionFlags()417 public int getProtectionFlags() { 418 return protectionLevel & ~PROTECTION_MASK_BASE; 419 } 420 421 @Override toString()422 public String toString() { 423 return "PermissionInfo{" 424 + Integer.toHexString(System.identityHashCode(this)) 425 + " " + name + "}"; 426 } 427 428 @Override describeContents()429 public int describeContents() { 430 return 0; 431 } 432 433 @Override writeToParcel(Parcel dest, int parcelableFlags)434 public void writeToParcel(Parcel dest, int parcelableFlags) { 435 super.writeToParcel(dest, parcelableFlags); 436 dest.writeInt(protectionLevel); 437 dest.writeInt(flags); 438 dest.writeString(group); 439 dest.writeInt(descriptionRes); 440 dest.writeInt(requestRes); 441 TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags); 442 } 443 444 /** @hide */ calculateFootprint()445 public int calculateFootprint() { 446 int size = name.length(); 447 if (nonLocalizedLabel != null) { 448 size += nonLocalizedLabel.length(); 449 } 450 if (nonLocalizedDescription != null) { 451 size += nonLocalizedDescription.length(); 452 } 453 return size; 454 } 455 456 /** @hide */ isAppOp()457 public boolean isAppOp() { 458 return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0; 459 } 460 461 public static final Creator<PermissionInfo> CREATOR = 462 new Creator<PermissionInfo>() { 463 @Override 464 public PermissionInfo createFromParcel(Parcel source) { 465 return new PermissionInfo(source); 466 } 467 @Override 468 public PermissionInfo[] newArray(int size) { 469 return new PermissionInfo[size]; 470 } 471 }; 472 PermissionInfo(Parcel source)473 private PermissionInfo(Parcel source) { 474 super(source); 475 protectionLevel = source.readInt(); 476 flags = source.readInt(); 477 group = source.readString(); 478 descriptionRes = source.readInt(); 479 requestRes = source.readInt(); 480 nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); 481 } 482 } 483