Android程序包管理(2)--使用adb install执行安装过程

2、程序安装过程
1.使用adb install执行安装过程
使用adb install执行安装过程总体流程图以下:shell

1、使用adb install命令安装apkapp

1.adb指令对应源文件system/core/adb/commandline.c。异步

2.指令参数解析:根据传入参数install判断是安装指令,直接调用到install_app();函数

3.执行文件拷贝:在install_app()中:ui

首先定义两个拷贝位置:分别对应拷贝到内部或者外部存储。这里须要根据传入参数肯定拷贝位置。默认是拷贝到内部存储中。this

执行拷贝:将制定的apk文件从电脑端拷贝到制定的目录处。.net

执行安装:调用pm_command()函数开始去安装。code

删除文件:当安装结束时删除该apk文件。server

4.开始去安装:在pm_command()中:对象

构造shell指令:将参数凭借成为shell指令。

去执行shell:使用send_shellcommand()去执行pm脚本,使用app_process运行pm.jar。

2、跨进程去执行安装

1.执行前准备:

获取Binder:首先获取PKMS对应的Binde对象。

解析传入参数:判断是install指令肯定是安装指令。调用runinstall()。

2.准备跨进程安装:在runinstall()中:

解析参数:while循环依次解析参数肯定installFlags,接着获取apk文件路径构造apkURI经过它读取文件。

跨进程调用:首先新建PackageInstallObserver回调接收PKMS安装结果,而后使用mPm.installPackageWithVerificationAndEncryption()跨进程调用到PKMS该函数执行。

等待安装结果:循环判断PackageInstallObserver.finished状态,等待安装结果根据结果提示用户信息。

3、PKMS执行具体安装

1.执行安装准备工做:在installPackageWithVerificationAndEncryption()中:

检查权限:首先检查调用者进程是否存在安装应用的权限。

获取uid,设置filteredFlags:获取调用者uid根据uid作后续判断。若是uid是SHELL_UID为filteredFlags设置INSTALL_FROM_ADB表示不然取消该表示,这里是须要设置该标识。

发生异步消息:获取INIT_COPY标识的Message对象,设置obj为新建对象InstallParams,该对象分装了安装须要的参数及信息。而后发送该Message。

InstallParams类图关系以下: 


2.执行异步消息:在PackageHandler中:

处理消息:异步消息都会调用doHandleMessage()处理具体逻辑。

判断在INIT_COPY标识下:

首先获取安装请求对象:obj即HandlerParams的子类InstallParams。

判断是否启动服务:mBound表示是否启动DefaultContainerService服务,该服务由DefaultContainerService.apk提供,主要做用是拷贝文件到应用程序目录。若是已启动则将该安装请求对象添加到队列mPendingInstalls中该队列若是为空则发生消息MCS_BOUND执行安装。若是未启动调用connectToService()启动该服务。

判断在MCS_BOUND标识下:该标识在DefaultContainerService启动成功后也会回调。

获取mContainerService对象:若是是DefaultContainerService启动成功后的回调,直接获取obj即为该对象。判断mContainerService是否为空,若是为空表明DefaultContainerService服务未启动不能执行安装操做,不为空判断若是mPendingInstalls队列存在请求则开始执行。

获取安装请求:使用mPendingInstalls.get(0)获取一个待安装请求HandlerParams。

执行安装请求:调用该HandlerParams.startCopy()函数,判断函数返回结果,返回为true表明处理成功。

请求处理成功:请求处理成功时,首先从mPendingInstalls队列中移除该请求,若是mPendingInstalls队列此时大小为0表明全部请求已完成则回调MCS_UNBIND断开服务。若是还存在请求则继续回调MCS_BOUND消息执行安装请求。

3.执行安装请求逻辑:HandlerParams.startCopy()中:

尝试次数判断:安装请求执行失败后有重试机制。判断mRetries是否大于最大尝试次数,超过最大次数发生异步消息MCS_GIVE_UP放弃执行返回false。未超过则执行安装行为。

执行拷贝操做:调用handleStartCopy()执行拷贝请求,具体是实如今InstallParams中。

执行安装操做:调用handleReturnCode()执行安装请求,具体是实如今InstallParams中。

4.执行apk的拷贝:在HandlerParams.handleStartCopy()中:

获取指定的安装位置:首先从flags中获取指定的安装位置,这里的flags来自于以前解析参数传入的filteredFlags。判断若是同时指定既在sd卡安装又在内部存储安装则赋值ret安装失败。

获取手机存储情况:经过dsm服务调用getMemoryLowThreshold()获取当前内部存储最小余量。小于这个值就是空间不足。

授予apk读取权限:授予DefContainerService URI读权限,使其能够执行apk的拷贝操做。

获取PackageInfoLite对象并判断:首先获取待安装apk的packageFile对象,根据该对象调用mContainerService.getMinimalPackageInfo()获取其对应的PackageInfoLite对象,该对象描述apk的包名、版本、推荐安装位置、签名等信息。而后判断该apk的安装推荐位置是RECOMMEND_FAILED_INSUFFICIENT_STORAGE表明当前存储空间不足须要释放空间,计算该apk安装须要的空间而后使用mInstaller.freeCache()释放空间,以后在尝试获取一次PackageInfoLite对象。

撤销apk读取权限:撤销对uri的读取权限mContext.revokeUriPermission()。

肯定最终安装的位置:根据pkgLite.recommendedInstallLocation肯定ret值,而且最终肯定安装位置sd卡或者是内部存储,并设置flags值。

新建安装参数对象InstallArgs:调用createInstallArgs(this)建立一个安装参数对象,根据flag对安装位置区别处理。这里若是是安装在sd卡上返回AsecInstallArgs对象,反之是FileInstallArgs对象。它们都继承自InstallArgs。注意这里构造的时候传入的是当前的安装请求对象HandlerParams,该对象分装了此次请求须要的全部信息参数。

判断一系列验证检查:若是设置了包验证开启,则收集信息发送广播给包校验器检查,检查经过才能接着进行安装。若是未设置则直接调用安装参数对象InstallArgs.copyApk()执行拷贝apk。

5.具体开始执行apk的拷贝操做:在InstallArgs.copyApk()中,假设安装位置在内部存储则该方法具体实如今FileInstallArgs中:

判断temp:temp表明拷贝到/data/app下的文件名是否须要随机,这里咱们传入的true是要随机,由于若是不随机以apk结尾,PKMS会监听到该文件以后直接执行安装操做,咱们不须要直接进行该安装操做,因此设置随机名。

执行apk拷贝操做:首先获取建立apk对应File对象codeFile,为DCM服务受权读取权限。接着使用imcs.copyResource()拷贝资源到codeFile文件。同时为该apk建立native目录而且拷贝native库到该位置。最后返回安装结果ret。

至此安装操做完成HandlerParams.handleStartCopy()执行完毕赋值安装结果给mRet变量。

6.拷贝完成执行安装操做:在HandlerParams.handleReturnCode()中:

判断安装参数对象InstallArgs:首先判断InstallArgs对象若是不为null则开始执行安装流程,调用processPendingInstall()。安装结束以后删除临时文件,若是未开启包验证则该文件不存在不须要删除。

执行安装操做:使用Hanlder发布异步任务,新建安装结果对象PackageInstalledInfo,接着调用installPackageLI()执行安装操做,传入安装参数对象InstallArgs及PackageInstalledInfo获取安装结果。安装完成以后新建对象PostInstallData分装InstallArgs及PackageInstalledInfo而后放入mRunningInstalls这个map中,新建一个token为索引。最后发生一个异步消息POST_INSTALL并携带索引token,通知安装结果。

7.安装完成执行通知操做:在PackageHandler中:

判断在POST_INSTALL标识下:

获取安装结果对象:在mRunningInstalls中根据token获取安装结果PostInstallData。若是存在则分别取出对应的InstallArgs和PackageInstalledInfo。

处理安装成功状况:判断PackageInstalledInfo.returnCode是安装成功,首先发送安装成功广播ACTION_PACKAGE_ADDED,若是是应用更新操做还要发送ACTION_PACKAGE_REPLACED广播。而后进行资源清理,接着取出InstallArgs.observer不为空表明存在安装结果回调对象,则回调其对应结果。

至此adb install安装程序流程完成。

简单总结流程:

将电脑端apk资源拷贝到制定的临时文件夹下。

将apk拷贝到/data/app目录下,可是文件名须要随机处理。

调用PKMS函数执行apk安装。

相关文章
相关标签/搜索