PKMS知识点梳理

参考1:http://blog.csdn.net/gaugamela/article/details/52637814#comments

参考2:《深入理解Android卷Ⅱ》邓凡平

一、PKMS的启动、main函数


二、构造函数部分

1、PKMS中的Settings


PKMS知识点梳理_第1张图片

Setting相关结构

PKMS中定义了Settings对象

final Settings mSettings;


Settings中有mOtherUsers、mUserIds和mSharedUsers成员。

final ArrayMap mSharedUsers = new ArrayMap();//以字符串(如android.uid.system)为key,利用名称作为索引管理SharedUserSettings对象
private final ArrayList mUserIds = new AarrayList();
mUserIds.set(index, obj);//普通APK的uid作为ArrayList的下标
private final SparseArray mOtherUserIds = new SparseArray();
mOtherUserIds.put(uid, obj);//系统APK的uid为key


PKMS知识点梳理_第2张图片

SharedUserSetting相关类图

如上图所示,Settings对象中持有多个SharedUserSettings对象,每个SharedUserSettings对象由会持有多个PackageSettings对象。从继承关系来看,SharedUserSettings和PackageSettings对象,最终都将继承SettingsBase对象。

从图上可以看出,SettingsBase对象持有PermissionsState对象,用于表示可用的权限。因此,SharedUserSettings对象和PackageSettings对象中都将包含有PermissionsState。可以据此推测出,SharedUserSettings中持有的是一组Package共有的权限;PackageSettings中持有的是单个Package独有的权限。

2、读取XML文件中的系统配置信息

创建SystemConfig对象,在SystemConfig构造函数中会通过readPermissions函数读取system/etc/permissions(或者odm/etc/permisions, oem/etc/permissions)目录下的权限配置文件中的信息,首先会读取platform.xml,platform.xml主要作用是:


*permission和group字段用于建立Linux层GID和Android层permission字段之间的映射关系;

*assign-permission用于向指定的uid赋予相应的权限,这个权限由Android定义,用字符串表示;

*library字段用于可链接的指定系统库,当应用程序运行时,系统会自动为这些进程加载这些库;

*allow-in-power:省电模式可访问网络

*allow-in-data-usage-save:省流量模式仍可访问网络

*allow-in-power-save-except-idle用于指定进程在省电模式下(非Idle)仍可上网

*system-user-whitelisted-app:指定以system user权限运行的App

*system-user-blacklisted-app:指定在system user权限下不运行的App

*backup-transport-whitelisted-service用于指定服务具有传输备份数据的权利


随后会读取其他xml文件,feature标签,用于描述一个手持终端(手机、平板等)应该支持的硬件特性,例如支持camera、支持蓝牙等。

readPermissions函数就是将xml文件中的标签转换成对应的数据结构,此处重要的是理解各种标签的作用。PKMS创建的SystemConfig负责解析系统的xml配置文件,最终将形成上图所示的数据结构(列举了主要数据)。在此之后,PKMS取出并保存了SystemConfig中的权限和feature等信息。

3、加载签名策略

mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();


解析system/etc/security/mac_permissions.xml(源码路径system/sepolicy/mac_permissions.xml,编译后copy到system/etc/security/mac_permissions.xml)读出相应的签名策略,根据mac_permissions.xml的定义,如果App是在Android源码编译环境下,其Android.mk中指定了LOCAL_CERTIFICATE : = platform的话,它的 seinfo就是platform。如果Android.mk中不进行对应的设置,setinfo为默认值default。对于第三方APK,其seinfo值通常为default。

4、扫描Package

4.1 系统库的dex优化,处理系统升级相关问题

对platform.xml中定义的链接库文件进行dex优化。

    
    
    
    ..........

4.2 扫描目标目录下的Package

利用scanDirTracedLI扫描vendor/overlay、system/framework、system/priv-app、system/app、vendor/app、oem/app等目录,传入的parseFlag不一样。

void scanDirTracedLI(File dir, final int parseFlags, int scanFlags, long currentTime)——>

void scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime)——>

PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags, ing scanFlags, long currentTime, UserHandle user)【处理目录下每一个package文件,返回值是PackageParser的内部类Package,该类的实例代表一个apk,所以就是和APK文件对应的数据结构】——>

PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scan Flags, long currentTime, UserHandle user)——>

----(1)PackageParser.parsePackage(File packageFile, int flags)【解析Apk Manifest.xml,完成从物理文件到数据结构的转换,返回一个Package对象】——>

--------(a)PackageParser.parseClusterPackage(File packageDir, int flags)【解析多APK】——>

------------①PackageLite parseClusterPackageLite(File packageDir, int flags)——>

----------------ApkLite parseApkLite(File apkFile, int flags)【执行实际的parse工作,本质是获取AndroidManifest.xml对应的XML资源解析器,解析出其中部分属性,然后形成ApkLite对象返回】——>

----------------return new PackageLite(codePath, baseApk, splitNames, splitCodePaths, splitRevisionCodes)【构造出PackageLite并返回】——>

------------②loadApkIntoAssetManager(assets, lite.baseCodePath, flags);【将APK的一些信息放入资源管理器中】

------------③final Package pkg = parseBaseApk(baseApk, assets, flags);【解析主要APK信息,构造Package对象,然后解析AndroidManifest.xml中的标签,形成对应的数据结构

----------------final Package pkg = parseBaseApk(res, parser, flags, outError);

--------------------return parseBaseApkCommon(pkg, null, res, parser, flags, outError);【解析结果保存在Package对象】

------------④parseSplitApk(pkg, i, assets, flags);【和parseBaseApk内容差不多】

--------parseClusterPackage的主要内容,实际上就是解析出Package对应的数据结构。 代码看起来相当繁琐,但实际思想确实很简单的,无非就是解析AndroidManifest.xml对应的标签项,然后形成对应的数据结构插入到Package中。 前面提到过parseClusterPackage是用于解析存在多个APK文件的Package,parseMonolithicPackage用于解析单个APK文件的Package。 实际上parseMonolithicPackage就是靠parseBaseApk函数完成解析工作的,是parseClusterPackage函数对应工作的一个子集。

--------(b)PacakgeParser.parseMonolithicPackage(File apkFile, int flags)【解析单个APK】

----(2)return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user)——>

--------(a)PackageParser.Package scannedPkg = scanPackageInternalLI(pkg, scanFile, PolicyFlags, scanFlags, currentTime, user)——>

------------PackageParser.Package scannedPkg = scanPackageLI(pkg, policyFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user);——>

----------------final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags, currentTime, user);【这里才是实际的解析函数】——>

----------------scanPackageDirtyLI()函数中单独处理了包名为“android”的package,对应的APK为framework-res.apk,此apk包含了两个重要的常用的Activity,即ChooserActivity(当多个Activity符合某个Internt的时候,系统会弹出Activity,由用户选择合适的应用来处理),ShutdownActivity(长安电源键关机时弹出的系统对话框);处理Native库和CPU API这些东西,看不太明白;处理系统APK更新时链接库的改变;将Package中的信息加入到了PKMS的Settings对象中,在此之前四大组件的信息都属于Package的私有财产,现在统一注册到PKMS中,于是PKMS就可以对外提供统一的组件了;解析非系统Apk的AndroidManifest.xml,形成对应的Package信息加入到PKMS中。


三、APK安装




你可能感兴趣的:(android开发学习,Android,Frameworks)