Android包管理机制(三)PMS处理APK的安装

本文详细探讨了Android包管理服务(PMS)处理APK安装的流程,包括PackageHandler如何处理安装消息,如何复制APK,以及安装APK的主要步骤。PMS通过发送INIT_COPY和MCS_BOUND消息来驱动复制和安装过程,使用DefaultContainerService进行APK的复制,并在安装过程中进行一系列检查和设置操作。

本文首发于微信公众号「刘望舒」

关联系列
Android包管理机制系列

前言

在上一篇文章Android包管理机制(二)PackageInstaller安装APK中,我们学习了PackageInstaller是如何安装APK的,最后会将APK的信息交由PMS处理。那么PMS是如何处理的呢?这篇文章会给你答案。

1.PackageHandler处理安装消息

APK的信息交由PMS后,PMS通过向PackageHandler发送消息来驱动APK的复制和安装工作。
先来查看PackageHandler处理安装消息的调用时序图。

VeClRJ.png

接着上一篇文章的代码逻辑来查看PMS的installStage方法。
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

 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);//1
        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);//2
        params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
        msg.obj = params;
        ...
        mHandler.sendMessage(msg);//3
    }

注释2处创建InstallParams,它对应于包的安装数据。注释1处创建了类型为INIT_COPY的消息,在注释3处将InstallParams通过消息发送出去。

1.1 对INIT_COPY的消息的处理

处理INIT_COPY类型的消息的代码如下所示。
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java#PackageHandler

        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) {
   
   //1
                        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                System.identityHashCode(mHandler));
                        //如果没有绑定服务,重新绑定,connectToService方法内部如果绑定成功会将mBound置为true
                        if (!connectToService()) {
   
   //2
                            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) {
   
   
                            mHandler.sendEmptyMessage(MCS_BOUND);//3
                        }
                    }
                    break;
                }
                ....
                }
    }
 }

PackageHandler继承自Handler,它被定义在PMS中,doHandleMessage方法用于处理各个类型的消息,来查看对INIT_COPY类型消息的处理。注释1处的mBound用于标识是否绑定了DefaultContainerService,默认值为false。DefaultContainerService是用于检查和复制可移动文件的服务,这是一个比较耗时的操作,因此DefaultContainerService没有和PMS运行在同一进程中,它运行在com.android.defcontainer进程,通过IMediaContainerService和PMS进行IPC通信,如下图所示。
VeCQG4.png

注释2处的connectToService方法用来绑定DefaultContainerService,注释3处发送MCS_BOUND类型的消息,触发处理第一个安装请求。
查看注释2处的connectToService方法:
**frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java#PackageHandler **

  private boolean connectToService() {
   
   
            if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
                    " DefaultContainerService");
            Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
            Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
            if (mContext.bindServiceAsUser(service, mDefContainerConn,
                    Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
   
   //1
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                mBound = true;//2
                return true;
            }
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            return false;
        }

注释2处如果绑定DefaultContainerService成功,mBound会置为ture 。注释1处的bindServiceAsUser方法会传入mDefContainerConn,bindServiceAsUser方法的处理逻辑和我们调用bindService是类似的,服务建立连接后,会调用onServiceConnected方法:
**frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java **

  class DefaultContainerConnection implements ServiceConnection {
   
   
        public void onServiceConnected(ComponentName name, IBinder service) {
   
   
            if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
            final IMediaContainerService imcs 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值