前言
apk安装分4种方式:
- 系统开机应用安装,安装的是系统应用。
- adb安装
- 应用调用系统应用安装第三方apk包
- 静默安装
在代码里的实现其实就是如下两种:
- PMS调用scanDirLI扫描安装
- 直接或间接调用installPackageAsUser安装,这个8.0下其实调用的是另一个函数
apk安装后主要体现在:
data/app:apk包-含优化后的oat与lib
data/data:数据目录
在本篇我们看下第一种系统启动时的安装流程。下一篇介绍第二种
分析
一张时序图:
介于大小问题图中执行长度不做对应。
dex的优化:
在SystemServer.java 中有mPackageManagerService.updatePackagesIfNeeded()
updatePackagesIfNeeded->performDexOptUpgrade->performDexOptTraced->performDexOptInternal->performDexOptInternalWithDependenciesLI->PackageDexOptimizer.performDexOpt->performDexOptLI->dexOptPath->Installer.dexopt->InstalldNativeService.dexopt->dexopt.dexopt
1.main
ZygoteInit fork启动SystemServer
frameworks\base\services\java\com\android\server\SystemServer.java
SystemServer.main
|
|
构建运行其run
2.run
SystemServer.run
参数设置,启动各主要服务,启动循环处理服务。
3.startBootstrapServices
SystemServer.startBootstrapServices
|
|
启动了一系列服务。其中Installer用binder与installd原生服务通话。
其中一个服务:PackageManagerService.main
4.PackageManagerService.main
frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java
|
|
构建PackageManagerService对象。添加到ServiceManager中。
5.PackageManagerService
构建函数PackageManagerService:
|
|
用scanDirTracedLI扫描几个目录:
- /system/framework
- /system/app
- /system/priv-app
- /vendor/app
- /data/app
- /data/app-private
6.scanDirTracedLI
PackageManagerService.scanDirTracedLI:
|
|
构建ParallelPackageParser对象,遍历目录文件,调用parallelPackageParser.submit解析,用scanPackageLI函数来对它进行更新解析和安装。
8.submit
parallelPackageParser.submit:
frameworks\base\services\core\java\com\android\server\pm\ParallelPackageParser.java
|
|
构建结果对象ParseResult pr = new ParseResult();
构建包解析器PackageParser pp = new PackageParser();的parsePackage方法对其解析,解析结果为PackageParser.Package存入pr.pkg将pr放入队列
12.parsePackage
PackageParser.parsePackage: 此后方法都是解析器的
frameworks\base\core\java\android\content\pm\PackageParser.java
|
|
构建资源res = new Resources(assets, mMetrics, null); 构建xml解析器XmlResourceParser
进一步分类解析apk,调用到关键函数:
final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);解析AndroidMainifest.xml
16.parseBaseApk
PackageParser.parseBaseApk
解析AndroidMainifest的工作主要在这里
9.scanPackageLI
PackageManagerService.scanDirLI最后调用这个安装apk,之前是xml的解析
PackageManagerService.scanPackageLI
frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java
|
|
调用scanPackageInternalLI更新解析包。
该函数扫描并返回新的解析过的包。
11.scanPackageInternalLI
PackageManagerService.scanPackageInternalLI
scanPackageInternalLI方法是把扫描到的androidmainifest数据和之前在手机内扫描得到的数据做对比,然后进行pkg的进一步设置。返回新的包.
最后调用:
13.scanPackageLI
参数5且首为package的scanPackageLI
|
|
调用scanPackageDirtyLI(pkg, policyFlags, scanFlags,currentTime, user);安装
参数为:解析好的pkg安装包信息。俩个Flags。当前时间
15.scanPackageDirtyLI
PackageManagerService.scanPackageDirtyLI:
|
|
不论是开机扫描安装APK,还是通过adb命令安装APK,最终都会调用scanPackageDirtyLI函数进行APK安装。
- 初始化Package的数据目录和资源目录;
- 如果需要则更新已有的Package的共享代码库;
- 如果安装时传递了签名信息,则验证签名信息的合法性;
- 验证新安装的APK中的Provider是否与系统中现有的Provider有冲突,并进行相应的处理;
- 如果新安装APK需要使用其他Package的权限,则进行相应处理;
- 调用createDataDirsLI()安装APK;
- 设置本地lib路径;
- 安装成功之后将Package信息更新到PMS和Setting相应的数据结构中;
- 设置APK安装时间;
- 设置APK的Provider信息,将Provider添加到相应的数据结构中;
- 设置权限组和权限信息;
- 该函数的主要工作便是将安装的APK的信息添加到PMS中,比如讲Provider、Activity、Service、Receiver等组件信息添加到相应的数据结构中,以便其他函数能够查询到