zoukankan      html  css  js  c++  java
  • Android PKMS服务

    它的作用?

    关于PKMS的全称是啥应该咱们不陌生,PackageManagerService,和AMS一样是Android系统的核心服务,它主要负责系统中Package的管理,应用程序的安装、卸载、信息查询等工作。几乎每个实际项目都会使用它,最典型的就是APP的更新安装。

    服务何时启动?

    那PKMS是在何时进行的启动了,其实是在SystemServer.main()中进行的,下面来直接看一下源码,其源码还是基于8.0,如下:

    然后在它的run()方法中看一下启动细节,看核心:

    然后接下来就启动各种服务了:

    那么问题来了?PKMS服务的启动是在哪个方法中来执行的呢?咱先先来看第一个启动引导服务方法:

    接下来就可以看到启动AMS服务了,也就是上次咱们所析的,这里再来回顾一下:

    接下来还有一系列系统服务的启动,如:PowerManagerService:

    DisplayManagerService:

     

    好,接下来我们想要的答案的代码来了:

    由于已经看到了咱们所要看到的服务的启动,对于其它2个启动服务的方法就暂且不看了,得集中精力分析我们想分析的PKMS,免得精力分散了:

    好,咱们来分析一下PKMS的main()方法,既然在注册它时调用了它:

     

    上面来将其整个PKMS启动的流程用图来表述一下:

     

    然后最后将其注册到ServiceManager当中:

    好,既然构造了PKMS,那下面来看一下它里面的构造细节。

    构造方法:

    该构造方法代码量很大:

     

    700多行。。当然也只能顺着核心流程来分析喽,其实分为如下五个阶段。

    第一阶段:

    构造函数在第一阶段的工作,主要是扫描并解析 ,XML 文件,将其中的信息保存到特定的数据结构中。看下代码:

     

    第二阶段:

    该阶段主要是扫描系统文件。

    1、创建/system的子目录,比如/system/framework、system/priv-app和/system/app等等。

    瞅下代码:

    2、扫描系统文件,比如/vendor/overlay、/system/framework、/system/app等等目录下的文件,对扫描到的系统文件做后续处理。 

    其中:

    /system/frameworks:该目录中的文件都是系统库,例如:framework.jar、services.jar、framework-res.apk。不过 scanDirLI 只扫描APK文件,所以 framework-res.apk 是该目录中唯一“受宠”的文件。
    该目录下全是默认的系统应用,例如:Browser.apk、SettingsProvider.apk 等。
    /vendor/app:该目录中的文件由厂商提供,即厂商特定的 APK 文件,不过目前市面上的厂商都把自己的应用放在 /system/app 目录下。

    瞅下代码:

    第三阶段:

    它是属于扫描data分区阶段,扫描/data/app和/data/app-private目录下的文件:

    ,具体细节为:

    1、遍历possiblyDeletedUpdatedSystemApps列表,如果这个系统App的包信息不在PMS的变量mPackages中,说明是残留的App信息,后续会删除它的数据。说明是存在于Data分区,不属于系统App,那么移除其系统权限。
    看下代码:

    其中可以看到是利用PackageParser.Package来对包进行扫描的:

    咱们点进去看一下大概扫描的细节:

    然后看一下它里面定义的成员变量,就知道它的大概作用了:

    也就是会扫描manifest文件,然后将其扫描的信息存储到对应的集合当中了。

    2、遍历mExpectingBetter列表,根据系统App所在的目录设置扫描的解析参数,内部会将packageName对应的包设置数据(PackageSetting)添加到mSettings的mPackages中。扫描系统App的升级包,最后清除mExpectingBetter列表。

    看下代码:

    第四阶段:

    扫描结束阶段主要是做了以下事情:

    1、如果当前平台SDK版本和上次启动时的SDK版本不同,重新更新APK的授权;

    2、如果是第一次启动或者是Android M升级后的第一次启动,需要初始化所有用户定义的默认首选App;

    3、OTA升级后的第一次启动,会清除代码缓存目录。

    4、把Settings的内容保存到packages.xml中,这样此后PMS再次创建时会读到此前保存的Settings的内容。

    第五阶段:

    此时就进入了准备安装的阶段了:

     

    以上五个阶段走完之后,咱们再来完善之前的图:

    installd进程:

    我们在之前分析PKMS服务启动时知道在它之前会创建一个这样的服务:

    而它是运行在installd进程中的,看一下Installer.java类的注释:

    那么该进程是何时启动的呢?这里就得从开机到app启动的流程进行梳理一下,其创建结点这在其中,下面来梳理一下:

    也就是installd 是由 Android 系统的 init 进程(pid=1),在解析 init.rc 文件的如下代码块时,通过 fork 创建的用户空间的守护进程 installd,

    而该进程的代码对应于这样cpp:

    而installd 是随着系统启动过程中 main class 而启动的,并启动InstalldNativeService服务发布到native层的ServiceManager中,通过IPC机制跟上层的 installer服务进行交互。下面来看一下它的main入口函数:

    然后咱们再来跟到InstalldNativeService.cpp中来看一下它启动的细节:

    而它里面都是跟一些app的操作相关的服务,大致瞅一下提供的函数:

    系统内置应用程序安装app:

    对于应用的安装我们在应用时会这样来写:

    咱们接下来就来分析一下它的整个安装过程,最终就是会用到PKMS来进行安装,先贴一张整个安装的流程图:

    下面根据上面的流程来看一下具体的代码,对于上面的调用安装是最终会到PackageInstallerActivity这个界面上来,也就是安装确定界面,这个是大家再熟悉不过的了,下面打开看一下这个类的源码:

    然后在onCreate()的最后会有一句这个代码:

    判断是否是未知来源的应用,如果开启允许安装未知来源选项则直接初始化安装,这个在实际咱们在安装时也是经常会出现的,此时就需要到设置里去把未知来源勾选一下就可以正常安装了,好下面再来看一下检测方法:

    好,下面直接来看一下直接安装的方法:

     

    然后具体UI的细节就不看了,直接看到用户点了“安装”的事件:

     

    此时就会跳到安装中的InstallInstalling的Acitivity界面了,跟进去看一下细节:

    然后在安装后台线程中看一下真正执行安装的逻辑:

     

    此时就转到PackageInstaller.Session.commit()方法来瞅一下:

    而它的具体实现类则为PackageInstallerSession.java,所以看一下它的细节:

     

    此时看一下这个消息处理逻辑:

     

     而mPm就是PKMS:

    所以又转到PKMS.installStage()方法中来瞅一下,最终的执行是通过消息处理:

     

    最终的安装就会还是用installer服务来进行安装,也就是对于安装是底层来完成的。也就是这块:

  • 相关阅读:
    编译原理-第二章 一个简单的语法指导编译器-2.4 语法制导翻译
    编译原理-第二章 一个简单的语法指导编译器-2.3 语法定义
    编译原理-第二章 一个简单的语法指导编译器-2.2 词法分析
    LeetCode 1347. Minimum Number of Steps to Make Two Strings Anagram
    LeetCode 1348. Tweet Counts Per Frequency
    1349. Maximum Students Taking Exam(DP,状态压缩)
    LeetCode 1345. Jump Game IV(BFS)
    LeetCode 212. Word Search II
    LeetCode 188. Best Time to Buy and Sell Stock IV (动态规划)
    LeetCode 187. Repeated DNA Sequences(位运算,hash)
  • 原文地址:https://www.cnblogs.com/webor2006/p/11890629.html
Copyright © 2011-2022 走看看