摘要:PackageManagerService在systemReady()后,进行了/system/etc/permissions中的各种xml进行扫描,进行相应的权限存储,供以后使用
阅读本文大约需要花费15分钟。
文章的内容主要还是从源码进行分析,虽然又臭又长,但是如果想要学习Android系统源码,这是必要走的路,没有捷径。
相对于碎片学习,我更倾向于静下心来花费1个小时认真的学习一段内容。
文章首发微信公众号:IngresGe
专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!
欢迎关注我的公众号!
[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析
[Android取经之路] 系列文章:
《系统启动篇》
- Android系统架构
- Android是怎么启动的
- Android 10.0系统启动之init进程
- Android10.0系统启动之Zygote进程
- Android 10.0 系统启动之SystemServer进程
- Android 10.0 系统服务之ActivityMnagerService
- Android10.0系统启动之Launcher(桌面)启动流程
- Android10.0应用进程创建过程以及Zygote的fork流程
- Android 10.0 PackageManagerService(一)工作原理及启动流程
- Android 10.0 PackageManagerService(二)权限扫描
- Android 10.0 PackageManagerService(三)APK扫描
- Android 10.0 PackageManagerService(四)APK安装流程
《日志系统篇》
- Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
- Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
- Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
- Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现
《PackageManagerService系列文章》
- Android 10.0 PackageManagerService(一)工作原理及启动流程
- Android 10.0 PackageManagerService(二)权限扫描
- Android 10.0 PackageManagerService(三)APK扫描
- Android 10.0 PackageManagerService(四)APK安装流程
《Binder通信原理》
- Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
- Android10.0 Binder通信原理(二)-Binder入门篇
- Android10.0 Binder通信原理(三)-ServiceManager篇
- Android10.0 Binder通信原理(四)-Native-C\C++实例分析
- Android10.0 Binder通信原理(五)-Binder驱动分析
- Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
- Android10.0 Binder通信原理(七)-Framework binder示例
- Android10.0 Binder通信原理(八)-Framework层分析
- Android10.0 Binder通信原理(九)-AIDL Binder示例
- Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
- Android10.0 Binder通信原理(十一)-Binder总结
《HwBinder通信原理》
- HwBinder入门篇-Android10.0 HwBinder通信原理(一)
- HIDL详解-Android10.0 HwBinder通信原理(二)
- HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
- HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
- HwServiceManager篇-Android10.0 HwBinder通信原理(五)
- Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
- Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
- JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
- JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
- HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
- HwBinder原理总结-Android10.0 HwBinder通信原理(十一)
《编译原理》
- 编译系统入门篇-Android10.0编译系统(一)
- 编译环境初始化-Android10.0编译系统(二)
- make编译过程-Android10.0编译系统(三)
- Image打包流程-Android10.0编译系统(四)
- Kati详解-Android10.0编译系统(五)
5 权限扫描
PKMS systemReady()时,通过SystemConfig的readPermissionsFromXml()来扫描读取/system/etc/permissions中的xml文件,包括platform.xml和系统支持的各种硬件模块的feature主要工作:
参考下图:
下面就针对于上述内容,进行分析
5.1 [SystemConfig.java] readPermissions()
说明:扫描/system/etc/permissions中文件,调用
readPermissionsFromXml()进行解析,存入SsytemConfig相应的成员数组变量中
void readPermissions(File libraryDir, int permissionFlag) {
...
// Iterate over the files in the directory and scan .xml files
File platformFile = null;
for (File f : libraryDir.listFiles()) {
if (!f.isFile()) {
continue;
}
// 最后读取platform.xml
if (f.getPath().endsWith("etc/permissions/platform.xml")) {
platformFile = f;
continue;
}
...
readPermissionsFromXml(f, permissionFlag);
}
// Read platform permissions last so it will take precedence
if (platformFile != null) {
readPermissionsFromXml(platformFile, permissionFlag);
}
}
解析xml的标签节点,存入mGlobalGids、mPermissions、mSystemPermissions等成员变量中,供其他进行调用
private void readPermissionsFromXml(File permFile, int permissionFlag) {
FileReader permReader = null;
permReader = new FileReader(permFile);
...
XmlPullParser parser = Xml.newPullParser();
parser.setInput(permReader);
while (true) {
...
String name = parser.getName();
switch (name) {
//解析 group 标签,前面介绍的 XML 文件中没有单独使用该标签的地方
case "group": {
String gidStr = parser.getAttributeValue(null, "gid");
if (gidStr != null) {
int gid = android.os.Process.getGidForName(gidStr);
//转换 XML 中的 gid字符串为整型,并保存到 mGlobalGids 中
mGlobalGids = appendInt(mGlobalGids, gid);
} else {
Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
+ parser.getPositionDescription());
}
...
}break;
case "permission": { //解析 permission 标签
if (allowPermissions) {
String perm = parser.getAttributeValue(null, "name");
if (perm == null) {
Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
+ parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
break;
}
perm = perm.intern();
readPermission(parser, perm); //调用 readPermission 处理,存入mPermissions
} else {
logNotAllowedInPartition(name, permFile, parser);
XmlUtils.skipCurrentTag(parser);
}
} break;
}
}
}
5.2 XML文件
/system/etc/permissions中会存在很多的xml文件,例如我们看下
android.software.webview.xml的文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<feature name="android.software.webview" />
</permissions>
里面只只有一个feature "android.software.webview",大部分的xml都是类似的定义方式。
让我们来简单的看下/system/etc/permissions/platform.xml的内容
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<permission name="android.permission.BLUETOOTH_ADMIN" >
<group gid="net_bt_admin" />
</permission>
<permission name="android.permission.INTERNET" >
<group gid="inet" />
</permission>
<permission name="android.permission.READ_LOGS" >
<group gid="log" />
</permission>
...
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
<assign-permission name="android.permission.WAKE_LOCK" uid="media" />
...
<split-permission name="android.permission.ACCESS_FINE_LOCATION">
<new-permission name="android.permission.ACCESS_COARSE_LOCATION" />
</split-permission>
<split-permission name="android.permission.WRITE_EXTERNAL_STORAGE">
<new-permission name="android.permission.READ_EXTERNAL_STORAGE" />
</split-permission>
<split-permission name="android.permission.READ_CONTACTS"
targetSdk="16">
<new-permission name="android.permission.READ_CALL_LOG" />
</split-permission>
...
<library name="android.test.base"
file="/system/framework/android.test.base.jar" />
<library name="android.test.mock"
file="/system/framework/android.test.mock.jar"
dependency="android.test.base" />
<library name="android.test.runner"
file="/system/framework/android.test.runner.jar"
dependency="android.test.base:android.test.mock" />
<!-- In BOOT_JARS historically, and now added to legacy applications. -->
<library name="android.hidl.base-V1.0-java"
file="/system/framework/android.hidl.base-V1.0-java.jar" />
<library name="android.hidl.manager-V1.0-java"
file="/system/framework/android.hidl.manager-V1.0-java.jar"
dependency="android.hidl.base-V1.0-java" />
...
</permissions>
platform.xml中出现的标签种类则较为多样,它们的含义分别是:
-
<group>:根据name获取gid
-
<permission >标签:把属性name所描述的权限赋予给<group>标签中属性gid所表示的用户组,一个权限可以有一个或多个group对象,当一个APK授权于这个这个权限时,它同时属于这几个组
-
<assign-permission>标签:把属性name所描述的权限赋予给uid属性所表示的用户
-
<split-permission>标签:一个权限可以扩展出一个新的权限
-
<library>标签:除framework中动态库以外的,所有系统会自动加载的动态库
-
<feature>标签:硬件支持的一些feature
-
<oem-permission>标签:oem厂商自己定义的一些权限
-
<privapp-permission>标签:来自system、vendor、product、system_ext的privapp权限分别存储,这是防止供应商分区中的xml授权于系统分区中的私有应用权限
最后将上面xml解析出来的数据做如下存储:
-
<group>标签gid属性的值会存放在mGlobalGids数组中;
-
<permission>标签,解析得到的值会存放在mPermissions集合中;
-
<assign-permission>标签解析得到的值会存放在mSystemPermissions中;
-
<split-permission>存储在mSplitPermissions
-
<library>标签解析得到的值会存放在mSharedLibraries中;
-
<feature>存储在mAvaliableFeatures
-
<oem-permission>存储在mOemPermissions
-
<privapp-permission>会根据不同的存储路径,分别存储在mVendorPrivAppPermissions、mProductPrivAppPermissions、mSystemExtPrivAppPermissions、mPrivAppPermissions
-
下一节将会讲解PKMS 的APK扫描、安装等内容,欢迎关注我
微信公众号:IngresGe