查看原文
其他

Android 10.0 PackageManagerService(二)权限扫描-[Android取经之路]

IngresGe IngresGe 2021-11-05

阅读本文大约需要花费15分钟。

文章的内容主要还是从源码进行分析,虽然又臭又长,但是如果想要学习Android系统源码,这是必要走的路,没有捷径。

相对于碎片学习,我更倾向于静下心来花费1个小时认真的学习一段内容。


系列文章:

Android取经之路——启动篇

Android系统架构-[Android取经之路]

Android是怎么启动的-[Android取经之路]

Android系统启动之init进程(一)-「Android取经之路」

Android系统启动之init进程(二)-「Android取经之路」

Android 10.0系统启动之init进程(三)-「Android取经之路」

Android 10.0系统启动之init进程(四)-「Android取经之路」

Android 10.0系统启动之Zygote进程(一)-「Android取经之路」

Android 10.0系统启动之Zygote进程(二)-「Android取经之路」

Android 10.0系统启动之Zygote进程(三)-「Android取经之路」

Android 10.0系统启动之Zygote进程(四)-「Android取经之路」

Android 10.0系统启动之SystemServer进程(一)-「Android取经之路」

Android 10.0系统启动之SystemServer进程(二)-「Android取经之路

Android 10.0系统服务之AMS启动流程-「Android取经之路」

Android10.0系统启动之Launcher(桌面)启动流程-[Android取经之路]

Android10.0应用进程创建过程以及Zygote的fork流程-[Android取经之路]

Android 10.0 PackageManagerService(一)工作原理及启动流程-[Android取经之路]


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


: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存