Android P PackageManagerService 初始化流程

Android P PackageManagerService 初始化流程

  1. 概述

    1. 解析AndroidManifest.xml,主要包括AndroidManifest中节点信息的解析和target-name的分析和提炼,这部分和ActivityManagerService和WindowManagerService都有紧急的联系。关于AndroidManifest.xml中的属性设置,会单独拎出来讲解,本文不扩展讲解。
    2. 扫描本地文件,主要针对apk,主要是系统应用、本地安装应用等等。这部分会在下面仔细讲解。
    3. 管理本地apk,主要包括安装、删除等等。
    4. 下面称PackageManagerService为PKMS
  2. PackageManagerService 启动

    frameworks/base/services/java/com/android/server/SystemServer.java
    293      public static void main(String[] args) {   //静态main函数
    294          new SystemServer().run();              //创建SystemServer 并执行其run函数
    295      }
    ...
    307      private void run() {
    308          try {
    309              traceBeginAndSlog("InitBeforeStartServices");
    426          // Start services.
    427          try {
    428              traceBeginAndSlog("StartServices");
    429              startBootstrapServices();         //启动初始化需要启动的services
    ...
    537      private void startBootstrapServices() {
    ....
    627          traceBeginAndSlog("StartPackageManagerService");
    628          mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
    629                  mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
                      ---->  执行PKMS的main函数
    630          mFirstBoot = mPackageManagerService.isFirstBoot();
    631          mPackageManager = mSystemContext.getPackageManager();
    
    
    frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
    2305      public static PackageManagerService main(Context context, Installer installer,
    2306              boolean factoryTest, boolean onlyCore) {
    2307          // Self-check for initial settings.
    2308          PackageManagerServiceCompilerMapping.checkProperties();
    2309  
    2310          PackageManagerService m = new PackageManagerService(context, installer,
    2311                  factoryTest, onlyCore);      ---> 创建PackageManagerService,此构造函数为PKMS初始化的主战场
    2312          m.enableSystemUserPackages();
    2313          ServiceManager.addService("package", m);
    2314          final PackageManagerNative pmn = m.new PackageManagerNative();
    2315          ServiceManager.addService("package_native", pmn);
    2316          return m;
    2317      }
    ...
    2402      public PackageManagerService(Context context, Installer installer,
    2403              boolean factoryTest, boolean onlyCore) {
    
    
  3. PKMS初始化过程

    ​ 我把PKMS的初始化划分为如下几个阶段:

    1. 第一阶段 :Settings 初始化

      此阶段主要为解析PKMS的几个xml文件,并将其解析并存放到mSettings变量中。相关代码如下:

      frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
      2430              mPermissionManager = PermissionManagerService.create(context,
      2431                      new DefaultPermissionGrantedCallback() {
      2432                          @Override
      2433                          public void onDefaultRuntimePermissionsGranted(int userId) {
      2434                              synchronized(mPackages) {
      2435                                  mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
      2436                              }
      2437                          }
      2438                      }, mPackages /*externalLock*/);  //初始化 mPermissionManager
      2439              mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
      2440              mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages);  //创建mSettings
      2441          }
      2442          }
      2445          mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
      2446                  ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
      2447          mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
      2448                  ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
      2449          mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
      2450                  ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
      2451          mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
      2452                  ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
      2453          mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
      2454                  ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
      2455          mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
      2456                  ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
      2457          mSettings.addSharedUserLPw("android.uid.se", SE_UID,
      2458                  ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
      ...
      Android 系统中 UID/GID 介绍:
      UID 为用户 ID 的缩写,GID 为用户组 ID 的缩写,这两个概念均与 Linux 系统中进程的权限管理有关。一般说来,每一个进程都会有一个对应的 UID(即表示该进程属于哪个 user,不同 user 有不同权限)。一个进程也可分属不同的用户组(每个用户组都有对应的权限)。
      
      ...
      2525              Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
      2526              mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));   // 此方法会解析paxkages.xml文件
      2527              Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
      
      frameworks/base/services/core/java/com/android/server/pm/Settings.java
      439          mSettingsFilename = new File(mSystemDir, "packages.xml");   // 其实质就是  /data/system/pacages.xml
      440          mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
      441          mPackageListFilename = new File(mSystemDir, "packages.list");
      ...
      3016                  str = new FileInputStream(mSettingsFilename);
      3017              }
      3018              XmlPullParser parser = Xml.newPullParser();
      3019              parser.setInput(str, StandardCharsets.UTF_8.name());
      ...
      2978      boolean readLPw(@NonNull List<UserInfo> users) {
      2979          FileInputStream str = null;
      3036              int outerDepth = parser.getDepth();
      3037              while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
      3038                      && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
      3039                  if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
      3040                      continue;
      3041                  }
      3042  
      3043                  String tagName = parser.getName();
      3044                  if (tagName.equals("package")) {
      3045                      readPackageLPw(parser);
      3046                  } else if (tagName.equals("permissions")) {
      3047                      mPermissions.readPermissions(parser);
      3048                  } else if (tagName.equals("permission-trees")) {
      3049                      mPermissions.readPermissionTrees(parser);
      
      
    2. 第二阶段:清理不正常的APK

      frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
      2529              // Clean up orphaned packages for which the code path doesn't exist
      2530              // and they are an update to a system app - caused by bug/32321269
      2531              final int packageSettingCount = mSettings.mPackages.size();
      2532              android.util.Log.d(TAG, "wangwei packageSettingCount = " + packageSettingCount);
      2533              for (int i = packageSettingCount - 1; i >= 0; i--) {
      2534                  PackageSetting ps = mSettings.mPackages.valueAt(i);
      2535                  if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
      2536                          && mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
      2537                      mSettings.mPackages.removeAt(i);  //从第一阶段产生的msettings中将该异常的apk删除掉。
      2538                      mSettings.enableSystemPackageLPw(ps.name); //因为删除掉的是系统预装的apk的升级版本,所以原本系统预装的apk需要再次被使能。
      2539                  }
      2540              }
      有的情况,同学可能不能理解这里地方的用意。其实就是比如我手机预装了facebook,而随着时间的推移这个facebook可能会升级,这个时候升级就是安装到data分区了,system分区的是disable掉了。但是升级apk就有失败的可能, 如果升级这个apk失败,或者安装在data分区的文件不存在了。那么就需要把原来预装到system分区的低版本facebook使能。
      
    3. 第三阶段:加载 framework 环境变量

      2561              final String bootClassPath = System.getenv("BOOTCLASSPATH");
      2562  //            BOOTCLASSPATH=/system/framework/core-oj.jar:/system/framework/core-libart.jar:/system/framework/conscrypt.jar:
      2563  // /system/framework/okhttp.jar:/system/framework/bouncycastle.jar:/system/framework/apache-xml.jar:/system/framework/ext.jar:
      2564  // /system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/ims-common.jar:
      2565  // /system/framework/android.hidl.base-V1.0-java.jar:/system/framework/android.hidl.manager-V1.0-java.jar:/system/framework/framework-oahl-backward-compatibility.jar:
      2566  // /system/framework/android.test.base.jar
      2567  
      2568              final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
      2569  //            generic_x86_64:/ # env | grep "SYSTEMSERVERCLASSPATH"
      2570  //            SYSTEMSERVERCLASSPATH=/system/framework/services.jar:/system/framework/ethernet-service.jar:
      2571  // /system/framework/wifi-service.jar:/system/framework/com.android.location.provider.jar
      
      其实就是加载 系统所需要的 frameworks相关的jar库。其变量的值我已经打印出来了。
      
    4. 第四阶段:扫描系统预装apk

      1.在安卓的资源加载逻辑中,除了在apk源代码里面就指定需要加载或者用到的资源外,还可以有RRO和SRO两种资源替换方式。此处的overlay 则为RRO

      2624              // Collect vendor/product overlay packages. (Do this before scanning any apps.)
      2625              // For security and version matching reason, only consider
      2626              // overlay packages if they reside in the right directory.
      2627  //            先查找 /vendor/overlay  /product/overlay , overlay apk 里面只含有资源的定义, 所以要先加载overlay
      2628  //            问题3 overlay apk 的工作机制, overlay apk 映射表在哪里?
      2629              scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
      2630                      mDefParseFlags
      2631                      | PackageParser.PARSE_IS_SYSTEM_DIR,
      2632                      scanFlags
      2633                      | SCAN_AS_SYSTEM
      2634                      | SCAN_AS_VENDOR,
      2635                      0);
      如果不清楚overlay apk的书写方式,请搜索查阅。
      此处主要扫描/vendor/overlay/*.apk  /product/overlay/*.apk
      
      
      
      1. 扫描framework目录
      2646              // Find base frameworks (resource packages without code).
      2647              scanDirTracedLI(frameworkDir,
      2648                      mDefParseFlags
      2649                      | PackageParser.PARSE_IS_SYSTEM_DIR,
      2650                      scanFlags
      2651                      | SCAN_NO_DEX
      2652                      | SCAN_AS_SYSTEM
      2653                      | SCAN_AS_PRIVILEGED,
      2654                      0);
      

      3.扫描/system/priv-app /system/app /vendor/priv-app /vendor/app /odm/priv-app /odm/app /oem/app /product/priv-app /product/app

      相关代码如下:

      2656              // Collect privileged system packages.
      2657              final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
      2658              scanDirTracedLI(privilegedAppDir,
      2659                      mDefParseFlags
      2660                      | PackageParser.PARSE_IS_SYSTEM_DIR,
      2661                      scanFlags
      2662                      | SCAN_AS_SYSTEM
      2663                      | SCAN_AS_PRIVILEGED,
      2664                      0);
      2665  
      2666              // Collect ordinary system packages.
      2667              final File systemAppDir = new File(Environment.getRootDirectory(), "app");
      2668              scanDirTracedLI(systemAppDir,
      2669                      mDefParseFlags
      2670                      | PackageParser.PARSE_IS_SYSTEM_DIR,
      2671                      scanFlags
      2672                      | SCAN_AS_SYSTEM,
      2673                      0);
      .....
      
    5. 扫描data/app 目录下面安装的apk

      2876                  scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
      2877  
      2878                  scanDirTracedLI(sDrmAppPrivateInstallDir, mDefParseFlags
      2879                          | PackageParser.PARSE_FORWARD_LOCK,
      2880                          scanFlags | SCAN_REQUIRE_KNOWN, 0);
      
      
    6. 根据解析出来的msetting 变量内容与mpackage 扫描各个目录获取到的app列表进行对比

      关键变量:mExpectingBetter

      2911                  /*
      2912                   * Make sure all system apps that we expected to appear on
      2913                   * the userdata partition actually showed up. If they never
      2914                   * appeared, crawl back and revive the system version.
      2915                   */
      2916                  for (int i = 0; i < mExpectingBetter.size(); i++) {
      2917                      final String packageName = mExpectingBetter.keyAt(i);
      2918                      if (!mPackages.containsKey(packageName)) {
      2919                          final File scanFile = mExpectingBetter.valueAt(i);
      2920  
      ...
      2990                          mSettings.enableSystemPackageLPw(packageName);
      2991  
      2992                          try {
      2993                              scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);    //此处的 scanFile 已经是data分区的更新版本的app目录了。
      2994                          } catch (PackageManagerException e) {
      2995                              Slog.e(TAG, "Failed to parse original system package: "
      2996                                      + e.getMessage());
      2997                          }
      
      

      在扫描完system app之后,会对msetting 变量做一次遍历,主要找出系统app中被disable掉的app,此类型的app只可能是因为有用户的升级,才会导致该系统app被disable掉。扫描到类似这样的系统app,则将其加入到mExpectingBetter列表中。第六步的主要目的是将前面扫描的时候加入到mExpectingBetter 列表里面的app,定位到该app是system/vendor/product等属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值