1、应用程序安装基础
- 单个APK程序安装的过程
- 把原始的APk文件复制到程序相应的目录文件下,对于第三方app复制到/data/app/目录下
- 为程序创建相应的数据目录、提取dex文件、修改系统包管理信息
- 程序安装过程
- 在程序目录下创建以包名称命名的程序apk文件File
- 在data/data/目录下创建应用程序的数据文件
- 将程序所有的信息写入到配置文件package.xml文件中
- HandlerParams主要实现子类
- InstallParams:完成要安装程序的Copy工作
- MoveParams:实现对已安装程序移动到外部保存目录中
abstract class HandlerParams {
// 抽象类
4676 final static int MAX_RETRIES = 4; // 最多重试4次
4677 int retry = 0;
4678 final boolean startCopy() {
// 提供文件Copy方法
4679 try {
4681 retry++;
4682 if (retry > MAX_RETRIES) {
// 尝试超过4次报错
4684 mHandler.sendEmptyMessage(MCS_GIVE_UP); // 超过4次后发送报错信息,回调错误方法
4685 handleServiceError();
4686 return false;
4687 } else {
4688 handleStartCopy(); // 子类需重写,执行文件复制操作
res = true;
4691 }
4692 } catch (RemoteException e) {
4694 mHandler.sendEmptyMessage(MCS_RECONNECT);
4695 }
4696 handleReturnCode();
return res;
4697 }
4699 final void serviceError() {
4701 handleServiceError();
4702 handleReturnCode();
4703 }
4704 abstract void handleStartCopy() throws RemoteException; // 抽象方法
4705 abstract void handleServiceError();
4706 abstract void handleReturnCode();
}
由上面源码知道,HandlerParams是抽象类,内部提供程序文件的复制功能,执行将安装的apk文件复制到程序的制定安装位置,程序调用startCopy()后开始执行文件赋值,具体赋值调用抽象方法handleStartCopy(),所以具体的功能子类需要重写此方法,在copy发生异常时会发送Handler消息实现重试,最多重试4次后抛出异常;
2、PMS中APK安装过程
程序的安装执行到PMS中后,从Packagemanager的installpackage()方法开始,间接调用到PMS中installStage()函数,installStage()中首先创建InstallParams对象,保存要安装的文件URI和其他信息,然后发送INIT_COPY异步消息启动文件复制
public void installStage(….) {
4590 Message msg = mHandler.obtainMessage(INIT_COPY); // 创建INIT_COPY消息
4591 msg.obj = new InstallParams(packageURI, observer, flags,
4592 installerPackageName); // 创建InstallParams对象封装安装包属性信息
4593 mHandler.sendMessage(msg);
4594 }
Handler在处理INIT_COPY消息时,根据mBound变量确定是否绑定了MSC服务,未绑定的先调用connectToService()执行绑定过程,然后将HandlerParams加入mPendingInstalls集合中等待执行,在服务绑定后发送MCS_BOUND消息,对于已经绑定的直接发送MSC_BOUND事件执行任务
if (!mBound) {
// 1、判断服务是否绑定
457 if (!connectToService()) {
// 2、执行Service绑定
459 params.serviceError();
460 return;
461 } else {
464 mPendingInstalls.add(idx, params); // 3、添加要执行的任务
465 }
466 } else {
467 mPendingInstalls.add(idx, params); // 3、添加任务
470 if (idx == 0) {
471 mHandler.sendEmptyMessage(MCS_BOUND); // 4、就一个事件时,直接发送事件立即执行
472 }
473 }
在处理MCS_BOUND消息时,使用获取的Binder服务从mPendingInstalls列表中取出安装信息HandlerParams类中,
if (msg.obj != null) {
mContainerService = (IMediaContainerService) msg.obj; // 1、获取对应的服务
}
HandlerParams params = mPendingInstalls.get(0); // 2、取出要安装的参数
if (params != null) {
If(params.startCopy()){
// 3、执行Copy文件,最终执行到FileInstallArgs.copyApk()
if (mPendingInstalls.size() > 0) {
mPendingInstalls.remove(0); // 删除集合中的数据
}
};
}
在Handler处理事件时,从消息msg中获取IMediaContainerService服务对象,并从mPendingInstalls集合中获取要执行的任务,此处获取的是前面创建的InstallParams对象,然后调用params.startCopy()方法执行文件复制,按照HandlerParams的源码程序会调用InstallParams.handleStartCopy()方法;
// InstallParams:实现全新安装时的复制过程
class InstallParams extends HandlerParams {
public void handleStartCopy() throws RemoteException {
mArgs = createInstallArgs(this); // 1、
4834 if (ret == PackageManager.INSTALL_SUCCEEDED) {
4837 ret = mArgs.copyApk(mContainerService, true); // 2、
4838 }
}
}
在InstallParams中主要执行两个过程:
- 根据Params类型创建InstallerArgs对象保存请求数据
- 调用InstallArgs.copyApk()方法实现复制
private InstallArgs createInstallArgs(InstallParams params) {
4931 if (installOnSd(params.flags)) {
4932 return new SdInstallArgs(params);//复制到外部存储时使用
4933 } else {
4934 return new FileInstallArgs(params); // 复制到内部存储时使用,在FileInstallArgs内部调用IMediaContainerService服务执行Copy过程
}
}
InstallArgs本身是一个抽象类,内部包含了很多属性信息,它的实现类主要有两个FileInstallArgs和SdInstallArgs,FileInstallArgs主要实现将文件复制到内部存储,而SdInstallArgs执行复制到外部文件存储,这里会创建FileInstallArgs对象,在FileInstallArgs.copy()中直接调用doCopyApk();
- FileInstallArgs.copyApk()
int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
// 1、创建临时文件路径:data/app/vmd.sessionId.tmp 文件目录
final File tempDir = mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
codeFile