之前不明白为什么权限白名单不生效,现在通过分析系统加载流程,得到了答案
以前在android 8.1的时候,直接在privapp-permissions-mediatek.xml 里添加对应app想要的运行时权限就可以了,但是在另外的项目里发现即使写了权限白名单也没用。 从device/mediatek/common/device.mk 里看到
PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,vendor/mediatek/proprietary/frameworks/base/data/etc/privapp-permissions-mediatek.xml:system/etc/permissions/privapp-permissions-mediatek.xml)
PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,vendor/mediatek/proprietary/frameworks/base/data/etc/system-ext-permissions-mediatek.xml:$(TARGET_COPY_OUT_SYSTEM_EXT)/etc/permissions/system-ext-permissions-mediatek.xml)
PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,vendor/mediatek/proprietary/frameworks/base/data/etc/product-permissions-mediatek.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/permissions/product-permissions-mediatek.xml)
privapp-permissions-mediatek.xml system-ext-permissions-mediatek.xml product-permissions-mediatek.xml 这三个文件都被内置到etc目录下 然后他们的内容也都是写的权限白名单,而且有相同的包名,也就是说有重复或者覆盖的可能。 分析系统流程发现
PermissionManagerService.java 里
SystemConfig systemConfig = SystemConfig.getInstance();
public static SystemConfig getInstance() {
synchronized (SystemConfig.class) {
if (sInstance == null) {
sInstance = new SystemConfig();
}
return sInstance;
}
}
SystemConfig() {
try {
readAllPermissions();
} finally {
log.traceEnd();
}
}
private void readAllPermissions() {
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
readPermissions(Environment.buildPath(
Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
}
会把 system vendor product odm systemext 目录下的permission xml文件全都解析出来
case "privapp-permissions": {
if (allowPrivappPermissions) {
boolean vendor = permFile.toPath().startsWith(
Environment.getVendorDirectory().toPath() + "/")
|| permFile.toPath().startsWith(
Environment.getOdmDirectory().toPath() + "/");
boolean product = permFile.toPath().startsWith(
Environment.getProductDirectory().toPath() + "/");
boolean systemExt = permFile.toPath().startsWith(
Environment.getSystemExtDirectory().toPath() + "/");
if (vendor) {
readPrivAppPermissions(parser, mVendorPrivAppPermissions,
mVendorPrivAppDenyPermissions);
} else if (product) {
readPrivAppPermissions(parser, mProductPrivAppPermissions,
mProductPrivAppDenyPermissions);
} else if (systemExt) {
readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
mSystemExtPrivAppDenyPermissions);
} else {
readPrivAppPermissions(parser, mPrivAppPermissions,
mPrivAppDenyPermissions);
}
} else {
logNotAllowedInPartition(name, permFile, parser);
XmlUtils.skipCurrentTag(parser);
}
} break;
再然后根据app的属性来决定加载哪个xml文件, 如果编译的时候编译app到 systemext 目录,那么加载的就会是system-ext-permissions-mediatek.xml 里面的白名单权限。 这样一来,我们如果写的不是这个文件里,就不会生效。
白名单权限授权过程
PermissionManagerService
public void onNewUserCreated(int userId)
private void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated,
@NonNull PermissionCallback callback)
private void updatePermissions(final @Nullable String changingPkgName,
final @Nullable AndroidPackage changingPkg,
final @Nullable String replaceVolumeUuid,
@UpdatePermissionFlags int flags,
final @Nullable PermissionCallback callback)
private void restorePermissionState(@NonNull AndroidPackage pkg, boolean replace,
@Nullable String packageOfInterest, @Nullable PermissionCallback callback)
{
...
if (bp.isSignature()) {
allowedSig = grantSignaturePermission(perm, pkg, ps, bp, origPermissions);
if (allowedSig) {
grant = GRANT_INSTALL;
}
}
...
}
起决定作用的就是这里是否能找到白名单权限hasPrivappWhitelistEntry
private boolean hasPrivappWhitelistEntry(String perm, AndroidPackage pkg) {
ArraySet<String> wlPermissions;
if (pkg.isVendor()) {
wlPermissions =SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.getPackageName());
} else if (pkg.isProduct()) {
wlPermissions=SystemConfig.getInstance().getProductPrivAppPermissions(pkg.getPackageName());
} else if (pkg.isSystemExt()) {
wlPermissions =SystemConfig.getInstance().getSystemExtPrivAppPermissions(
pkg.getPackageName());
} else {
wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.getPackageName());
}
return wlPermissions != null && wlPermissions.contains(perm);
}
而SystemConfig.getInstance().getPrivAppPermissions 获取的权限名单列表,就是开机加载的白名单列表。
总结:
权限白名单可以使系统app开机即可获取运行时权限,因为在开机过程中会去检测权限是否有白名单,而对应的白名单会根据app编译的路径而做不同的更改。 例如:Launcher的makefile里添加了LOCAL_SYSTEM_EXT_MODULE := true ,所以编译的结果会是Launcher被编译到了system\system_ext 路径下,而对应的白名单权限,就会去加载system-ext-permissions-mediatek.xml 这个文件里的列表。
|