Android PMS APP安装流程

这篇具有很好参考价值的文章主要介绍了Android PMS APP安装流程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

仓库网址:http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

一、PMS安装APP流程图

Android PMS APP安装流程

二、文件复制

PMS处理安装HandlerParams安装参数流程图

Android PMS APP安装流程PackageManagerService.java#installStage方法介绍

1、创建了一个InstallParams对象
2、创建并发送了一个INIT_COPY的Message消息。
3、InstallParams继承自HandlerParams,用来记录安装应用的参数。
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;
        }

PMS处理复制APP流程图
DefaultContainerService : 真正处理复制APP文件的类

Android PMS APP安装流程PackageManagerService.java#HandlerParams#startCopy

1、尝试安装次数是否超过4次,超过就移除安装的列表数据
2、handleStartCopy : //复制APK文件
3、handleReturnCode : //开始安装APK

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

1、获取APP的部分安装信息
2、获取APP的安装位置
3、InstallArgs复制APP----> FileInstallArgs复制APP---->DefaultContainerService复制APP
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

APP安装流程图

Android PMS APP安装流程

1、在安装前检查是否环境的可靠,如果不可靠会清除复制的APK文件。
2、installPackageTracedLI其内部会调用PMS的installPackageLI方法,进行APP安装。
3、处理安装后操作,如果安装不成功,删除掉安装相关的目录与文件。文章来源地址https://www.toymoban.com/news/detail-498935.html

  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);
                }
              ...
            }
        });
    }

到了这里,关于Android PMS APP安装流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 整理的Binder、DMS、Handler、PMS、WMS等流程图

    AMS: Binder: Handler: PMS: starActivity: WMS: 系统启动:

    2024年01月21日
    浏览(23)
  • Android APP启动流程解析

    Android手机在开机Linux内核启动的时候,会加载system/core/init/init.rc文件,启动init进程,这个是Android特有的初始化程序,主要负责 各种复杂工作 负责开关机画面 文件系统的创建和挂载 启动Zygote(孵化器)进程 启动ServiceManager,它是Binder服务管理器,管理所有Android系统服务 fork

    2024年03月20日
    浏览(32)
  • Android/iOS APP备案流程

    工业和信息化部(工信部)全面调研我国移动互联网应用程序(简称APP)的有关情况,在广泛征集APP主办者等互联网信息服务提供者、网络接入服务提供者、应用分发平台、智能终端生产企业等各方意见的基础上,组织开展APP备案工作,着力提升对APP监管效能,促进互联网行业

    2024年02月05日
    浏览(35)
  • android源码学习- APP启动流程(android12源码)

    百度一搜能找到很多讲APP启动流程的,但是往往要么就是太老旧(还是基于android6去分析的),要么就是不全(往往只讲了整个流程的一小部分)。所以我结合网上现有的文章,以及源码的阅读和调试,耗费了3整天的时间,力求写出一篇最完整,最详细,最通俗易懂的文章,

    2024年02月11日
    浏览(36)
  • Android 10.0 开机启动时PMS扫描apk耗时相关功能优化

      在android10.0的系统rom定制化开发中,在系统中开发产品时,会根据客户要求内置第三方app,这时如果内置app过多,或者安装的app过多,在系统开机的过程中 在pms扫描安装app的时候,就会比较耗时,这时候就需要优化下pms扫描安装app这块的功能代码,用多线程来实现pms扫描安装

    2024年02月04日
    浏览(47)
  • 【Android】AMS(三)APP启动流程

    在 Android 系统中,启动一个应用程序可以分为三种启动方式: 热启动 、 冷启动 和 温启动 。它们分别表示了不同的启动方式和启动过程。 热启动 热启动是指在已经打开并处于后台运行的应用程序中,再次通过图标进入应用程序的启动方式。这时应用程序的进程已经存在,

    2024年02月08日
    浏览(33)
  • 【Android Framework系列】第10章 PMS之Hook实现广播的调用

    前面章节我们学习了【Android Framework系列】第4章 PMS原理我们了解了PMS原理,【Android Framework系列】第9章 AMS之Hook实现登录页跳转我们知道AMS可以Hook拦截下来实现未注册Activity页面的跳转,本章节我们来尝试一下 HookPMS实现广播的发送 。 这里我们只简单介绍一下HookPMS思路和重

    2024年02月13日
    浏览(26)
  • Android S从桌面点击图标启动APP流程 (六)

    系列文章 Android S从桌面点击图标启动APP流程 (一) Android S从桌面点击图标启动APP流程 (二) Android S从桌面点击图标启动APP流程 (三) Android S从桌面点击图标启动APP流程 (四) Android S从桌面点击图标启动APP流程 (五) Android 12的源码链接: android 12 aosp http://aospxref.com/android-12.0.0_r3/ 上文

    2024年02月06日
    浏览(33)
  • Android 系统级APP 升级方案 OTA全流程

    支持原创,请关注专栏: 高质量文章导航 一.Android ota固件编译 OTA 介绍 OTA ( over the air )升级是 Android 系统提供的标准软件升级方式。它功能强大,提供了 完全升级(完整包)、增量升级模式(差异包),可以通过本地升级,也可以通过网络升级 1.完整包 完整包所包含内容

    2024年02月02日
    浏览(68)
  • Uniapp App离线打包流程(Android、IOS待续)

    开发环境: Visual Studio Code 版本:1.84.2 (非必需,可跳过) HBuilder X 版本:3.96 Android Studio 版本: 2022.1.1 JDK 版本:11.0.1 Android SDK. 版本:34.0.0 官网打包流程:https://nativesupport.dcloud.net.cn/AppDocs/usesdk/android.html) 温馨提示:网盘下载如龟速,如需要SDK可以加V benjamin19950304 由于uniapp 3

    2024年04月15日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包