1.前言
当我们安装应用程序的时候,会弹出安装界面,那么,在我们点击安装之后,发生了什么呢?今天就来了解下,应用程序是如何安装的。首先,我们今天介绍的是通过安装器安装应用,当然,在pms的构造函数中,也会将我们原先安装好的应用装载到内存中。
以6.0源码为例。安装器在源码目录packages/apps/PackageInstaller中,
2.安装器
显示安装 取消按钮的那个界面对应着PackageInstallerActivity,而安装按钮对应的是mOk,对应部分代码。
|
|
虽然,我不知懂这里的mSessionId是什么含义,但是 根据代码能看出,安装一个应用应该是startInstall方法。在这个方法中,最终会去玩InstallAppProgress这个界面,对应我们安装中进度条显示的界面。有如下代码。
|
|
- mPackageURI,安装应用的话,应该是file
- pm 为ApplicationPackageManager
因此,我们看installPackageWithVerificationAndEncryption方法。
3.ApplicationPackageManager#installPackageWithVerificationAndEncryption
在这个方法中,会调用installCommon方法,而installCommon方法中,会进行简单的参数校验,然后调用mPM的installPackage方法去安装。这个mPM参数实在构造的时候传入的。是通过ActivityThread.getPackageManager()获取。
|
|
从中可以看出,其binder服务端为PackageManagerService.
4.PackageManagerService#installPackage
在这个方法中,回调用installPackageAsUser方法。在这个方法中,会发送一个消息,执行安装过程的第一个阶段,copy
|
|
这里的mHandler为PackageHandler实例对象,其消息处理部分代码在doHandleMessage中,我们看INIT_COPY,做了什么?
|
|
如果没有绑定,就绑定,如果绑定了,将HandlerParams加入到mPendingInstalls中,并且如果以前为空,则发送MCS_BOUND这个空消息。
在接受到MCS_BOUND这个消息之后,会循环处理并且再次发送MCS_BOUND消息,
|
|
从上诉代码中,我们就能知道,通过params.startCopy()去执行copy操作,并且如果还有未安装的,会重复发这个消息,知道所有都安装成功。
5.HandlerParams#startCopy
|
|
这里有重试机制。而handleStartCopy的实现在InstallParams中。
6.InstallParams#handleStartCopy
这个方法比较长,分段来看。
|
|
首先,如果需要的空间不够大,就调用Install的freeCache去释放一部分缓存。
这里的mContainerService对应的binder服务端实现,在DefaultContainerService中。
中间经过复杂的判断处理之后,创建一个InstallArgs对象,如果前面的判断结果是能安装成功的话,进入分支。
|
|
- 如果启动了包验证的话,就会进入验证阶段。
- 发送有序广播,
- 否则,直接进行复制操作
验证部分的逻辑很长,大部分代码都是对intent进行设置。
7.InstallArgs#copyApk
在createInstallArgs中,会根据InstallParams创建不同的InstallArgs对象。
|
|
以FileInstallArgs为例,我们来看看。
|
|
- 首先mInstallerService.allocateStageDirLegacy申请足够的存储空间
- 得到申请的那部分空间的文件描述符,并且修改权限
- IMediaContainerService#copyPackage 拷贝到指定目录,实现在DefaultContainerService中,
- NativeLibraryHelper#copyNativeBinariesWithOverride 拷贝二进制文件(so库)
8.DefaultContainerService#copyPackage
|
|
- 解析apk文件
- 将文件拷贝到指定目录
9.NativeLibraryHelper#copyNativeBinariesWithOverride
在这个方法中,将不同的so库通过copyNativeBinariesForSupportedAbi方法copy到不同的目录。copy的具体流程就不说了。
到现在,copy的流程就完了。
在上面startCopy中,下面有handleReturnCode,是对copy后进行后续处理的,我们依然看,InstallParams的这个方法。
10.InstallParams#handleReturnCode
在这个方法中,会调用processPendingInstall去处理。
|
|
安装过程
- installPackageLI,在这个之前,会用doPreInstall进行cleanup操作,在这之后会用doPostInstall进行clean操作。
- 恢复部分代码 没看明白。😭
- 发送POST_INSTALL消息
11.installPackageLI
改方法氛围几部分。
首先是解析包过程。
|
|
其次是校验签名的md5的过程
|
|
调用installNewPackageLI安装。
12.installNewPackageLI
在这个方法中,调用scanPackageDirtyLI进行扫描,而在scanPackageDirtyLI中,经过复杂的操作之后就算完成了安装,诸如,创建用户数据目录,进行dex优化等等。
13.处理POST_INSTALL消息
略。