如下代码见PackageManagerService.java:
private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace) {
final PackageSetting ps = (PackageSetting) pkg.mExtras;
if (ps == null) {
return;
}
final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
HashSet<String> origPermissions = gp.grantedPermissions;
boolean changedPermission = false;
if (replace) {
ps.permissionsFixed = false;
if (gp == ps) {
origPermissions = new HashSet<String>(gp.grantedPermissions);
gp.grantedPermissions.clear();
gp.gids = mGlobalGids;
}
}
if (gp.gids == null) {
gp.gids = mGlobalGids;
}
//获取需要授权的权限列表
final int N = pkg.requestedPermissions.size();
for (int i=0; i<N; i++) {
//权限名称
final String name = pkg.requestedPermissions.get(i);
//已获取的权限中是否包含该权限
final boolean required = pkg.requestedPermissionsRequired.get(i);
//由权限名获取封装的工具类BasePermission
final BasePermission bp = mSettings.mPermissions.get(name);
if (DEBUG_INSTALL) {
if (gp != ps) {
Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
}
}
if (bp == null || bp.packageSetting == null) {
Slog.w(TAG, "Unknown permission " + name
+ " in package " + pkg.packageName);
continue;
}
//权限名称
final String perm = bp.name;
boolean allowed;
boolean allowedSig = false;
final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
//PermissionInfo.PROTECTION_NORMAL = 0 ;
//PermissionInfo.PROTECTION_DANGEROUS = 1 ;
//以android.permission.INSTALL_PACKAGES,该权限的protectionLevel = 2,会走else if (level == PermissionInfo.PROTECTION_SIGNATURE)
//的case
if (level == PermissionInfo.PROTECTION_NORMAL
|| level == PermissionInfo.PROTECTION_DANGEROUS) {
// We grant a normal or dangerous permission if any of the following
// are true:
// 1) The permission is required
// 2) The permission is optional, but was granted in the past
// 3) The permission is optional, but was requested by an
// app in /system (not /data)
//
// Otherwise, reject the permission.
//以下4种情况同意申请
allowed = (required || origPermissions.contains(perm)
|| (isSystemApp(ps) && !isUpdatedSystemApp(ps)));
} else if (bp.packageSetting == null) {
// This permission is invalid; skip it.
allowed = false;
//PermissionInfo.PROTECTION_SIGNATURE = 2;
//android.permission.INSTALL_PACKAGES 会走这个case
} else if (level == PermissionInfo.PROTECTION_SIGNATURE) {
allowed = grantSignaturePermission(perm, pkg, bp, origPermissions);
if (allowed) {
allowedSig = true;
}
} else {
allowed = false;
}
if (DEBUG_INSTALL) {
if (gp != ps) {
Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
}
}
//如果同意权限申请则更新权限列表
if (allowed) {
if (!isSystemApp(ps) && ps.permissionsFixed) {
// If this is an existing, non-system package, then
// we can't add any new permissions to it.
if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
// Except... if this is a permission that was added
// to the platform (note: need to only do this when
// updating the platform).
allowed = isNewPlatformPermissionForPackage(perm, pkg);
}
}
if (allowed) {
if (!gp.grantedPermissions.contains(perm)) {
changedPermission = true;
gp.grantedPermissions.add(perm);
gp.gids = appendInts(gp.gids, bp.gids);
} else if (!ps.haveGids) {
gp.gids = appendInts(gp.gids, bp.gids);
}
} else {
Slog.w(TAG, "Not granting permission " + perm
+ " to package " + pkg.packageName
+ " because it was previously installed without");
}
} else {
if (gp.grantedPermissions.remove(perm)) {
changedPermission = true;
gp.gids = removeInts(gp.gids, bp.gids);
Slog.i(TAG, "Un-granting permission " + perm
+ " from package " + pkg.packageName
+ " (protectionLevel=" + bp.protectionLevel
+ " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
+ ")");
} else {
Slog.w(TAG, "Not granting permission " + perm
+ " to package " + pkg.packageName
+ " (protectionLevel=" + bp.protectionLevel
+ " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
+ ")");
}
}
}
另外一个重要方法为:
private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
BasePermission bp, HashSet<String> origPermissions) {
boolean allowed;
//我用自定义签名的apk申请android.permission.INSTALL_PACKAGES,则签名比较是返回为false
allowed = (compareSignatures(
bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
== PackageManager.SIGNATURE_MATCH)
|| (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
== PackageManager.SIGNATURE_MATCH);
Log.d("PM_DEBUG","allowed1 is " + allowed + " for pkg " + pkg.packageName + " permission is " + perm);
//自定义签名apk申请会接着进入下述case
//因为level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE = bp.protectionLevel & 0xf
//所以bp.protectionLevel = 0x0010
//PermissionInfo.PROTECTION_FLAG_SYSTEM = 0x10
if (!allowed && (bp.protectionLevel
& PermissionInfo.PROTECTION_FLAG_SYSTEM) != 0) {
//如果是系统APK判断之前是否有授权
if (isSystemApp(pkg)) {
// For updated system applications, a system permission
// is granted only if it had been defined by the original application.
//如果是升级后的系统APK
if (isUpdatedSystemApp(pkg)) {
final PackageSetting sysPs = mSettings
.getDisabledSystemPkgLPr(pkg.packageName);
final GrantedPermissions origGp = sysPs.sharedUser != null
? sysPs.sharedUser : sysPs;
//判断之前是否有授权
if (origGp.grantedPermissions.contains(perm)) {
// If the original was granted this permission, we take
// that grant decision as read and propagate it to the
// update.
allowed = true;
Log.d("PM_DEBUG","allowed2 is " + allowed + " for pkg " + pkg.packageName + " permission is " + perm);
} else {
// The system apk may have been updated with an older
// version of the one on the data partition, but which
// granted a new system permission that it didn't have
// before. In this case we do want to allow the app to
// now get the new permission if the ancestral apk is
// privileged to get it.
// 若之前无授权则进一步判断是否有特权
////isSystemApp包含system/app 和 system/priv-app 目录下面的APK
if (sysPs.pkg != null && sysPs.isPrivileged()) {
//有特权则判断之前是否有授权
for (int j=0;
j<sysPs.pkg.requestedPermissions.size(); j++) {
if (perm.equals(
sysPs.pkg.requestedPermissions.get(j))) {
allowed = true;
Log.d("PM_DEBUG","allowed3 is " + allowed + " for pkg " + pkg.packageName + " permission is " + perm);
break;
}
}
}
}
} else {
//如果不是升级的系统APK
//isSystemApp包含system/app 和 system/priv-app 目录下面的APK
//只要放在priv-app即是isPrivilegedApp
allowed = isPrivilegedApp(pkg);
Log.d("PM_DEBUG","allowed4 is " + allowed + " for pkg " + pkg.packageName + " permission is " + perm);
}
}
}
if (!allowed && (bp.protectionLevel
& PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
// For development permissions, a development permission
// is granted only if it was already granted.
allowed = origPermissions.contains(perm);
Log.d("PM_DEBUG","allowed5 is " + allowed + " for pkg " + pkg.packageName + " permission is " + perm);
}
return allowed;
}
以上,当我们的apk需要特殊权限时如:android.permission.INSTALL_PACKAGES时可以将其放置在
system/priv-app 目录下即可绕过系统签名的限制。
其他的权限我们在grantSignaturePermission函数中做一些workaround也可以绕过签名的限制。