Jimmy Chen

A Programmer

(原创)基于Android 8.1之PackageInstaller源码分析(三)

  上一篇我们讲到在PackageInstallerSession的commitLocked方法中,我们最后调用了PackageManagerService的installStage方法。这里我们直接从

PackageManagerService.java

installStage

  上面的代码中,在最后我们向mHandler发送了INIT_COPY,接下来我们分析mHandler是如何处理INIT_COPY的。

mHandler处理INIT_COPY

  首先在PackageManagerService初始化的时候有初始化mHandler:mHandler = new PackageHandler(mHandlerThread.getLooper());,所以这里直接查看PackageHandler相关代码。

  mBound是用来标记是否已经绑定到DefaultContainerService服务,mBound的默认值是false,表示默认没有绑定到DefaultContainerService。


connectToService

  这里bindServiceAsUser和应用层调用bindService是一样的,当传递BIND_AUTO_CREATE后会立刻调用mDefContainerConn的onServiceConnected方法。


DefaultContainerConnection

  在onServiceConnected中,首先获取到IMediaContainerService的服务对象,然后再将该imcs服务对象附加到MCS_BOUND类型的Message中,最后再发送出去。这里再一次通过mHandler来处理数据,接下来我们分析mHandler是如何处理MCS_BOUND类型的消息的。


mHandler处理MCS_BOUND消息

  上面的代码都比较容易理解,我们接着分析关键部分startCopy的代码。


startCopy

  这里主要有handleStartCopy和handleReturnCode来完成所有的工作。


handleStartCopy

  这上面的代码内容很多,这里尽量对其中一些函数做分析。

1. handleStartCopy -> getMinimalPackageInfo

  这里对最终的安装路径感兴趣,所以继续最终下去,接着看resolveInstallLocation的代码

1.1 getMinimalPackageInfo -> resolveInstallLocation

  上面显示了安装路径的确认过程。现在我们再次返回handleStartCopy方法中,接着我们分析handleStartCopy方法中的createInstallArgs方法。这个方法会根据安装路径来创建不同的参数对象,源码如下

2. handleStartCopy -> createInstallArgs

  InstallArgs是一个抽象类,定义了应用的安装逻辑。MoveInstallArgs、AsecInstallArgs和FileInstallArgs三个类都是InstallArgs的子类。这里确认使用FileInstallArgs,所以我们接着回到handleStartCopy方法中,分析args.copyApk方法。args表示的就是一个FileInstallArgs对象,所以这里调用的是FileInstallArgs的copyApk方法。


FileInstallArgs.copyApk

  上面调用DefaultContainerService的copyPackage方法进行Package的复制操作,所以我们看看copyPackage完成什么操作。

doCopyApk -> copyPackage

  handleStartCopy的所有流程到这里就结束了,接着我们返回到最前面的startCopy函数处,还有一个方法调用没有解析,那就是handleReturnCode方法了,接下来让我们继续go on


handleReturnCode

  这上面的mArgs是一个FileInstallArgs对象,代表一个安装参数对象。

processPendingInstall

安装前处理doPreInstall

  这里有个疑问就是,在执行doPreInstall前就已经判断过status是否为PackageManager.INSTALL_SUCCEEDED,只有status等于PackageManager.INSTALL_SUCCEEDED才会执行doPreInstall操作。为什么在doPreInstall里面还要多此一举呢?这里估计res.returnCode这个返回值是可以在多处被修改的,所以可能在整个安装过程中这个值被修改了,例如在此之前可能还在执行正常的安装,但是到执行doPreInstall的时候,用户突然点击了Cancel按钮。

安装实际操作 installPackageTracedLI

  这一段代码比较长,博主能看懂能解释的都尽量解释了。因为我们这里假设的是安装过程,所以我们接下来看安装应用调用的方法installNewPackageLIF。

installPackageLI -> installNewPackageLIF

  最后我们还有一个POST_INSTALL消息还没处理,接下来我们查看POST_INSTALL消息是如何处理的

POST_INSTALL消息处理

  handlePackagePostInstall是我们需要分析的最后一个函数了,再坚持一下把它看完吧。

handlePackagePostInstall

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注