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.java293      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.java2305      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.java2430              mPermissionManager = PermissionManagerService.create(context,2431                      new DefaultPermissionGrantedCallback() {2432                          @Override2433                          public void onDefaultRuntimePermissionsGranted(int userId) {2434                              synchronized(mPackages) {2435                                  mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);2436                              }2437                          }2438                      }, mPackages /*externalLock*/);  //初始化 mPermissionManager2439              mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();2440              mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages);  //创建mSettings2441          }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.java439          mSettingsFilename = new File(mSystemDir, "packages.xml");   // 其实质就是  /data/system/pacages.xml440          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 users) {2979          FileInputStream str = null;3036              int outerDepth = parser.getDepth();3037              while ((type = parser.next()) != XmlPullParser.END_DOCUMENT3038                      && (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.java2529              // Clean up orphaned packages for which the code path doesn't exist2530              // and they are an update to a system app - caused by bug/323212692531              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.jar2567  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 consider2626              // overlay packages if they reside in the right directory.2627  //            先查找 /vendor/overlay  /product/overlay , overlay apk 里面只含有资源的定义, 所以要先加载overlay2628  //            问题3 overlay apk 的工作机制, overlay apk 映射表在哪里?2629              scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),2630                      mDefParseFlags2631                      | PackageParser.PARSE_IS_SYSTEM_DIR,2632                      scanFlags2633                      | SCAN_AS_SYSTEM2634                      | 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                      mDefParseFlags2649                      | PackageParser.PARSE_IS_SYSTEM_DIR,2650                      scanFlags2651                      | SCAN_NO_DEX2652                      | SCAN_AS_SYSTEM2653                      | 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                      mDefParseFlags2660                      | PackageParser.PARSE_IS_SYSTEM_DIR,2661                      scanFlags2662                      | SCAN_AS_SYSTEM2663                      | SCAN_AS_PRIVILEGED,2664                      0);2665  2666              // Collect ordinary system packages.2667              final File systemAppDir = new File(Environment.getRootDirectory(), "app");2668              scanDirTracedLI(systemAppDir,2669                      mDefParseFlags2670                      | PackageParser.PARSE_IS_SYSTEM_DIR,2671                      scanFlags2672                      | SCAN_AS_SYSTEM,2673                      0);.....
    5. 扫描data/app 目录下面安装的apk

      2876                  scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);2877  2878                  scanDirTracedLI(sDrmAppPrivateInstallDir, mDefParseFlags2879                          | 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 on2913                   * the userdata partition actually showed up. If they never2914                   * 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等属性。

更多相关文章

  1. Android系统修改汇总(MTK)
  2. android things中与标准android系统不同的地方
  3. android系统信息(内存,cpu,sd卡,电量,版本)的获取
  4. Android获取系统时间以及网络时间
  5. Mac系统下Android(安卓)SDK更新以及ADT无法在线下载
  6. 关于Android系统 和 Android应用程序
  7. Android(安卓)系统启动流程
  8. Android关于BuildToolVersion与ComplieSdkVersion的区别
  9. 拦截系统收到短信的Notification

随机推荐

  1. 经典SQL语句大全第1/2页
  2. 三种实现方法实现数据表中遍历寻找子节点
  3. 一道sql面试题附答案
  4. SQLServer中master数据库分析
  5. mssql SA帐号的改名和删除
  6. SQL2000中改名和删除默认sa帐号的最安全
  7. LINQ to SQL:处理char(1)字段的方式会引
  8. 一条语句简单解决“每个Y的最新X”的经典
  9. 在查询结果中添加一列表示记录的行数的sq
  10. 精妙的SQL和SQL SERVER 与ACCESS、EXCEL