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 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
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等属性。