Android权限的⼀些细节
Android 权限的⼀些细节
1 哪些app属于system app?
为了区分privilege app和system app,这⾥先说明system app是什么,避免之后的讨论概念混乱。
在PackageManagerService中对是否是system app的判断:
具有ApplicationInfo.FLAG_SYSTEM标记的,被视为System app。
1private static boolean isSystemApp(PackageParser.Package pkg) {
2return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
3 }
4
5private static boolean isSystemApp(PackageSetting ps) {
6return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
7 }
有两类app属于System app:
1.1 第⼀类System app:特定的shared uid的app 属于system app
例如:shared uid为android.uid.system,android.uid.phone,android.uid.log,android.uid.nfc,android.uid.bluetooth,android.uid.shell。这类app都被赋予了ApplicationInfo.FLAG_SYSTEM标志。
在PackageManagerService的构造⽅法中,代码如下:
1 mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
2 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
3 mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
4 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
5 mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
6 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
7 mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
8 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
9 mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
10 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
11 mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
12 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
1.2 第⼆类System app:特定⽬录中的app属于system app
特定⽬录包括:/vendor/overlay,/system/framework,/system/priv-app,/system/app,/vendor/app,/oem/app。这些⽬录中的app,被视为system app。
在PackageManagerService的构造⽅法中,代码如下:
1// /vendor/overlay folder
2 File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
3 scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
4 | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
5
6// Find base frameworks (resource packages without code). /system/framework folder
7 File frameworkDir = new RootDirectory(), "framework");
8 scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
9 | PackageParser.PARSE_IS_SYSTEM_DIR
10 | PackageParser.PARSE_IS_PRIVILEGED,
11 scanFlags | SCAN_NO_DEX, 0);
12
13// Collected privileged system packages. /system/priv-app folder
14final File privilegedAppDir = new RootDirectory(), "priv-app");
15 scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
16 | PackageParser.PARSE_IS_SYSTEM_DIR
17 | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
18
19// Collect ordinary system packages. /system/app folder
20final File systemAppDir = new RootDirectory(), "app");
21 scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
22 | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
23
24// Collect all vendor packages.
25 File vendorAppDir = new File("/vendor/app");
26 scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
27 | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
28
29// Collect all OEM packages. /oem/app folder
30final File oemAppDir = new OemDirectory(), "app");
31 scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
32 | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
scanDirLI参数中的PackageParser.PARSE_IS_SYSTEM最终会被转换为Package的ApplicationInfo.FLAG_SYSTEM属性。这个过程相关的代码流程(简略):
1 scanDirLI(PackageParser.PARSE_IS_SYSTEM)
2
3 -> scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK, scanFlags, currentTime, null);
4
5 -> scanPackageLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user);
6
7 -> final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags, currentTime, user);
8
9 -> scanPackageDirtyLI()中
10if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
11 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
12 }
2 什么是privileged app(特权app)?
注:privileged app,在本⽂中称之为特权app,主要原因是此类特权app可以使⽤protectionLevel为signatureOrSystem或者protectionLevel为signature|privileged的权限。从PackageManagerService的isPrivilegedApp()可以看出特权app是具有ApplicationInfo.PRIVATE_FLAG_PRIVILEGED标志的⼀类app。
1private static boolean isPrivilegedApp(PackageParser.Package pkg) {
2return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
3 }
特权app⾸先必须是System app。也就是说 System app分为普通的system app和特权的system app。
1 System app = 普通的system app + 特权app
直观的(但不准确严谨)说,普通的system app就是/system/app⽬录中的app,特权的system app就是/system/priv-app⽬录中的app。
BTW: priv-app 是privileged app的简写。
区分普通system app和特权app的⽬的是澄清这个概念:"signatureOrSystem"权限中的System不是为普通system app提供的,⽽是只有特权app能够使⽤。
进⼀步说,android:protectionLevel="signatureOrSystem"中的System和android:protectionLevel="signature|privileged"中的privileged的含义是⼀样的。
可以从PermissionInfo.java中的fixProtectionLevel()看出来:
// PermissionInfo.java
public static int fixProtectionLevel(int level) {
if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {
// "signatureOrSystem"权限转换成了"signature|privileged"权限
level = PROTECTION_SIGNATURE | PROTECTION_FLAG_PRIVILEGED;
}
return level;
}
所以,当我们说起system app时,通常指的是前⾯提到的特定uid和特定⽬录中的app,包含了普通的system app和特权app。
当我们说起有访问System权限或者privileged权限的app时,通常指特权app。
3 哪些app属于privileged app(特权app)?
特权app⾸先是System app,然后要具有ApplicationInfo.PRIVATE_FLAG_PRIVILEGED标志。
有两类app属于privileged app(特权app):
参考PackageManagerService的构造⽅法。
3.1 第⼀类privileged app:特定uid的app
shared uid为"android.uid.system","android.uid.phone","android.uid.log","android.uid.nfc","android.uid.bluetooth","android.uid.shell"的app被赋予了privileged的权限。这些app同时也是system app。
代码如下:
1// PackageManagerService的构造⽅法
2 mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
3 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
4 mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
5 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
6 mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
7 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
8 mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
9 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
10 mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
11 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
12 mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
13 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
3.2 第⼆类privileged app:/system/framework和/system/priv-app⽬录下的app
/system/framework和/system/priv-app⽬录下的app被赋予了privileged的权限。
其中/system/framework⽬录中的apk,只是包含资源,不包含代码(dex)。
代码如下:
/
1 / PackageManagerService的构造⽅法
2// /system/framework
3 File frameworkDir = new RootDirectory(), "framework");
4 scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
5 | PackageParser.PARSE_IS_SYSTEM_DIR
6 | PackageParser.PARSE_IS_PRIVILEGED,
7 scanFlags | SCAN_NO_DEX, 0);
8
9// /system/priv-app
10final File privilegedAppDir = new RootDirectory(), "priv-app");
11 scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
12 | PackageParser.PARSE_IS_SYSTEM_DIR
13 | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
14
15 PackageParser.PARSE_IS_PRIVILEGED标志最终会转换为Package的ApplicationInfo.PRIVATE_FLAG_PRIVILEGED标志。⼤概的代码流程,如下:
16
17 scanDirLI(PackageParser.PARSE_IS_PRIVILEGED)
18
19 -> scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK, scanFlags, currentTime, null);
20
21 -> PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user);
22
23 -> final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags, currentTime, user);
24
25 -> scanPackageDirtyLI()中
26if ((parseFlags & PackageParser.PARSE_IS_PRIVILEGED) != 0) {
27 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
28 }
29
4 Android app中的权限是必须先声明后使⽤吗?
在本⽂中,声明权限是指在l中使⽤了<permission>,使⽤权限是指在l中使⽤了<uses-permission>。获得权限(或赋予权限)是指真正的可以通过系统
的权限检查,调⽤到权限保护的⽅法。
场景:App A中声明了权限PermissionA,App B中使⽤了权限PermissionA。
那么App A必须⽐App B先安装,App B才能获取到权限吗?
答案是不⼀定,要看具体情况⽽定。这个具体情况就是权限的保护级别。
情况⼀:PermissionA的保护级别是normal或者dangerous
App B先安装,App A后安装,此时App B没有获取到PermissionA的权限。
即,此种情况下,权限必须先声明再使⽤。即使App A和App B是相同的签名。
情况⼆:PermissionA的保护级别是signature或者signatureOrSystem
App B先安装,App A后安装,如果App A和App B是相同的签名,那么App B可以获取到PermissionA的权限。如果App A和App B的签名不同,则App B获取不到PermissionA权限。
即,对于相同签名的app来说,不论安装先后,只要是声明了权限,请求该权限的app就会获得该权限。
这也说明了对于具有相同签名的系统app来说,安装过程不会考虑权限依赖的情况。安装系统app时,按照某个顺序(例如名字排序,⽬录位置排序等)安装即可,等所有app安装完了,所有使⽤权限的app都会获得权限。
在这⾥提供⼀种⽅法,可以⽅便的验证上⾯的说法:
4.1 验证某个app是否获得了某个权限的⽅法
可以⽤下⾯2个命令来验证:
adb shell dumpsys package permission <;权限名>
adb shell dumpsys package <;包名>
其中,adb shell dumpsys package permission <;权限名>可以查看某个权限是谁声明的,谁使⽤了。
adb shell dumpsys package <;包名>可以看到某个app是否获得了某个权限。
例如,App A中声明了权限com.package.a.PermissionA,App B中使⽤了权限com.package.a.PermissionA。
App A的包名为com.package.a,App B的包名为com.package.b。
4.1.1 命令⼀: adb shell dumpsys package permission <;权限名>
查看某个权限是谁声明的,谁使⽤了。
通过下⾯的命令,查看com.package.a.PermissionA权限:
adb shell dumpsys package permission com.package.a.PermissionA
输出结果为:(注:这⾥只显⽰关键信息,省略了其他很多信息)
Permission [com.package.a.PermissionA] (a2930ef):
sourcePackage=com.package.a // 权限的声明者
uid=10226 gids=null type=0 prot=normal //保护级别为normal
Packages:
Package [com.package.b] (350d95): // 权限的使⽤者
requested permissions:
com.package.a.PermissionA
install permissions:
com.package.a.PermissionA, granted=true, flags=0x0
其中granted=true表明App B 获取到了com.package.a.PermissionA权限。
如果App B没有获取到com.package.a.PermissionA权限,则输出结果中只有权限的声明信息,如下:
Permission [com.package.a.PermissionA] (a2930ef):
sourcePackage=com.package.a
uid=10226 gids=null type=0 prot=normal 保护级别为normal
4.1.2 命令⼆: adb shell dumpsys package <;包名>
查看某个app是否获得了某个权限。
查看App B(包名为com.package.b)是否获得了权限com.package.a.PermissionA:
adb shell dumpsys package com.package.b
输出结果为:(注:省略了很多其他信息)
Packages:
Package [com.package.b] (6611d16):
requested permissions: // 申请了哪些权限
com.package.a.PermissionA
install permissions: // 获得了哪些权限
com.package.a.PermissionA, granted=true, flags=0x0
上⾯的输出结果表明,App B获取到了com.package.a.PermissionA权限。
如果App B没有获取到 com.package.a.PermissionA 权限,那么在 install permissions 中不会出现com.package.a.PermissionA, granted=true, flags=0x0。
5 关于signature权限和signatureOrSystem权限的获取(或拒绝)
这⾥要说的是这种场景:App A中声明了权限com.package.a.PermissionA,App B中使⽤了权限com.package.a.PermissionA。其中com.package.a.PermissionA的保护级别为signature或者signatureOrSystem。App A先安装,App B后安装。App B和App A的签名可能⼀样,也可能不⼀样。App B的签名也可能是系统签名,这是对于⼚商的app来说的。
安装App B时,PackageManagerService会对App B能否获得com.package.a.PermissionA权限做检查。
⼤概的代码流程如下:
安装App B的时候:
1 installPackageLI()
2private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
3final File tmpPackageFile = new CodePath());// 被安装的apk的路径
4final PackageParser.Package pkg;
5try {
6 pkg = pp.parsePackage(tmpPackageFile, parseFlags);
7 }
8 ...
9if (replace) {
10 ...
11 } else {
12// run here
13 installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
14 args.user, installerPackageName, volumeUuid, res);
15 }
16 }
17 installNewPackageLI()
18private void installNewPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user, String installerPackageName, String volumeUuid, PackageInstalledInfo res) {
19 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanFlags, System.currentTimeMillis(), user);
20
21 updateSettingsLI(newPackage, installerPackageName, volumeUuid, null, null, res, user);// run here
22 }
23 updateSettingsLI()
24private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
25 String volumeUuid, int[] allUsers, boolean[] perUserInstalled, PackageInstalledInfo res,
26 UserHandle user) {
27
28 updatePermissionsLPw(newPackage.packageName, newPackage,
29 UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
30 ? UPDATE_PERMISSIONS_ALL : 0));
31 grantPermissionsLPw()
32private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace,
33 String packageOfInterest) {
34
35// 遍历安装包pkg中所有请求的权限
36final int N = questedPermissions.size();
37for (int i=0; i<N; i++) {
38final String name = (i); // 权限的名字
39final BasePermission bp = (name);// 权限的信息
40
41final String perm = bp.name;
42boolean allowedSig = false;
43int grant = GRANT_DENIED;
44
45final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; // 权限的保护级别, PROTECTION_MASK_BASE 为0xf,signature级别时,bp.protectionLevel = 2;signatureOrSystem级别时,bp.protectionLevel = 0x12,所46switch (level) {
47case PermissionInfo.PROTECTION_NORMAL: { // value is 0
48// For all apps normal permissions are install time ones.
49 grant = GRANT_INSTALL;
50 } break;
51
52case PermissionInfo.PROTECTION_DANGEROUS: {// value is 1
53// 略
54 } break;
55
56// 被安装app使⽤了其他app声明的signature或者signatureOrSystem权限,上⾯提到的场景会执⾏到这⾥
57case PermissionInfo.PROTECTION_SIGNATURE: {// value is 2
58// For all apps signature permissions are install time ones.
59 allowedSig = grantSignaturePermission(perm, pkg, bp, origPermissions);android获取真正的签名
60if (allowedSig) {
61 grant = GRANT_INSTALL;
62 }
63 } break;
64 }
65 grantSignaturePermission()
注:pre23的权限,请参考链接:关于pre23权限。
1private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
2 BasePermission bp, PermissionsState origPermissions) {
3boolean allowed;
4// 这⾥检查被安装的app的签名(pkg.mSignatures)与声明权限的app的签名(bp.packageSetting.signatures.mSignatures)是否⼀致,
5// 如果不⼀致,则再检查被安装app的签名是否与系统签名(mPlatformPackage.mSignatures)⼀致。
6// 如果其中⼀个是⼀致的,则赋予被安装app signature权限。
7// 注意:只要被安装的app的签名是系统签名,则其可以访问任意第三⽅声明的signature权限。
8 allowed = (compareSignatures(
9 bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
10 == PackageManager.SIGNATURE_MATCH)
11 || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
12 == PackageManager.SIGNATURE_MATCH);
13
14// 如果被安装app的签名既不是声明权限的app的签名,也不是系统签名,则继续检查其他标志位。
15// ⾸先检查声明的权限是否是privileged权限(也就是signatureOrSystem中的System权限),如果权限是privileged的,那么对于系统应⽤(满⾜isSystemApp(pkg))并且是privileged应⽤(满⾜isPrivilegedApp(pkg)),就会赋予
16if (!allowed && (bp.protectionLevel
17 & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) {
18if (isSystemApp(pkg)) {// 如果被安装的app是system应⽤(见前⾯对system app的说明)
19if (pkg.isUpdatedSystemApp()) { // 如果是更新系统app
20// 略
21 } else {// 不是更新系统app,如果被安装的app是privileged的,则赋予其权限。也就是说,对于/system/priv-app⽬录中的app,会获取到权限。这种情况发⽣在privileged app第⼀次被安装时,[或者系统被root后,强⾏push apk到system/priv-app⽬
22 allowed = isPrivilegedApp(pkg);
23 }
24 }
25 }
26
27if (!allowed) {
28if (!allowed && (bp.protectionLevel
29 & PermissionInfo.PROTECTION_FLAG_PRE23) != 0
30 && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {// 如果之前没有获取到权限,再判断是否是pre23的权限。如果是pre23的权限,且被安装的app的targetVersion是22及以下,则赋予其权限。
31 allowed = true;
32 }
33if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0
34 && pkg.packageName.equals(mRequiredInstallerPackage)) {// 只有指定的system installer才能使⽤该权限。
35 allowed = true;
36 }
37if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0
38 && pkg.packageName.equals(mRequiredVerifierPackage)) {// 只有指定的system verifier才能使⽤该权限。
39 allowed = true;
40 }
41if (!allowed && (bp.protectionLevel
42 & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0
43 && isSystemApp(pkg)) { // 对于preinstalled级别的权限,只有系统app可以使⽤该权限。
44// Any pre-installed system app is allowed to get this permission.
45 allowed = true;
46 }
47if (!allowed && (bp.protectionLevel
48 & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
49// For development permissions, a development permission
50// is granted only if it was already granted.
51 allowed = origPermissions.hasInstallPermission(perm);
52 }
53 }
54return allowed;
55 }
6 哪些app可以使⽤某app提供的signature权限或signatureOrSystem权限?
根据上⾯的代码,我们可以得出以下结论:
如果App A声明了signatureOrSystem权限,即android:protectionLevel="signature|privileged"或者android:protectionLevel="signatureOrSystem",则可以使⽤该权限的app包
括:
(1)与App A有相同签名的app
(2)与系统签名相同的app,即与⼚商签名(⼚商ROM中的系统app签名)相同的app
(3)在/system/priv-app⽬录中的app,不管是否满⾜(1)和(2)的条件。即任意app只要放到了/system/priv-app就可以使⽤App A的signatureOrSystem级别的权限。
如果App A声明了signature权限,即android:protectionLevel="signature",则可以使⽤该权限的app包括:
(1)与App A有相同签名的app
(2)与系统签名相同的app,即与⼚商签名(⼚商ROM中的系统app签名)相同的app
注意:与系统签名相同,即与⼚商签名相同,这是指⼚商推出的app,这些app有很⼤的访问权限。
7 关于pre23的权限
在framework/base/core/l中,有2个权限从normal级别提升到signature级别,它们是
android.permission.WRITE_SETTINGS
android.permission.SYSTEM_ALERT_WINDOW
可以预见,当市场上绝⼤多数app的targetSdkVersion为23或23以上(即Android 6.0或以上)时,pre23字样将会被去掉,到那时这两个权限将会得到更好地保护。
pre23的含义是,如果某个app的targetSdkVersion是22或者22以下(即Android 5.x及以下),那么该app就可以获取到这2个权限。
<permission android:name="android.permission.WRITE_SETTINGS"
android:label="@string/permlab_writeSettings"
android:description="@string/permdesc_writeSettings"
android:protectionLevel="signature|preinstalled|appop|pre23"/>
<permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
android:label="@string/permlab_systemAlertWindow"
android:description="@string/permdesc_systemAlertWindow"
android:protectionLevel="signature|preinstalled|appop|pre23|development"/>
8 关于install权限和runtime权限
install权限:安装时权限,是指在安装app的时候,赋予app的权限。normal和signature级别的权限都是安装时权限。不会给⽤户提⽰界⾯,系统⾃动决定权限的赋予或拒绝。runtime权限:运⾏时权限,是指在app运⾏过程中,赋予app的权限。这个过程中,会显⽰明显的权限授予界⾯,让⽤户决定是否授予权限。如果app的targetSdkVersion是
22(Lollipop MR1)及以下,dangerous权限是安装时权限,否则dangerous权限是运⾏时权限。
参考:grantPermissionsLPw()中的注释。
9 官⽅⽂档关于权限保护级别的说明
权限保护级别是指由android:protectionLevel指定的值。
Value Meaning
“normal” normal级别是默认值。低风险的权限采⽤此级别。在app安装的时候,系统⾃动赋予此app请求的所有normal权限,⽽不会征求⽤户的同意(但是,在安装app之前,⽤户总是有权选择检查这些权限)。
“dangerous” 较⾼风险的权限,此级别的权限意味着,请求权限的app将要访问⽤户的隐私数据或者控制设备,这可能给⽤户带来负⾯影响。
因为dangerous权限会引⼊潜在的风险,所以系统不会⾃动赋予此类权限给app。例如,在安装app的时候,会将dangerous权限展⽰给⽤户,并请求⽤户确认。“signature” 只有请求权限的app与声明权限的app的签名是⼀样的时候,系统才会赋予signature权限。
如果签名⼀致,系统会⾃动赋予权限,⽽不会通知⽤户或者征求⽤户的同意。
“signatureOrSystem” 系统赋予此类权限有2种情况:(1)请求权限的app与声明权限的app的签名⼀致;(2)请求权限的app在Android 系统镜像(system image)中。signatureOrSystem权限主要⽤在这个场景:多个软件供应商的apps预装到了系统⽬录(system/priv-app)中,⽽且这些apps之间会共享⼀些功能。除此之外,尽量不要使⽤此类权限级别。
PermissionInfo.java中的权限保护级别主要有PROTECTION_NORMAL, PROTECTION_DANGEROUS, 或者 PROTECTION_SIGNATURE。
public static final int PROTECTION_NORMAL = 0;
public static final int PROTECTION_DANGEROUS = 1;
public static final int PROTECTION_SIGNATURE = 2;
除此之外,signature级别的权限还有⼀些附加的标志,例如,PROTECTION_FLAG_PRIVILEGED,PROTECTION_FLAG_APPOP或者PROTECTION_FLAG_PRE23 等等。
public static final int PROTECTION_FLAG_PRIVILEGED = 0x10;
public static final int PROTECTION_FLAG_DEVELOPMENT = 0x20;
public static final int PROTECTION_FLAG_APPOP = 0x40;
注意:PROTECTION_SIGNATURE_OR_SYSTEM 和PROTECTION_FLAG_SYSTEM已经被弃⽤。
这⾥涵盖了protectionLevel所有可能的取值。
protectionLevel描绘了权限所蕴含的潜在风险,并且指明了系统在赋予某个app请求的权限时所要遵守的规程(procedure)。Android标准的权限有着事先定义好的、固定不变的protectionLevel(事实上,protectionLevel也会变,见pre23相关的说明)。
⾃定义的权限的protectionLevel属性可以取下⾯列表中的‘Constant’值,如果有多个’Constant’值,则需要⽤‘|’分隔开。如果没有定义protectionLevel,则默认权限为normal。
权限级别可以分为两类:基础权限级别和附加权限级别。
基础权限级别
有3种:normal、dangerous和signature。(注:signatureOrSystem处于弃⽤状态,不建议使⽤)
附加权限级别
0x10及其之后的权限级别都属此类,例如,privileged、appop等。它们必须附加在基础权限上。⽬前貌似只能附加在signature权限上。
Constant Value Description
normal 0 normal级别是默认值。低风险的权限采⽤此级别。在app安装的时候,系统⾃动赋予此app请求的所有normal权限,⽽不会征求⽤户的同意(但是,在安装app之前,⽤户总是有权选择检查这些权限)。
dangerous 1 较⾼风险的权限,此级别的权限意味着,请求权限的app将要访问⽤户的隐私数据或者控制设备,这可能给⽤户带来负⾯影响。
因为dangerous权限会引⼊潜在的风险,所以系统不会⾃动赋予此类权限给app。例如,在安装app的时候,会将dangerous权限展⽰给⽤户,并请求⽤户确认。
signature 2 只有请求权限的app与声明权限的app的签名是⼀样的时候,系统才会赋予signature权限。
如果签名⼀致,系统会⾃动赋予权限,⽽不会通知⽤户或者征求⽤户的同意。
signatureOrSystem 3 系统赋予此类权限有2种情况:(1)请求权限的app与声明权限的app的签名⼀致;(2)请求权限的app在Android 系统镜像(system image)中。signatureOrSystem权限主要⽤在这个场景:多个软件供应商的apps预装到了系统⽬录(system/priv-app)中,⽽且这些apps之间会共享⼀些功能。除此之外,尽量不要使⽤此类权限级别。
privileged 0x10 只能与signature同时使⽤。signature|privileged与signatureOrSystem意义相同。Android中system/priv-app⽬录和system/framework⽬录中的app可以访问privileged权限。
system 0x10 意义与privileged相同。注意:由于system的概念会造成混乱,不建议使⽤。system权限并不是system/app⽬录中的app能访问的权限。
development 0x20 development applications可以访问此权限。 Android标准权限中,development是与signature和privileged⼀起⽤的。例如
android:protectionLevel="signature|privileged|development"
appop 0x40 由AppOpsManager来检查app是否访问此类权限。
pre23 0x80 此类权限⾃动被赋予那些targetSdkVersion在22(Android 5.x)或22以下的app。
installer 0x100 此类权限⾃动被赋予负责安装apk的系统app。
verifier 0x200 此类权限⾃动被赋予负责验证apk的系统app。
preinstalled 0x400 此类权限可以⾃动被赋予任何预安装在system image中的app,不只是privileged app。
setup 0x800 此类权限⾃动被赋予‘安装向导’app。
10.1 在l使⽤权限保护组件
通过在l中采⽤⾼保护级别的权限,来保护系统或者app的组件不会被随意访问。实现⽅式是,为组件添加android:permission属性。
Activity 权限(⽤于 <activity> 标记) 限定了哪些app可以启动Activity。权限检查是在 Context.startActivity() 和Activity.startActivityForResult()的时候进⾏的。如果调⽤者没有此权限,则抛出SecurityException异常。
Service 权限(⽤于 <service> 标记) 限定了哪些app可以启动(start)或者绑定(bind)服务。权限检查是在Context.startService(), Context.stopService() 和Context.bindService()的时候进⾏的。如果调⽤者没有此权限,则抛出SecurityException异常。
BroadcastReceiver 权限(⽤于<receiver> 标记) 限定了哪些app可以发送⼴播给receiver。权限检查是在Context.sendBroadcast()返回之后,在系统尝试将⼴播递交给receiver的时候。即使调⽤者没有权限,也不会抛出异常,只是不递送intent(⼴播)给receiver。
同理,在调⽤isterReceiver()的时候,也可以加上权限,来控制谁可以发⼴播给这个动态注册的receiver。也可以在调⽤Context.sendBroadcast()的时候加上权限,来限定哪些BroadcastReceiver 允许接收这个⼴播。
注意,可以同时给receiver(动态或静态receiver)加上权限,并且给Context.sendBroadcast()加上权限,在这种情况下,需要双⽅都验证通过,才能完成信息传递。
注:动态receiver是指isterReceiver()声明的receiver。
静态receiver是指l中<receiver> 声明的receiver。
ContentProvider 权限(⽤于 <provider> 标记) 限定了哪些app可以访问ContentProvider中的数据。与
其他组件不同,ContentProvider有2种权限android:readPermission和android:writePermission,分别控制读和写。
注意:如果provider同时受读权限和写权限保护,调⽤者只拥有写权限,是不能够执⾏读操作的。
在获取provider的时候,会进⾏权限检查。如果没有读权限和写权限,则抛出SecurityException异常。
在操作provider的时候,也会进⾏权限检查。在这⾥操作provider是指增删查改操作,读写⽂件。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。