Android P PackageManagerService 初始化流程
-
概述
- 解析AndroidManifest.xml,主要包括AndroidManifest中节点信息的解析和target-name的分析和提炼,这部分和ActivityManagerService和WindowManagerService都有紧急的联系。关于AndroidManifest.xml中的属性设置,会单独拎出来讲解,本文不扩展讲解。
- 扫描本地文件,主要针对apk,主要是系统应用、本地安装应用等等。这部分会在下面仔细讲解。
- 管理本地apk,主要包括安装、删除等等。
- 下面称PackageManagerService为PKMS
-
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) {
-
PKMS初始化过程
我把PKMS的初始化划分为如下几个阶段:
-
第一阶段 :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);
-
第二阶段:清理不正常的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使能。
-
第三阶段:加载 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库。其变量的值我已经打印出来了。
-
第四阶段:扫描系统预装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
- 扫描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); .....
-
扫描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);
-
根据解析出来的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等属性。
-