文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PMS安装APP流程解析

2024-11-30 00:36

关注

PMS安装APP流程

文件复制

PackageManagerService.java#installStage安装阶段:

InstallParams中有一个成员变量mArgs,是一个抽象类型InstallArgs,主要是用来执行APK的复制,真正的实现类包括FileInstallArgs用来完成非ASEC应用的安装,ASEC全称是Android Secure External Cache,MoveInstallArgs用来完成已安装应用的移动安装。

void installStage(String packageName, File stagedDir, String stagedCid,
    IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
    String installerPackageName, int installerUid, UserHandle user,
    Certificate[][] certificates) {
    ...
    final Message msg = mHandler.obtainMessage(INIT_COPY);
    final int installReason = fixUpInstallReason(installerPackageName, installerUid,
        sessionParams.installReason);
    final InstallParams params = new InstallParams(origin, null, observer,
        sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
        verificationInfo, user, sessionParams.abiOverride,
        sessionParams.grantedRuntimePermissions, certificates, installReason);
    params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
    msg.obj = params;
    ...
    //发送信息拷贝INIT_COPY 信息
    mHandler.sendMessage(msg);
}

PackageManagerService.java#PackageHandler包处理:connectToService()用于检查和复制可移动文件的服务发送MCS_BOUND信息,触发处理第一个安装请求。

void doHandleMessage(Message msg) {
    switch (msg.what) {
        case INIT_COPY: 
            HandlerParams params = (HandlerParams) msg.obj;
            int idx = mPendingInstalls.size();
            if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
            //mBound用于标识是否绑定了服务,默认值为false
            if (!mBound) { 
                Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS", System.identityHashCode(mHandler));
                //connectToService里面的DefaultContainerService是用于检查和复制可移动文件的服务
                if (!connectToService()) {  
                    Slog.e(TAG, "Failed to bind to media container service");
                    params.serviceError();
                    Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS", System.identityHashCode(mHandler));
                    if (params.traceMethod != null) {
                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod, params.traceCookie);
                    }
                    //绑定服务失败则return
                    return;
                } else { 
                    //绑定服务成功,将请求添加到ArrayList类型的mPendingInstalls中,等待处理
                    mPendingInstalls.add(idx, params);
                }
            } else {  
                //已经绑定服务
                mPendingInstalls.add(idx, params);
                if (idx == 0) {   //5
                    //发送MCS_BOUND类型的消息,触发处理第一个安装请求
                    mHandler.sendEmptyMessage(MCS_BOUND);
                }
            }
            break;
        ....
    }
}

MCS_BOUND 流程处理:

case MCS_BOUND: 
    if (mContainerService == null) {         //判断是否已经绑定了服务
        if (!mBound) {            //绑定服务的标识位,没有绑定成功
            Slog.e(TAG, "Cannot bind to media container service");
            for (HandlerParams params : mPendingInstalls) {
                params.serviceError();
                Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall", System.identityHashCode(params));
                if (params.traceMethod != null) {
                    Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod, params.traceCookie);
                }
                return;
            }   
            //绑定失败,清空安装请求队列
            mPendingInstalls.clear();
        } else {             // 绑定成功
            //继续等待绑定服务
            Slog.w(TAG, "Waiting to connect to media container service");
        }
    } else if (mPendingInstalls.size() > 0) {        //安装APK的队列
        HandlerParams params = mPendingInstalls.get(0);   //安装队列有参数
        if (params != null) {
            Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall", System.identityHashCode(params));
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
            if (params.startCopy()) {               //HandlerParams开始拷贝
                if (DEBUG_SD_INSTALL) Log.i(TAG, "Checking for more work or unbind...");
                    //如果APK安装成功,删除本次安装请求
                    if (mPendingInstalls.size() > 0) {
                        mPendingInstalls.remove(0);
                    }
                    if (mPendingInstalls.size() == 0) {  //安装队列没有参数
                        if (mBound) {            //已经绑定服务,需要发送一个解绑MCS_UNBIND的message
                            //如果没有安装请求了,发送解绑服务的请求
                            if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting delayed MCS_UNBIND");
                                removeMessages(MCS_UNBIND);
                                Message ubmsg = obtainMessage(MCS_UNBIND);
                                sendMessageDelayed(ubmsg, 10000);
                            }
                        } else {
                            if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting MCS_BOUND for next work");
                                //如果还有其他的安装请求,接着发送MCS_BOUND消息继续处理剩余的安装请求       
                                mHandler.sendEmptyMessage(MCS_BOUND);
                            }
                        }
                        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                    }else {
                        Slog.w(TAG, "Empty queue");
                    }
            break;

DefaultContainerService: 真正处理复制APP文件的类

PackageManagerService.java#HandlerParams#startCopy开始复制:

final boolean startCopy() {
    boolean res;
    try {
        if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
        //startCopy方法尝试的次数,超过了4次,就放弃这个安装请求
        if (++mRetries > MAX_RETRIES) {
            Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
            mHandler.sendEmptyMessage(MCS_GIVE_UP);  //发送放弃安装信息
            handleServiceError();
            return false;
        } else {
            handleStartCopy();      //复制APK文件
            res = true;
        }
    } catch (RemoteException e) {
        if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
            mHandler.sendEmptyMessage(MCS_RECONNECT);
            res = false;
        }
        handleReturnCode();   //处理复制APK后的安装APK逻辑
        return res;
    }
}

PackageManagerService.java#InstallParams#handleStartCopy复制apk文件:

InstallArgs做为抽象类,FileInstallArgs和MoveInstallArgs继承InstallArgs FileInstallArgs对data/data/包名(系统应用),MoveInstallArgs用于处理已安装APK的移动:

public void handleStartCopy() throws RemoteException {
    ...
    //确定APK的安装位置。onSd:安装到SD卡, onInt:内部存储即Data分区,ephemeral:安装到临时存储(Instant Apps安装)            
    final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
    final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
    final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
    PackageInfoLite pkgLite = null;
    if (onInt && onSd) {
        // APK不能同时安装在SD卡和Data分区
        Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
        ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
        //安装标志冲突,Instant Apps不能安装到SD卡中
    } else if (onSd && ephemeral) {
        Slog.w(TAG,  "Conflicting flags specified for installing ephemeral on external");
        ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
    } else {
        //获取APK的少量的信息
        pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags, packageAbiOverride);
        if (DEBUG_EPHEMERAL && ephemeral) {
            Slog.v(TAG, "pkgLite for install: " + pkgLite);
        }
        ...
        if (ret == PackageManager.INSTALL_SUCCEEDED) {
            //判断安装的位置
            int loc = pkgLite.recommendedInstallLocation;
            if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
               ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
            } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
               ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
            } 
            ...
        }else {
            loc = installLocationPolicy(pkgLite);     //确定APP安装的位置
             ...
        }
    }
    //根据InstallParams创建InstallArgs对象
    final InstallArgs args = createInstallArgs(this);    InstallArgs作用时:复制和重命名APK
    mArgs = args;
    if (ret == PackageManager.INSTALL_SUCCEEDED) {
        ...
        if (!origin.existing && requiredUid != -1 && isVerificationEnabled(verifierUser.getIdentifier(), installFlags, installerUid)) {
           ...
        } else{
            ret = args.copyApk(mContainerService, true);     // InstallArgs开始复制APP
        }
    }
    mRet = ret;
}

private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
    ...
    try {
        final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
        //创建临时文件存储目录
        final File tempDir = mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
        codeFile = tempDir;
        resourceFile = tempDir;
    } catch (IOException e) {
        Slog.w(TAG, "Failed to create copy file: " + e);
        return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
    }
    ...
    int ret = PackageManager.INSTALL_SUCCEEDED;
    ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
    ...
    return ret;
}

安装APK

final boolean startCopy() {
    ......
    handleStartCopy();  //APP文件复制拷贝
    .....
    //开始安装APP
    handleReturnCode();
}
   
void handleReturnCode() {
    ........
    if (mArgs != null) {
        processPendingInstall(mArgs, mRet);
    }
}

private void processPendingInstall(final InstallArgs args, final int currentStatus) {
    mHandler.post(new Runnable() {
        public void run() {
            mHandler.removeCallbacks(this);
            PackageInstalledInfo res = new PackageInstalledInfo();
            res.setReturnCode(currentStatus);
            res.uid = -1;
            res.pkg = null;
            res.removedInfo = null;
            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                //安装前处理
                args.doPreInstall(res.returnCode);
                synchronized (mInstallLock) {
                    //开始安装
                    installPackageTracedLI(args, res);
                }
                //安装后收尾
                args.doPostInstall(res.returnCode, res.uid);
            }
            ...
        }
    });
}
来源:沐雨花飞蝶内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯