分析 PackageManagerService 的构造方法,主要是扫描已存在的应用并建立应用信息库用于查询

PackageManagerService 构造过程

  • 涉及文件
    • frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
    • frameworks/base/services/core/java/com/android/server/pm/Settings.java
    • frameworks/base/core/java/com/android/server/SystemConfig.java
    • frameworks/base/services/core/java/com/android/server/pm/ParallelPackageParser.java
    • frameworks/base/core/java/android/content/pm/PackageParser.java
    • frameworks/base/services/core/java/com/android/server/pm/PackageSetting.java

PackageManagerService()

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
public PackageManagerService(Context context, Installer installer,
                             boolean factoryTest, boolean onlyCore) {
    //LockGuard 验证所有锁定是否以一致的顺序完成,并且如果检测到任何反转则将记录。
    //例如,如果调用线程在保持  PackageManager 锁时试图获取  ActivityManager 锁,它将会提示。
    LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                        SystemClock.uptimeMillis());
    //ro.build.version.sdk 没有设置,这个一般是不可能的
    if (mSdkVersion <= 0) {
        Slog.w(TAG, "**** ro.build.version.sdk not set!");
    }

    mContext = context;
    // 正常情况下,mFactoryTest=false mOnlyCore=false
    mFactoryTest = factoryTest;
    mOnlyCore = onlyCore;
    //分辨率相关
    mMetrics = new DisplayMetrics();
    //用于远程调用  installd
    mInstaller = installer;

    // Create sub-components that provide services / data. Order here is important.
    synchronized (mInstallLock) {
        synchronized (mPackages) {
            // Expose private service for system components to use.
            // PackageManager 加入到  LocalServices 供  SystemServer 内部调用  PackageManagerService
            LocalServices.addService(
                                     PackageManagerInternal.class, new PackageManagerInternalImpl());
            // 用户管理
            sUserManager = new UserManagerService(context, this,
                                                  new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
            // 权限管理
            mPermissionManager = PermissionManagerService.create(context,
                                                                 new DefaultPermissionGrantedCallback() {
                                                                     @Override
                                                                     public void onDefaultRuntimePermissionsGranted(int userId) {
                                                                         synchronized(mPackages) {
                                                                             mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
                                                                         }
                                                                     }
                                                                 }, mPackages /*externalLock*/);
            // 默认权限策略,比如默认情况下  Phone 应该具有电话相关的权限
            mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
            // 保存有关动态设置的信息 <1.>
            mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages);
        }
    }
    // Android UID 与  Linux UID 的一一对应关系
    mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
                               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
                               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
                               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
                               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
                               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    mSettings.addSharedUserLPw("android.uid.se", SE_UID,
                               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    // 调试相关,默认未设置是空
    String separateProcesses = SystemProperties.get("debug.separate_processes");
    if (separateProcesses != null && separateProcesses.length() > 0) {
        if ("*".equals(separateProcesses)) {
            mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
            mSeparateProcesses = null;
            Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
        } else {
            mDefParseFlags = 0;
            mSeparateProcesses = separateProcesses.split(",");
            Slog.w(TAG, "Running with debug.separate_processes: "
                   + separateProcesses);
        }
    } else {
        mDefParseFlags = 0;
        mSeparateProcesses = null;
    }
    // 用于在包上运行  dexopt 命令的  Helper 类
    mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
                                                   "*dexopt*");
    DexManager.Listener dexManagerListener = DexLogger.getListener(this,
                                                                   installer, mInstallLock);
    // 用于处理  dex 文件
    mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock,
                                 dexManagerListener);
    // ArtManagerService Art 虚拟机管理服务
    mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);
    // 两个回调
    mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());

    mOnPermissionChangeListeners = new OnPermissionChangeListeners(
                                                                   FgThread.get().getLooper());
    // 存储分辨率、显示等相关信息
    getDefaultDisplayMetrics(context, mMetrics);
    // 系统设置 <2.>
    SystemConfig systemConfig = SystemConfig.getInstance();
    // 支持的功能
    mAvailableFeatures = systemConfig.getAvailableFeatures();
    // 需要特殊保护的包
    mProtectedPackages = new ProtectedPackages(mContext);

    synchronized (mInstallLock) {
        // writer
        synchronized (mPackages) {
            // 该  Handler 将处理  PackageManagerService 的相关消息,APK 的安装就由其负责
            mHandlerThread = new ServiceThread(TAG,
                                               Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
            mHandlerThread.start();
            mHandler = new PackageHandler(mHandlerThread.getLooper());
            // 日志相关
            mProcessLoggingHandler = new ProcessLoggingHandler();
            // 监控堵塞
            Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
            // 用于管理即时应用
            mInstantAppRegistry = new InstantAppRegistry(this);
            // 保存共享库到当前服务
            ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
            final int builtInLibCount = libConfig.size();
            for (int i = 0; i < builtInLibCount; i++) {
                String name = libConfig.keyAt(i);
                String path = libConfig.valueAt(i);
                addSharedLibraryLPw(path, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
                                    SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
            }
            // 从  mac_permissions.xml 等相关文件加载  SELinux MAC 策略
            SELinuxMMAC.readInstallPolicy();

            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks");
            // ApplicationInfo#category 的回调
            FallbackCategoryProvider.loadFallbacks();
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
            // 是否首次启动设备
            mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

            // Clean up orphaned packages for which the code path doesn't exist
            // and they are an update to a system app - caused by bug/32321269
            // 清除孤立包
            final int packageSettingCount = mSettings.mPackages.size();
            for (int i = packageSettingCount - 1; i >= 0; i--) {
                PackageSetting ps = mSettings.mPackages.valueAt(i);
                if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
                    && mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
                    mSettings.mPackages.removeAt(i);
                    mSettings.enableSystemPackageLPw(ps.name);
                }
            }

            if (mFirstBoot) {
                // 请求把备份系统的数据复制到  data 分区,如果有的话
                requestCopyPreoptedFiles();
            }
            // 获取自定义  ResolverActivity,一般为空,
            //ResolverActivity 用于显示系统启动一个  Intent 的多个匹配项
            String customResolverActivity = Resources.getSystem().getString(
                                                                            R.string.config_customResolverActivity);
            if (TextUtils.isEmpty(customResolverActivity)) {
                customResolverActivity = null;
            } else {
                mCustomResolverComponentName = ComponentName.unflattenFromString(
                                                                                 customResolverActivity);
            }

            long startTime = SystemClock.uptimeMillis();

            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                                startTime);
            // 系统启动相关类的环境变量,默认包括 /sysem/frameworks/*.jar
            final String bootClassPath = System.getenv("BOOTCLASSPATH");
            // SystemServer 相关类的环境变量, 包括 /system/framework/services.jar /system/framework/*-service.jar
            final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");

            if (bootClassPath == null) {
                Slog.w(TAG, "No BOOTCLASSPATH found!");
            }

            if (systemServerClassPath == null) {
                Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
            }
            //  /system/framework 目录
            File frameworkDir = new File(Environment.getRootDirectory(), "framework");
            // 系统  ota 升级相关
            final VersionInfo ver = mSettings.getInternalVersion();
            mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
            if (mIsUpgrade) {
                logCriticalInfo(Log.INFO,
                                "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT);
            }

            // when upgrading from pre-M, promote system app permissions from install to runtime
            mPromoteSystemApps =
                mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;

            // When upgrading from pre-N, we need to handle package extraction like first boot,
            // as there is no profiling data available.
            mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;

            mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;

            // save off the names of pre-existing system packages prior to scanning; we don't
            // want to automatically grant runtime permissions for new system apps
            // 在扫描之前保存预先存在的系统包的名称; 我们不希望自动为新系统应用授予运行时权限
            if (mPromoteSystemApps) {
                Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
                while (pkgSettingIter.hasNext()) {
                    PackageSetting ps = pkgSettingIter.next();
                    if (isSystemApp(ps)) {
                        mExistingSystemPackages.add(ps.name);
                    }
                }
            }
            // 获取缓存目录,如果是升级的话则删除缓存目录并重新生成缓存
            mCacheDir = preparePackageParserCache(mIsUpgrade);

            // Set flag to monitor and not change apk file paths when
            // scanning install directories.
            // 扫描安装包的默认参数
            int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
            // 第一次或  ota 升级后开机
            if (mIsUpgrade || mFirstBoot) {
                scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
            }
            // 从指定目录扫描安装包,不同点目录扫描参数不一样 <3.>
            // /system/priv-app,/system/app,/system/frameworks,/vender,/odm 等目录
            // Collect vendor/product overlay packages. (Do this before scanning any apps.)
            // For security and version matching reason, only consider
            // overlay packages if they reside in the right directory.
            scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
                            mDefParseFlags
                            | PackageParser.PARSE_IS_SYSTEM_DIR,
                            scanFlags
                            | SCAN_AS_SYSTEM
                            | SCAN_AS_VENDOR,
                            0);

            // ......

            // Collect ordinary product packages.
            File productAppDir = new File(Environment.getProductDirectory(), "app");
            try {
                productAppDir = productAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(productAppDir,
                            mDefParseFlags
                            | PackageParser.PARSE_IS_SYSTEM_DIR,
                            scanFlags
                            | SCAN_AS_SYSTEM
                            | SCAN_AS_PRODUCT,
                            0);
            // 处理不存在的系统安装包
            // Prune any system packages that no longer exist.
            final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
            // 子包必须替换为  data 分区上的完整包或被禁用
            // Stub packages must either be replaced with full versions in the /data
            // partition or be disabled.
            final List<String> stubSystemApps = new ArrayList<>();
            if (!mOnlyCore) {
                // do this first before mucking with mPackages for the "expecting better" case
                final Iterator<PackageParser.Package> pkgIterator = mPackages.values().iterator();
                while (pkgIterator.hasNext()) {
                    final PackageParser.Package pkg = pkgIterator.next();
                    if (pkg.isStub) {
                        stubSystemApps.add(pkg.packageName);
                    }
                }

                final Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
                while (psit.hasNext()) {
                    PackageSetting ps = psit.next();

                    /*
                     * If this is not a system app, it can't be a
                     * disable system app.
                     */
                    if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                        continue;
                    }

                    /*
                     * If the package is scanned, it's not erased.
                     */
                    final PackageParser.Package scannedPkg = mPackages.get(ps.name);
                    if (scannedPkg != null) {
                        /*
                         * If the system app is both scanned and in the
                         * disabled packages list, then it must have been
                         * added via OTA. Remove it from the currently
                         * scanned package so the previously user-installed
                         * application can be scanned.
                         */
                        if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                            logCriticalInfo(Log.WARN,
                                            "Expecting better updated system app for " + ps.name
                                            + "; removing system app.  Last known"
                                            + " codePath=" + ps.codePathString
                                            + ", versionCode=" + ps.versionCode
                                            + "; scanned versionCode=" + scannedPkg.getLongVersionCode());
                            removePackageLI(scannedPkg, true);
                            mExpectingBetter.put(ps.name, ps.codePath);
                        }

                        continue;
                    }

                    if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
                        psit.remove();
                        logCriticalInfo(Log.WARN, "System package " + ps.name
                                        + " no longer exists; it's data will be wiped");
                        // Actual deletion of code and data will be handled by later
                        // reconciliation step
                    } else {
                        // we still have a disabled system package, but, it still might have
                        // been removed. check the code path still exists and check there's
                        // still a package. the latter can happen if an OTA keeps the same
                        // code path, but, changes the package name.
                        final PackageSetting disabledPs =
                            mSettings.getDisabledSystemPkgLPr(ps.name);
                        if (disabledPs.codePath == null || !disabledPs.codePath.exists()
                            || disabledPs.pkg == null) {
                            possiblyDeletedUpdatedSystemApps.add(ps.name);
                        }
                    }
                }
            }

            //delete tmp files
            deleteTempPackageFiles();

            final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get();

            // Remove any shared userIDs that have no associated packages
            // 删除没有关联包的任何共享用户标识
            mSettings.pruneSharedUsersLPw();
            final long systemScanTime = SystemClock.uptimeMillis() - startTime;
            final int systemPackagesCount = mPackages.size();
            Slog.i(TAG, "Finished scanning system apps. Time: " + systemScanTime
                   + " ms, packageCount: " + systemPackagesCount
                   + " , timePerPackage: "
                   + (systemPackagesCount == 0 ? 0 : systemScanTime / systemPackagesCount)
                   + " , cached: " + cachedSystemApps);
            if (mIsUpgrade && systemPackagesCount > 0) {
                MetricsLogger.histogram(null, "ota_package_manager_system_app_avg_scan_time",
                                        ((int) systemScanTime) / systemPackagesCount);
            }
            if (!mOnlyCore) {
                // 处理第三方安装包
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                                    SystemClock.uptimeMillis());
                scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);

                scanDirTracedLI(sDrmAppPrivateInstallDir, mDefParseFlags
                                | PackageParser.PARSE_FORWARD_LOCK,
                                scanFlags | SCAN_REQUIRE_KNOWN, 0);

                // Remove disable package settings for updated system apps that were
                // removed via an OTA. If the update is no longer present, remove the
                // app completely. Otherwise, revoke their system privileges.
                for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
                    PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
                    mSettings.removeDisabledSystemPackageLPw(deletedAppName);
                    final String msg;
                    if (deletedPkg == null) {
                        // should have found an update, but, we didn't; remove everything
                        msg = "Updated system package " + deletedAppName
                            + " no longer exists; removing its data";
                        // Actual deletion of code and data will be handled by later
                        // reconciliation step
                    } else {
                        // found an update; revoke system privileges
                        msg = "Updated system package + " + deletedAppName
                            + " no longer exists; revoking system privileges";

                        // Don't do anything if a stub is removed from the system image. If
                        // we were to remove the uncompressed version from the /data partition,
                        // this is where it'd be done.

                        final PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
                        deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
                        deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
                    }
                    logCriticalInfo(Log.WARN, msg);
                }

                /*
                 * Make sure all system apps that we expected to appear on
                 * the userdata partition actually showed up. If they never
                 * appeared, crawl back and revive the system version.
                 */
                for (int i = 0; i < mExpectingBetter.size(); i++) {
                    final String packageName = mExpectingBetter.keyAt(i);
                    if (!mPackages.containsKey(packageName)) {
                        final File scanFile = mExpectingBetter.valueAt(i);

                        logCriticalInfo(Log.WARN, "Expected better " + packageName
                                        + " but never showed up; reverting to system");

                        final @ParseFlags int reparseFlags;
                        final @ScanFlags int rescanFlags;
                        if (FileUtils.contains(privilegedAppDir, scanFile)) {
                            reparseFlags =
                                mDefParseFlags |
                                PackageParser.PARSE_IS_SYSTEM_DIR;
                            rescanFlags =
                                scanFlags
                                | SCAN_AS_SYSTEM
                                | SCAN_AS_PRIVILEGED;
                        } else if (FileUtils.contains(systemAppDir, scanFile)) {

                            // ......

                        } else {
                            Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                            continue;
                        }

                        mSettings.enableSystemPackageLPw(packageName);

                        try {
                            scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);
                        } catch (PackageManagerException e) {
                            Slog.e(TAG, "Failed to parse original system package: "
                                   + e.getMessage());
                        }
                    }
                }

                // Uncompress and install any stubbed system applications.
                // This must be done last to ensure all stubs are replaced or disabled.
                // 最后处理子安装包,确保子安装包被整包替换或被禁用
                decompressSystemApplications(stubSystemApps, scanFlags);

                final int cachedNonSystemApps = PackageParser.sCachedPackageReadCount.get()
                    - cachedSystemApps;

                final long dataScanTime = SystemClock.uptimeMillis() - systemScanTime - startTime;
                final int dataPackagesCount = mPackages.size() - systemPackagesCount;
                Slog.i(TAG, "Finished scanning non-system apps. Time: " + dataScanTime
                       + " ms, packageCount: " + dataPackagesCount
                       + " , timePerPackage: "
                       + (dataPackagesCount == 0 ? 0 : dataScanTime / dataPackagesCount)
                       + " , cached: " + cachedNonSystemApps);
                if (mIsUpgrade && dataPackagesCount > 0) {
                    MetricsLogger.histogram(null, "ota_package_manager_data_app_avg_scan_time",
                                            ((int) dataScanTime) / dataPackagesCount);
                }
            }
            mExpectingBetter.clear();

            // Resolve the storage manager.
            // 获取存储管理器
            mStorageManagerPackage = getStorageManagerPackageName();

            // Resolve protected action filters. Only the setup wizard is allowed to
            // have a high priority filter for these actions.
            // 只允许开机向导设为高优先级
            mSetupWizardPackage = getSetupWizardPackageName();
            if (mProtectedFilters.size() > 0) {
                if (DEBUG_FILTERS && mSetupWizardPackage == null) {
                    Slog.i(TAG, "No setup wizard;"
                           + " All protected intents capped to priority 0");
                }
                for (ActivityIntentInfo filter : mProtectedFilters) {
                    if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {
                        // skip setup wizard; allow it to keep the high priority filter
                        continue;
                    }
                    filter.setPriority(0);
                }
            }

            mSystemTextClassifierPackage = getSystemTextClassifierPackageName();

            mDeferProtectedFilters = false;
            mProtectedFilters.clear();

            // Now that we know all of the shared libraries, update all clients to have
            // the correct library paths.
            // 现在我们知道所有共享库,更新所有客户端以获得正确的库路径。
            updateAllSharedLibrariesLPw(null);

            for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
                // NOTE: We ignore potential failures here during a system scan (like
                // the rest of the commands above) because there's precious little we
                // can do about it. A settings error is reported, though.
                final List<String> changedAbiCodePath =
                    adjustCpuAbisForSharedUserLPw(setting.packages, null /*scannedPackage*/);
                if (changedAbiCodePath != null && changedAbiCodePath.size() > 0) {
                    for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) {
                        final String codePathString = changedAbiCodePath.get(i);
                        try {
                            mInstaller.rmdex(codePathString,
                                             getDexCodeInstructionSet(getPreferredInstructionSet()));
                        } catch (InstallerException ignored) {
                        }
                    }
                }
                // Adjust seInfo to ensure apps which share a sharedUserId are placed in the same
                // SELinux domain.
                setting.fixSeInfoLocked();
            }

            // Now that we know all the packages we are keeping,
            // read and update their last usage times.
            mPackageUsage.read(mPackages);
            mCompilerStats.read();

            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                                SystemClock.uptimeMillis());
            Slog.i(TAG, "Time to scan packages: "
                   + ((SystemClock.uptimeMillis()-startTime)/1000f)
                   + " seconds");

            // If the platform SDK has changed since the last time we booted,
            // we need to re-grant app permission to catch any new ones that
            // appear.  This is really a hack, and means that apps can in some
            // cases get permissions that the user didn't initially explicitly
            // allow...  it would be nice to have some better way to handle
            // this situation.
            // SDK 有改变时,需处理新出现的权限
            final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);
            if (sdkUpdated) {
                Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
                       + mSdkVersion + "; regranting permissions for internal storage");
            }
            mPermissionManager.updateAllPermissions(
                                                    StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(),
                                                    mPermissionCallback);
            ver.sdkVersion = mSdkVersion;

            // If this is the first boot or an update from pre-M, and it is a normal
            // boot, then we need to initialize the default preferred apps across
            // all defined users.
            // 如果这是第一次启动或来自  pre-M 的更新,并且它是正常启动,
            //那么我们需要在所有已定义的用户中初始化默认的首选应用程序。
            if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
                for (UserInfo user : sUserManager.getUsers(true)) {
                    mSettings.applyDefaultPreferredAppsLPw(this, user.id);
                    applyFactoryDefaultBrowserLPw(user.id);
                    primeDomainVerificationsLPw(user.id);
                }
            }

            // Prepare storage for system user really early during boot,
            // since core system apps like SettingsProvider and SystemUI
            // can't wait for user to start
            // 为先于用户启动的系统应用准备存储
            final int storageFlags;
            if (StorageManager.isFileEncryptedNativeOrEmulated()) {
                storageFlags = StorageManager.FLAG_STORAGE_DE;
            } else {
                storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
            }
            List<String> deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
                                                             UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
                                                             true /* onlyCoreApps */);
            mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
                    TimingsTraceLog traceLog = new TimingsTraceLog("SystemServerTimingAsync",
                                                                   Trace.TRACE_TAG_PACKAGE_MANAGER);
                    traceLog.traceBegin("AppDataFixup");
                    try {
                        mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,
                                                StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
                    } catch (InstallerException e) {
                        Slog.w(TAG, "Trouble fixing GIDs", e);
                    }
                    traceLog.traceEnd();

                    traceLog.traceBegin("AppDataPrepare");
                    if (deferPackages == null || deferPackages.isEmpty()) {
                        return;
                    }
                    int count = 0;
                    for (String pkgName : deferPackages) {
                        PackageParser.Package pkg = null;
                        synchronized (mPackages) {
                            PackageSetting ps = mSettings.getPackageLPr(pkgName);
                            if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) {
                                pkg = ps.pkg;
                            }
                        }
                        if (pkg != null) {
                            synchronized (mInstallLock) {
                                prepareAppDataAndMigrateLIF(pkg, UserHandle.USER_SYSTEM, storageFlags,
                                                            true /* maybeMigrateAppData */);
                            }
                            count++;
                        }
                    }
                    traceLog.traceEnd();
                    Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages");
                }, "prepareAppData");

            // If this is first boot after an OTA, and a normal boot, then
            // we need to clear code cache directories.
            // Note that we do *not* clear the application profiles. These remain valid
            // across OTAs and are used to drive profile verification (post OTA) and
            // profile compilation (without waiting to collect a fresh set of profiles).
            // OTA 清除缓存不是应用数据,所以  OTA 后开机会很慢,因为要重新生成缓存
            if (mIsUpgrade && !onlyCore) {
                Slog.i(TAG, "Build fingerprint changed; clearing code caches");
                for (int i = 0; i < mSettings.mPackages.size(); i++) {
                    final PackageSetting ps = mSettings.mPackages.valueAt(i);
                    if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
                        // No apps are running this early, so no need to freeze
                        clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                                        StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
                                        | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                    }
                }
                ver.fingerprint = Build.FINGERPRINT;
            }
            // 检查默认浏览器,没有则设置
            checkDefaultBrowser();

            // clear only after permissions and other defaults have been updated
            mExistingSystemPackages.clear();
            mPromoteSystemApps = false;

            // All the changes are done during package scanning.
            ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;

            // can downgrade to reader
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
            // 保存配置,将信息写到  package.xml、package.lsit 及  pacakge-stopped.xml 文件中
            mSettings.writeLPr();
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                                SystemClock.uptimeMillis());
            // 获取一下变量
            if (!mOnlyCore) {
                mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr();
                mRequiredInstallerPackage = getRequiredInstallerLPr();
                mRequiredUninstallerPackage = getRequiredUninstallerLPr();
                mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
                if (mIntentFilterVerifierComponent != null) {
                    mIntentFilterVerifier = new IntentVerifierProxy(mContext,
                                                                    mIntentFilterVerifierComponent);
                } else {
                    mIntentFilterVerifier = null;
                }
                mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                                                                                      PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES,
                                                                                      SharedLibraryInfo.VERSION_UNDEFINED);
                mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                                                                                    PackageManager.SYSTEM_SHARED_LIBRARY_SHARED,
                                                                                    SharedLibraryInfo.VERSION_UNDEFINED);
            } else {
                mRequiredVerifierPackage = null;
                mRequiredInstallerPackage = null;
                mRequiredUninstallerPackage = null;
                mIntentFilterVerifierComponent = null;
                mIntentFilterVerifier = null;
                mServicesSystemSharedLibraryPackageName = null;
                mSharedSystemSharedLibraryPackageName = null;
            }

            mInstallerService = new PackageInstallerService(context, this);
            final Pair<ComponentName, String> instantAppResolverComponent =
                getInstantAppResolverLPr();
            if (instantAppResolverComponent != null) {
                if (DEBUG_INSTANT) {
                    Slog.d(TAG, "Set ephemeral resolver: " + instantAppResolverComponent);
                }
                mInstantAppResolverConnection = new InstantAppResolverConnection(
                                                                                 mContext, instantAppResolverComponent.first,
                                                                                 instantAppResolverComponent.second);
                mInstantAppResolverSettingsComponent =
                    getInstantAppResolverSettingsLPr(instantAppResolverComponent.first);
            } else {
                mInstantAppResolverConnection = null;
                mInstantAppResolverSettingsComponent = null;
            }
            updateInstantAppInstallerLocked(null);

            // Read and update the usage of dex files.
            // Do this at the end of PM init so that all the packages have their
            // data directory reconciled.
            // At this point we know the code paths of the packages, so we can validate
            // the disk file and build the internal cache.
            // The usage file is expected to be small so loading and verifying it
            // should take a fairly small time compare to the other activities (e.g. package
            // scanning).
            final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
            final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
            for (int userId : currentUserIds) {
                userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());
            }
            // 执行  dexopt 操作生成 .odex 后缀文件
            mDexManager.load(userPackages);
            if (mIsUpgrade) {
                MetricsLogger.histogram(null, "ota_package_manager_init_time",
                                        (int) (SystemClock.uptimeMillis() - startTime));
            }
        } // synchronized (mPackages)
    } // synchronized (mInstallLock)

    // Now after opening every single application zip, make sure they
    // are all flushed.  Not really needed, but keeps things nice and
    // tidy.
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "GC");
    // 清理及资源回收
    Runtime.getRuntime().gc();
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

    // The initial scanning above does many calls into installd while
    // holding the mPackages lock, but we're mostly interested in yelling
    // once we have a booted system.
    mInstaller.setWarnIfHeld(mPackages);

    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}

Settings.class

建立 Android 体系与 Linux 内核的用户权限对应关系

Settings()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Settings(PermissionSettings permissions, Object lock) {
    this(Environment.getDataDirectory(), permissions, lock);
}

Settings(File dataDir, PermissionSettings permission, Object lock) {
    mLock = lock;
    mPermissions = permission;
    mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
    // /data/system 目录
    mSystemDir = new File(dataDir, "system");
    mSystemDir.mkdirs();
    FileUtils.setPermissions(mSystemDir.toString(),
                             FileUtils.S_IRWXU|FileUtils.S_IRWXG
                             |FileUtils.S_IROTH|FileUtils.S_IXOTH,
                             -1, -1);
    // 记录应用相关信息:permission、package、shared-user、keyset-settings
    mSettingsFilename = new File(mSystemDir, "packages.xml");
    // package-backup.xml 是  package.xml 的备份文件,
    // package.xml 写入成功后再写入到备份文件,写入失败时可恢复到上次状态
    mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
    // 记录安装包相关信息:包名、userid、debugable、应用数据存放路径、seinfo、gid
    mPackageListFilename = new File(mSystemDir, "packages.list");
    FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);
    // sdcardfs 的作用与  fuse 相同,也是用于控制文件访问的权限。
    final File kernelDir = new File("/config/sdcardfs");
    mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;

    // Deprecated: Needed for migration
    // 强制停止运行的应用信息
    mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
    mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}

addSharedUserLPw()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
    SharedUserSetting s = mSharedUsers.get(name);
    if (s != null) {
        if (s.userId == uid) {
            // 相应的  SharedUserSetting 存在并且  userId 相同直接返回该对象
            return s;
        }
        // userId 不同则抱一个错误
        PackageManagerService.reportSettingsProblem(Log.ERROR,
                                                    "Adding duplicate shared user, keeping first: " + name);
        return null;
    }
    // 不存在新建存入到  mShsredUsers 并返回新建的对象
    s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
    s.userId = uid;
    if (addUserIdLPw(uid, s, name)) {
        mSharedUsers.put(name, s);
        return s;
    }
    return null;
}

private boolean addUserIdLPw(int uid, Object obj, Object name) {
    if (uid > Process.LAST_APPLICATION_UID) {
        // userId 没有对应的应用,不合法
        return false;
    }

    if (uid >= Process.FIRST_APPLICATION_UID) {
        // 非系统应用
        // 存入到  mUserIds 中  userId 对应的下标位置;中间空白部分用  null 填充
        int N = mUserIds.size();
        final int index = uid - Process.FIRST_APPLICATION_UID;
        while (index >= N) {
            mUserIds.add(null);
            N++;
        }
        if (mUserIds.get(index) != null) {
            PackageManagerService.reportSettingsProblem(Log.ERROR,
                                                        "Adding duplicate user id: " + uid
                                                        + " name=" + name);
            return false;
        }
        mUserIds.set(index, obj);
    } else {
        // 系统内置的  userId
        if (mOtherUserIds.get(uid) != null) {
            PackageManagerService.reportSettingsProblem(Log.ERROR,
                                                        "Adding duplicate shared id: " + uid
                                                        + " name=" + name);
            return false;
        }
        // 存入到  mOtherUserIds 中
        mOtherUserIds.put(uid, obj);
    }
    return true;
}

SettingsmSharedUsers 是一个 map 对象,利用名称作为索引管理 SharedUserSettings 对象。 Settings 中的 mOtherUserIdsmUserIds ,均是利用 userId 作为索引管理 SharedUserSettings 对象。不同的是 mOtherUserIdsSparseArray ,以系统 uid 作为键值;=mUserIds= 是 ArrayList ,普通 APK 的 uidArrayList 的下标。 SharedUserSettings 将持有一组 PackageSettingAndroidManifest.xmlandroid:sharedUserId 的属性就是应用的 UserId 其与 Linux 的 UID 相关联,而 Linux 的权限是建立再用户的基础上的,从而建立应用的权限体系。

SystemConfig.class

从文件读取系统配置

SystemConfig()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// 单例模式
public static SystemConfig getInstance() {
    synchronized (SystemConfig.class) {
        if (sInstance == null) {
            sInstance = new SystemConfig();
        }
        return sInstance;
    }
}

SystemConfig() {
    // Read configuration from system
    // 从 /system 目录读取权限配置信息
    readPermissions(Environment.buildPath(
                                          Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);

    // Read configuration from the old permissions dir
    // 旧配置文件
    readPermissions(Environment.buildPath(
                                          Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);

    // Vendors are only allowed to customze libs, features and privapp permissions
    // 从 /vendor 目录读取权限配置信息,该目录下只能自定义:libs、features、privapp 权限
    int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS;
    if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
        // For backward compatibility
        vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
    }
    readPermissions(Environment.buildPath(
                                          Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
    readPermissions(Environment.buildPath(
                                          Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);

    // Allow ODM to customize system configs as much as Vendor, because /odm is another
    // vendor partition other than /vendor.
    // 从 /odm 目录读取权限配置信息,限制和 /vendor 一样
    int odmPermissionFlag = vendorPermissionFlag;
    readPermissions(Environment.buildPath(
                                          Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
    readPermissions(Environment.buildPath(
                                          Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);

    // Allow OEM to customize features and OEM permissions
    // 从  /oem 目录读取权限配置信息,只能自定义:features 和  OEM 权限
    int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS;
    readPermissions(Environment.buildPath(
                                          Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
    readPermissions(Environment.buildPath(
                                          Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);

    // Allow Product to customize system configs around libs, features, permissions and apps
    // 从产品目录读取配置信息,可以自定义:system configs、libs、features、permissions、apps
    int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
        ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
    readPermissions(Environment.buildPath(
                                          Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
    readPermissions(Environment.buildPath(
                                          Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
}

readPermissions()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void readPermissions(File libraryDir, int permissionFlag) {
    // Read permissions from given directory.
    if (!libraryDir.exists() || !libraryDir.isDirectory()) {
        if (permissionFlag == ALLOW_ALL) {
            Slog.w(TAG, "No directory " + libraryDir + ", skipping");
        }
        return;
    }
    if (!libraryDir.canRead()) {
        Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
        return;
    }

    // Iterate over the files in the directory and scan .xml files
    File platformFile = null;
    for (File f : libraryDir.listFiles()) {
        // We'll read platform.xml last
        if (f.getPath().endsWith("etc/permissions/platform.xml")) {
            platformFile = f;
            continue;
        }

        if (!f.getPath().endsWith(".xml")) {
            Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
            continue;
        }
        if (!f.canRead()) {
            Slog.w(TAG, "Permissions library file " + f + " cannot be read");
            continue;
        }

        readPermissionsFromXml(f, permissionFlag);
    }

    // Read platform permissions last so it will take precedence
    if (platformFile != null) {
        // 解析  XML 文件并保存解析后的结果
        readPermissionsFromXml(platformFile, permissionFlag);
    }
}

扫描已安装应用信息并保存

scanDirTracedLI()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags, long currentTime) {
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
    try {
        scanDirLI(scanDir, parseFlags, scanFlags, currentTime);
    } finally {
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
}

private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime) {
    final File[] files = scanDir.listFiles();
    if (ArrayUtils.isEmpty(files)) {
        Log.d(TAG, "No files in app dir " + scanDir);
        return;
    }

    try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
                                                                                 mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
                                                                                 mParallelPackageParserCallback)) {
        // Submit files for parsing in parallel
        int fileCount = 0;
        for (File file : files) {
            // 过滤  apk、文件夹并排除临时文件
            final boolean isPackage = (isApkFile(file) || file.isDirectory())
                && !PackageInstallerService.isStageName(file.getName());
            if (!isPackage) {
                // Ignore entries which are not packages
                continue;
            }
            // 提交符合条件的文件,用于并行解析
            parallelPackageParser.submit(file, parseFlags);
            // 计数用于后面处理解析结果
            fileCount++;
        }

        // Process results one by one
        // 逐个处理解析结果
        for (; fileCount > 0; fileCount--) {
            ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
            Throwable throwable = parseResult.throwable;
            int errorCode = PackageManager.INSTALL_SUCCEEDED;

            if (throwable == null) {
                // TODO(toddke): move lower in the scan chain
                // Static shared libraries have synthetic package names
                if (parseResult.pkg.applicationInfo.isStaticSharedLibrary()) {
                    // 重命名静态共享库包:pkg.packageName + "_"  + pkg.staticSharedLibVersion
                    renameStaticSharedLibraryPackage(parseResult.pkg);
                }
                try {
                    if (errorCode == PackageManager.INSTALL_SUCCEEDED) {
                        // 继续解析其它信息
                        scanPackageChildLI(parseResult.pkg, parseFlags, scanFlags,
                                           currentTime, null);
                    }
                } catch (PackageManagerException e) {
                    errorCode = e.error;
                    Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage());
                }
            } else if (throwable instanceof PackageParser.PackageParserException) {
                PackageParser.PackageParserException e = (PackageParser.PackageParserException)
                    throwable;
                errorCode = e.error;
                Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage());
            } else {
                throw new IllegalStateException("Unexpected exception occurred while parsing "
                                                + parseResult.scanFile, throwable);
            }

            // Delete invalid userdata apps
            if ((scanFlags & SCAN_AS_SYSTEM) == 0 &&
                errorCode != PackageManager.INSTALL_SUCCEEDED) {
                logCriticalInfo(Log.WARN,
                                "Deleting invalid package at " + parseResult.scanFile);
                // 移除无用的用户安装包
                removeCodePathLI(parseResult.scanFile);
            }
        }
    }
}

ParallelPackageParser.class

这是一个辅助类用于并行解析安装包

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
static class ParseResult {

    PackageParser.Package pkg; // Parsed package
    File scanFile; // File that was parsed
    Throwable throwable; // Set if an error occurs during parsing
}

/**
 * Take the parsed package from the parsing queue, waiting if necessary until the element
 * appears in the queue.
 * @return parsed package
 */
// 取出解析结果
public ParseResult take() {
    try {
        if (mInterruptedInThread != null) {
            throw new InterruptedException("Interrupted in " + mInterruptedInThread);
        }
        return mQueue.take();
    } catch (InterruptedException e) {
        // We cannot recover from interrupt here
        Thread.currentThread().interrupt();
        throw new IllegalStateException(e);
    }
}

/**
 * Submits the file for parsing
 * @param scanFile file to scan
 * @param parseFlags parse falgs
 */
提交到线程池
    public void submit(File scanFile, int parseFlags) {
    mService.submit(() -> {
            ParseResult pr = new ParseResult();
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]");
            try {
                PackageParser pp = new PackageParser();
                // debug.separate_processes 值
                pp.setSeparateProcesses(mSeparateProcesses);
                pp.setOnlyCoreApps(mOnlyCore);
                pp.setDisplayMetrics(mMetrics);
                pp.setCacheDir(mCacheDir);
                pp.setCallback(mPackageParserCallback);
                pr.scanFile = scanFile;
                // 保存解析信息
                pr.pkg = parsePackage(pp, scanFile, parseFlags);
            } catch (Throwable e) {
                pr.throwable = e;
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
            try {
                // 保存解析结果
                mQueue.put(pr);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                // Propagate result to callers of take().
                // This is helpful to prevent main thread from getting stuck waiting on
                // ParallelPackageParser to finish in case of interruption
                mInterruptedInThread = Thread.currentThread().getName();
            }
        });
}

@VisibleForTesting
protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile,
                                             int parseFlags) throws PackageParser.PackageParserException {
    // 交由  PackageParser 类进行解析
    return packageParser.parsePackage(scanFile, parseFlags, true /* useCaches */);
}

PackageParser.class

安装包解析类

  • parsePackage()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    
    public Package parsePackage(File packageFile, int flags) throws PackageParserException {
        return parsePackage(packageFile, flags, false /* useCaches */);
    }
    
    public Package parsePackage(File packageFile, int flags, boolean useCaches)
        throws PackageParserException {
        // 这次是  true,如果从缓存中找到直接返回该对象
        Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
        if (parsed != null) {
            return parsed;
        }
    
        long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
        // 目录和单个文件调用的方法不同,但大同小异;
        // Android 目前默认都是文件夹;那我这里也就只分析解析文件夹的方法
        if (packageFile.isDirectory()) {
            parsed = parseClusterPackage(packageFile, flags);
        } else {
            parsed = parseMonolithicPackage(packageFile, flags);
        }
    
        long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
        // 缓存解析结果
        cacheResult(packageFile, flags, parsed);
        if (LOG_PARSE_TIMINGS) {
            parseTime = cacheTime - parseTime;
            cacheTime = SystemClock.uptimeMillis() - cacheTime;
            if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
                Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
                       + "ms, update_cache=" + cacheTime + " ms");
            }
        }
        return parsed;
    }
  • parseClusterPackage() 解析文件夹

    ```java /**

    • Parse all APKs contained in the given directory, treating them as a
    • single package. This also performs sanity checking, such as requiring
    • identical package name and version codes, a single base APK, and unique
    • split names.
    • Note that this does not perform signature verification; that
    • must be done separately in {@link #collectCertificates(Package, int)}. */ private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException { // 解析出所有 apk 信息 <3> final PackageLite lite = parseClusterPackageLite(packageDir, 0); if (mOnlyCoreApps && !lite.coreApp) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, “Not a coreApp: “ + packageDir); }

      // Build the split dependency tree. // 构建子包依赖树 SparseArray splitDependencies = null; final SplitAssetLoader assetLoader; if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) { try { splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite); assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags); } catch (SplitAssetDependencyLoader.IllegalDependencyException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage()); } } else { assetLoader = new DefaultSplitAssetLoader(lite, flags); }

      try { // 解析母 apk <5> final AssetManager assets = assetLoader.getBaseAssetManager(); final File baseApk = new File(lite.baseCodePath); final Package pkg = parseBaseApk(baseApk, assets, flags); if (pkg == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, “Failed to parse base APK: “ + baseApk); }

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      
      if (!ArrayUtils.isEmpty(lite.splitNames)) {
          final int num = lite.splitNames.length;
          pkg.splitNames = lite.splitNames;
          pkg.splitCodePaths = lite.splitCodePaths;
          pkg.splitRevisionCodes = lite.splitRevisionCodes;
          pkg.splitFlags = new int[num];
          pkg.splitPrivateFlags = new int[num];
          pkg.applicationInfo.splitNames = pkg.splitNames;
          pkg.applicationInfo.splitDependencies = splitDependencies;
          pkg.applicationInfo.splitClassLoaderNames = new String[num];
      
          for (int i = 0; i < num; i++) {
              // 解析子  apk,过程类似母  apk
              final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
              parseSplitApk(pkg, i, splitAssets, flags);
          }
      }
      
      pkg.setCodePath(packageDir.getCanonicalPath());
      pkg.setUse32bitAbi(lite.use32bitAbi);
      return pkg;

      } catch (IOException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, “Failed to get path: “ + lite.baseCodePath, e); } finally { IoUtils.closeQuietly(assetLoader); } } ```

  • parseClusterPackageLite()

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    
    // PackageLite 的构造方法,主要是保存应用的信息
    public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
                       boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
                       String[] splitCodePaths, int[] splitRevisionCodes) {
        this.packageName = baseApk.packageName;
        this.versionCode = baseApk.versionCode;
        this.versionCodeMajor = baseApk.versionCodeMajor;
        this.installLocation = baseApk.installLocation;
        this.verifiers = baseApk.verifiers;
        this.splitNames = splitNames;
        this.isFeatureSplits = isFeatureSplits;
        this.usesSplitNames = usesSplitNames;
        this.configForSplit = configForSplit;
        this.codePath = codePath;
        this.baseCodePath = baseApk.codePath;
        this.splitCodePaths = splitCodePaths;
        this.baseRevisionCode = baseApk.revisionCode;
        this.splitRevisionCodes = splitRevisionCodes;
        this.coreApp = baseApk.coreApp;
        this.debuggable = baseApk.debuggable;
        this.multiArch = baseApk.multiArch;
        this.use32bitAbi = baseApk.use32bitAbi;
        this.extractNativeLibs = baseApk.extractNativeLibs;
        this.isolatedSplits = baseApk.isolatedSplits;
    }
    
    static PackageLite parseClusterPackageLite(File packageDir, int flags)
        throws PackageParserException {
        final File[] files = packageDir.listFiles();
        if (ArrayUtils.isEmpty(files)) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
                                             "No packages found in split");
        }
    
        String packageName = null;
        int versionCode = 0;
    
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
        final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
        for (File file : files) {
            if (isApkFile(file)) {
                // 解析单个  APK 文件
                final ApkLite lite = parseApkLite(file, flags);
    
                // Assert that all package names and version codes are
                // consistent with the first one we encounter.
                if (packageName == null) {
                    packageName = lite.packageName;
                    versionCode = lite.versionCode;
                } else {
                    // 检查包名是否一致
                    if (!packageName.equals(lite.packageName)) {
                        throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
                                                         "Inconsistent package " + lite.packageName + " in " + file
                                                         + "; expected " + packageName);
                    }
                    // 检查版本号是否一致
                    if (versionCode != lite.versionCode) {
                        throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
                                                         "Inconsistent version " + lite.versionCode + " in " + file
                                                         + "; expected " + versionCode);
                    }
                }
                // 检查子包的唯一性
                // Assert that each split is defined only once
                if (apks.put(lite.splitName, lite) != null) {
                    throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
                                                     "Split name " + lite.splitName
                                                     + " defined more than once; most recent was " + file);
                }
            }
        }
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        // 因为  baseApk.splitName=null,所以移除  null 返回  baseApk
        final ApkLite baseApk = apks.remove(null);
        if (baseApk == null) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
                                             "Missing base APK in " + packageDir);
        }
    
        // Always apply deterministic ordering based on splitName
        final int size = apks.size();
    
        String[] splitNames = null;
        boolean[] isFeatureSplits = null;
        String[] usesSplitNames = null;
        String[] configForSplits = null;
        String[] splitCodePaths = null;
        int[] splitRevisionCodes = null;
        String[] splitClassLoaderNames = null;
        if (size > 0) {
            splitNames = new String[size];
            isFeatureSplits = new boolean[size];
            usesSplitNames = new String[size];
            configForSplits = new String[size];
            splitCodePaths = new String[size];
            splitRevisionCodes = new int[size];
            // 子包排序储存
            splitNames = apks.keySet().toArray(splitNames);
            Arrays.sort(splitNames, sSplitNameComparator);
    
            for (int i = 0; i < size; i++) {
                final ApkLite apk = apks.get(splitNames[i]);
                usesSplitNames[i] = apk.usesSplitName;
                isFeatureSplits[i] = apk.isFeatureSplit;
                configForSplits[i] = apk.configForSplit;
                splitCodePaths[i] = apk.codePath;
                splitRevisionCodes[i] = apk.revisionCode;
            }
        }
    
        final String codePath = packageDir.getAbsolutePath();
        // 构建  PackageLite 对象并返回
        return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
                               configForSplits, splitCodePaths, splitRevisionCodes);
    }
  • parseApkLite()

    ```java /**

    • Utility method that retrieves lightweight details about a single APK
    • file, including package name, split name, and install location. *
    • @param apkFile path to a single APK
    • @param flags optional parse flags, such as
    • {@link #PARSE_COLLECT_CERTIFICATES} */ public static ApkLite parseApkLite(File apkFile, int flags) throws PackageParserException { return parseApkLiteInner(apkFile, null, null, flags); }

    private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName, int flags) throws PackageParserException { // 这里 fd、debugPathName 都是 null // 这个获得 apk 绝对路径 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    
    XmlResourceParser parser = null;
    try {
        final ApkAssets apkAssets;
        try {
            // 从  apk 中加载  AndroidManifest.xml 文件
            apkAssets = fd != null
                ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
                : ApkAssets.loadFromPath(apkPath);
        } catch (IOException e) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
                                             "Failed to parse " + apkPath);
        }
        // 准备解析  AndroidManifest.xml 文件
        parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
    
        final SigningDetails signingDetails;
        if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
            // TODO: factor signature related items out of Package object
            final Package tempPkg = new Package((String) null);
            // 系统签名  apk 跳过签名相关
            final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0;
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
            try {
                // 获取签名信息
                collectCertificates(tempPkg, apkFile, skipVerify);
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
            signingDetails = tempPkg.mSigningDetails;
        } else {
            signingDetails = SigningDetails.UNKNOWN;
        }
    
        //XmlResourceParser 是  AttributeSet 的子类
        final AttributeSet attrs = parser;
        return parseApkLite(apkPath, parser, attrs, signingDetails);
    
    } catch (XmlPullParserException | IOException | RuntimeException e) {
        Slog.w(TAG, "Failed to parse " + apkPath, e);
        throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                                         "Failed to parse " + apkPath, e);
    } finally {
        IoUtils.closeQuietly(parser);
        // TODO(b/72056911): Implement and call close() on ApkAssets.
    }

    } // 主要解析 AndroidManifest.xml 文件,并将结果保存到 ApkLite 对象中 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs, SigningDetails signingDetails) throws IOException, XmlPullParserException, PackageParserException { final Pair packageSplit = parsePackageSplitNames(parser, attrs);

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
    int versionCode = 0;
    int versionCodeMajor = 0;
    int revisionCode = 0;
    boolean coreApp = false;
    boolean debuggable = false;
    boolean multiArch = false;
    boolean use32bitAbi = false;
    boolean extractNativeLibs = true;
    boolean isolatedSplits = false;
    boolean isFeatureSplit = false;
    String configForSplit = null;
    String usesSplitName = null;
    
    // 从  AndroidManifest.xml 中解析上述变量的值
    // ......
    // 构建  ApkLite 对象并返回
    return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
                       configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode,
                       installLocation, verifiers, signingDetails, coreApp, debuggable,
                       multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);

    } ```

  • parseBaseApk()

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    
    private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
        throws PackageParserException {
        final String apkPath = apkFile.getAbsolutePath();
    
        String volumeUuid = null;
        if (apkPath.startsWith(MNT_EXPAND)) {
            final int end = apkPath.indexOf('/', MNT_EXPAND.length());
            volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
        }
    
        mParseError = PackageManager.INSTALL_SUCCEEDED;
        mArchiveSourcePath = apkFile.getAbsolutePath();
    
        if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
    
        XmlResourceParser parser = null;
        try {
            // 根据  apk 路径获取资源管理器中的  AndroidManifest.xml
            final int cookie = assets.findCookieForPath(apkPath);
            if (cookie == 0) {
                throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
                                                 "Failed adding asset path: " + apkPath);
            }
            parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
            final Resources res = new Resources(assets, mMetrics, null);
    
            final String[] outError = new String[1];
            final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
            if (pkg == null) {
                throw new PackageParserException(mParseError,
                                                 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
            }
    
            pkg.setVolumeUuid(volumeUuid);
            pkg.setApplicationVolumeUuid(volumeUuid);
            pkg.setBaseCodePath(apkPath);
            pkg.setSigningDetails(SigningDetails.UNKNOWN);
    
            return pkg;
    
        } catch (PackageParserException e) {
            throw e;
        } catch (Exception e) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                                             "Failed to read manifest from " + apkPath, e);
        } finally {
            IoUtils.closeQuietly(parser);
        }
    }
    
    private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
                                      int flags, String[] outError) throws XmlPullParserException, IOException {
        // Make sure we have a valid child package name
        // 包名
        String childPackageName = parser.getAttributeValue(null, "package");
        if (validateName(childPackageName, true, false) != null) {
            mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
            return false;
        }
    
        // Child packages must be unique
        // 包名唯一
        if (childPackageName.equals(parentPkg.packageName)) {
            String message = "Child package name cannot be equal to parent package name: "
                + parentPkg.packageName;
            Slog.w(TAG, message);
            outError[0] = message;
            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
            return false;
        }
    
        // Child packages must be unique
        if (parentPkg.hasChildPackage(childPackageName)) {
            String message = "Duplicate child package:" + childPackageName;
            Slog.w(TAG, message);
            outError[0] = message;
            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
            return false;
        }
    
        // Go ahead and parse the child
        Package childPkg = new Package(childPackageName);
    
        // Child package inherits parent version code/name/target SDK
        // 解析出:版本号、名称、SDK 版本等信息
        childPkg.mVersionCode = parentPkg.mVersionCode;
        childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
        childPkg.mVersionName = parentPkg.mVersionName;
        childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
        childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
    
        childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
        if (childPkg == null) {
            // If we got null then error was set during child parsing
            return false;
        }
    
        // Set the parent-child relation
        if (parentPkg.childPackages == null) {
            parentPkg.childPackages = new ArrayList<>();
        }
        parentPkg.childPackages.add(childPkg);
        childPkg.parentPackage = parentPkg;
    
        return true;
    }

scanPackageChildLI()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
private PackageParser.Package scanPackageChildLI(PackageParser.Package pkg,
                                                 final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
                                                 @Nullable UserHandle user)
    throws PackageManagerException {
    // If the package has children and this is the first dive in the function
    // we scan the package with the SCAN_CHECK_ONLY flag set to see whether all
    // packages (parent and children) would be successfully scanned before the
    // actual scan since scanning mutates internal state and we want to atomically
    // install the package and its children.
    // 如果有子包,第一次只确保扫描到所有子包但不解析,因为解析会改变包的状态
    if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
        if (pkg.childPackages != null && pkg.childPackages.size() > 0) {
            scanFlags |= SCAN_CHECK_ONLY;
        }
    } else {
        scanFlags &= ~SCAN_CHECK_ONLY;
    }

    // Scan the parent
    PackageParser.Package scannedPkg = addForInitLI(pkg, parseFlags,
                                                    scanFlags, currentTime, user);

    // Scan the children
    final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
    for (int i = 0; i < childCount; i++) {
        PackageParser.Package childPackage = pkg.childPackages.get(i);
        addForInitLI(childPackage, parseFlags, scanFlags,
                     currentTime, user);
    }


    if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
        // 第二次进入改方法,解析所有包
        return scanPackageChildLI(pkg, parseFlags, scanFlags, currentTime, user);
    }

    return scannedPkg;
}
  • addForInitLI()

    这个方法比较长,主要作用是把扫描到的应用包信息存储到 PackageManagerService ,由于以后查询, Intent 行为主要依赖次信息库;在此过程中也会附加检查,如果包与先前已知的包相同,则发生基本验证[例如确保匹配签名,检查版本代码等]。 如果程序包未通过签名检查,则将删除 /data 上安装的版本。 如果新软件包的版本小于或等于 /data 上的版本,则将忽略它。

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    
    private PackageParser.Package addForInitLI(PackageParser.Package pkg,
                                               @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
                                               @Nullable UserHandle user)
        throws PackageManagerException {
        // 系统内置的即非  data 分区
        final boolean scanSystemPartition = (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0;
        final String renamedPkgName;
        final PackageSetting disabledPkgSetting;
        final boolean isSystemPkgUpdated;
        final boolean pkgAlreadyExists;
        PackageSetting pkgSetting;
    
        // NOTE: installPackageLI() has the same code to setup the package's
        // application info. This probably should be done lower in the call
        // stack [such as scanPackageOnly()]. However, we verify the application
        // info prior to that [in scanPackageNew()] and thus have to setup
        // the application info early.
        pkg.setApplicationVolumeUuid(pkg.volumeUuid);
        pkg.setApplicationInfoCodePath(pkg.codePath);
        pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath);
        pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths);
        pkg.setApplicationInfoResourcePath(pkg.codePath);
        pkg.setApplicationInfoBaseResourcePath(pkg.baseCodePath);
        pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
    
        synchronized (mPackages) {
            // 获取自首次安装以来已重命名的软件包的原始包名。 键是包的新名称,值是原始名称。
            renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage);
            final String realPkgName = getRealPackageName(pkg, renamedPkgName);
            if (realPkgName != null) {
                // 更改为原始包名
                ensurePackageRenamed(pkg, renamedPkgName);
            }
            //获取原始包配置,原始包必须以相同的方式签名,且必须具有相同的名称和共享用户[如果有]。
            final PackageSetting originalPkgSetting = getOriginalPackageLocked(pkg, renamedPkgName);
            // 获取当前包配置
            final PackageSetting installedPkgSetting = mSettings.getPackageLPr(pkg.packageName);
            pkgSetting = originalPkgSetting == null ? installedPkgSetting : originalPkgSetting;
            // 判断当前应用包是否已经存在
            pkgAlreadyExists = pkgSetting != null;
            final String disabledPkgName = pkgAlreadyExists ? pkgSetting.name : pkg.packageName;
            // 获取被当前应用包替换的系统应用包配置
            disabledPkgSetting = mSettings.getDisabledSystemPkgLPr(disabledPkgName);
            // 是否是系统应用的升级包
            isSystemPkgUpdated = disabledPkgSetting != null;
    
            final SharedUserSetting sharedUserSetting = (pkg.mSharedUserId != null)
                ? mSettings.getSharedUserLPw(pkg.mSharedUserId,
                                             0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true)
                : null;
    
            if (scanSystemPartition) {
                // Potentially prune child packages. If the application on the /system
                // partition has been updated via OTA, but, is still disabled by a
                // version on /data, cycle through all of its children packages and
                // remove children that are no longer defined.
                // 如果 /system 分区上的应用程序已通过  OTA 更新,但仍然被 /data 上的版本禁用,则循环遍历其所有子程序包并删除不再定义的子项。
                if (isSystemPkgUpdated) {
                    final int scannedChildCount = (pkg.childPackages != null)
                        ? pkg.childPackages.size() : 0;
                    final int disabledChildCount = disabledPkgSetting.childPackageNames != null
                        ? disabledPkgSetting.childPackageNames.size() : 0;
                    for (int i = 0; i < disabledChildCount; i++) {
                        String disabledChildPackageName =
                            disabledPkgSetting.childPackageNames.get(i);
                        boolean disabledPackageAvailable = false;
                        for (int j = 0; j < scannedChildCount; j++) {
                            PackageParser.Package childPkg = pkg.childPackages.get(j);
                            if (childPkg.packageName.equals(disabledChildPackageName)) {
                                disabledPackageAvailable = true;
                                break;
                            }
                        }
                        if (!disabledPackageAvailable) {
                            mSettings.removeDisabledSystemPackageLPw(disabledChildPackageName);
                        }
                    }
                    // we're updating the disabled package, so, scan it as the package setting
                    final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, null,
                                                                disabledPkgSetting /* pkgSetting */, null /* disabledPkgSetting */,
                                                                null /* originalPkgSetting */, null, parseFlags, scanFlags,
                                                                (pkg == mPlatformPackage), user);
                    applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage);
                    scanPackageOnlyLI(request, mFactoryTest, -1L);
                }
            }
        }
        // 新包安装路径是否改变
        final boolean newPkgChangedPaths =
            pkgAlreadyExists && !pkgSetting.codePathString.equals(pkg.codePath);
        // 新包版本是否升级
        final boolean newPkgVersionGreater =
            pkgAlreadyExists && pkg.getLongVersionCode() > pkgSetting.versionCode;
        // 系统包是否有升级
        final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated
            && newPkgChangedPaths && newPkgVersionGreater;
        if (isSystemPkgBetter) {
            // The version of the application on /system is greater than the version on
            // /data. Switch back to the application on /system.
            // It's safe to assume the application on /system will correctly scan. If not,
            // there won't be a working copy of the application.
            // /system 上的应用程序版本大于 /data 上的版本。 切换回 /system 上的应用程序。
            synchronized (mPackages) {
                // just remove the loaded entries from package lists
                mPackages.remove(pkgSetting.name);
            }
    
            final InstallArgs args = createInstallArgsForExisting(
                                                                  packageFlagsToInstallFlags(pkgSetting), pkgSetting.codePathString,
                                                                  pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting));
            // 清理资源文件
            args.cleanUpResourcesLI();
            synchronized (mPackages) {
                // 重新启用系统分区上的应用包
                mSettings.enableSystemPackageLPw(pkgSetting.name);
            }
        }
    
        if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) {
            // The version of the application on the /system partition is less than or
            // equal to the version on the /data partition. Even though the disabled system package
            // is likely to be replaced by a version on the /data partition, we make assumptions
            // that it's part of the mPackages collection during package manager initialization. So,
            // add it to mPackages if there isn't already a package in the collection and then throw
            // an exception to use the application already installed on the /data partition.
            // /system 分区上的应用程序版本小于或等于 /data 分区上的版本。仍然使用 /data 分区上的版本,但仍将改包加入到应用管理器
            synchronized (mPackages) {
                if (!mPackages.containsKey(pkg.packageName)) {
                    mPackages.put(pkg.packageName, pkg);
                }
            }
        }
    
        // Verify certificates against what was last scanned. If it is an updated priv app, we will
        // force re-collecting certificate.
        // 根据上次扫描的内容验证证书。 如果它是更新  priv-app 下的应用程序,我们将强制重新收集证书。
        final boolean forceCollect = PackageManagerServiceUtils.isApkVerificationForced(
                                                                                        disabledPkgSetting);
        // Full APK verification can be skipped during certificate collection, only if the file is
        // in verified partition, or can be verified on access (when apk verity is enabled). In both
        // cases, only data in Signing Block is verified instead of the whole file.
        // 只有当文件位于已验证的分区中,或者可以在访问时验证(apk 启用访问验证时),
        //才能在证书收集期间跳过完整的  APK 验证。 在这两种情况下,仅验证签名块中的数据而不是整个文件。
        final boolean skipVerify = ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) ||
            (forceCollect && canSkipFullPackageVerification(pkg));
        collectCertificatesLI(pkgSetting, pkg, forceCollect, skipVerify);
    
        // Reset profile if the application version is changed
        maybeClearProfilesForUpgradesLI(pkgSetting, pkg);
    
        /*
         * A new system app appeared, but we already had a non-system one of the
         * same name installed earlier.
         */
        // 出现了一个新的系统应用程序,但我们之前已经安装了一个同名的非系统应用程序。
        boolean shouldHideSystemApp = false;
        // A new application appeared on /system, but, we already have a copy of
        // the application installed on /data.
        if (scanSystemPartition && !isSystemPkgUpdated && pkgAlreadyExists
            && !pkgSetting.isSystem()) {
    
            if (!pkg.mSigningDetails.checkCapability(pkgSetting.signatures.mSigningDetails,
                                                     PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)
                && !pkgSetting.signatures.mSigningDetails.checkCapability(
                                                                          pkg.mSigningDetails,
                                                                          PackageParser.SigningDetails.CertCapabilities.ROLLBACK)) {
                // 签名不匹配,删除改包
                try (PackageFreezer freezer = freezePackage(pkg.packageName,
                                                            "scanPackageInternalLI")) {
                    deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null);
                }
                pkgSetting = null;
            } else if (newPkgVersionGreater) {
                // The application on /system is newer than the application on /data.
                // Simply remove the application on /data [keeping application data]
                // and replace it with the version on /system.
                // 系统新包版本更高,移除 /data 上的应用包但保留应用数据
                InstallArgs args = createInstallArgsForExisting(
                                                                packageFlagsToInstallFlags(pkgSetting), pkgSetting.codePathString,
                                                                pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting));
                synchronized (mInstallLock) {
                    args.cleanUpResourcesLI();
                }
            } else {
                // The application on /system is older than the application on /data. Hide
                // the application on /system and the version on /data will be scanned later
                // and re-added like an update.
                // /system 上的应用程序比 /data 上的应用程序旧。 隐藏 /system 上的应用程序,稍后将扫描 /data 上的版本,并像更新一样重新添加。
                shouldHideSystemApp = true;
            }
        }
        // 下一步 <2>
        final PackageParser.Package scannedPkg = scanPackageNewLI(pkg, parseFlags, scanFlags
                                                                  | SCAN_UPDATE_SIGNATURE, currentTime, user);
    
        if (shouldHideSystemApp) {
            synchronized (mPackages) {
                // 停用需要隐藏的系统包
                mSettings.disableSystemPackageLPw(pkg.packageName, true);
            }
        }
        return scannedPkg;
    }
  • scanPackageNewLI()

    这个方法主要是有新应用包时(比如 ota 引入)确认是否要替换原应用包

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    
    @GuardedBy("mInstallLock")
    private PackageParser.Package scanPackageNewLI(@NonNull PackageParser.Package pkg,
                                                   final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
                                                   @Nullable UserHandle user) throws PackageManagerException {
    
        final String renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage);
        final String realPkgName = getRealPackageName(pkg, renamedPkgName);
        if (realPkgName != null) {
            ensurePackageRenamed(pkg, renamedPkgName);
        }
        final PackageSetting originalPkgSetting = getOriginalPackageLocked(pkg, renamedPkgName);
        final PackageSetting pkgSetting = mSettings.getPackageLPr(pkg.packageName);
        final PackageSetting disabledPkgSetting =
            mSettings.getDisabledSystemPkgLPr(pkg.packageName);
        // 调整扫描参数
        scanFlags = adjustScanFlags(scanFlags, pkgSetting, disabledPkgSetting, user, pkg);
        synchronized (mPackages) {
            // 根据给定的策略标志将策略应用于已解析的包。
            applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage);
            // 断言解析的包根据给定的策略有效。 如果包无效,无论出于何种原因,抛出  PackageManagerException。
            assertPackageIsValid(pkg, parseFlags, scanFlags);
    
            SharedUserSetting sharedUserSetting = null;
            if (pkg.mSharedUserId != null) {
                // SIDE EFFECTS; may potentially allocate a new shared user
                // 如果不存在则新建
                sharedUserSetting = mSettings.getSharedUserLPw(
                                                               pkg.mSharedUserId, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/);
            }
    
            boolean scanSucceeded = false;
            try {
                final ScanRequest request = new ScanRequest(pkg, sharedUserSetting,
                                                            pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting,
                                                            originalPkgSetting, realPkgName, parseFlags, scanFlags,
                                                            (pkg == mPlatformPackage), user);
                // 前面主要是解析  AndroidManifest.xm 获取应用的基本信息;同时确定应用使用的版本
                // 这个方法将解析四大组件相关信息,并储存以供以后查询,比如  Intent 相关 <3>
                final ScanResult result = scanPackageOnlyLI(request, mFactoryTest, currentTime);
                if (result.success) {
                    // 提交结果 <4>
                    commitScanResultsLocked(request, result);
                }
                scanSucceeded = true;
            } finally {
                if (!scanSucceeded && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
                    // DELETE_DATA_ON_FAILURES is only used by frozen paths
                    // 失败则清理无效数据
                    destroyAppDataLIF(pkg, UserHandle.USER_ALL,
                                      StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
                    destroyAppProfilesLIF(pkg, UserHandle.USER_ALL);
                }
            }
        }
        return pkg;
    }
  • scanPackageOnlyLI()

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    
    @GuardedBy("mInstallLock")
    private static @NonNull ScanResult scanPackageOnlyLI(@NonNull ScanRequest request,
                                                         boolean isUnderFactoryTest, long currentTime)
        throws PackageManagerException {
        final PackageParser.Package pkg = request.pkg;
        PackageSetting pkgSetting = request.pkgSetting;
        final PackageSetting disabledPkgSetting = request.disabledPkgSetting;
        final PackageSetting originalPkgSetting = request.originalPkgSetting;
        final @ParseFlags int parseFlags = request.parseFlags;
        final @ScanFlags int scanFlags = request.scanFlags;
        final String realPkgName = request.realPkgName;
        final SharedUserSetting sharedUserSetting = request.sharedUserSetting;
        final UserHandle user = request.user;
        final boolean isPlatformPackage = request.isPlatformPackage;
    
        List<String> changedAbiCodePath = null;
    
        DexManager.maybeLogUnexpectedPackageDetails(pkg);
    
        // Initialize package source and resource directories
        // 初始化资源、源码目录
        final File scanFile = new File(pkg.codePath);
        final File destCodeFile = new File(pkg.applicationInfo.getCodePath());
        final File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
    
        // We keep references to the derived CPU Abis from settings in oder to reuse
        // them in the case where we're not upgrading or booting for the first time.
        // 如果不是系统升级或首次开机可以使用以前保存的  CPU Abis 的引用
        String primaryCpuAbiFromSettings = null;
        String secondaryCpuAbiFromSettings = null;
        // 需要生成  abi 引用
        boolean needToDeriveAbi = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0;
    
        if (!needToDeriveAbi) {
            // 不需要生成  abi 引用时,确保是否有旧的存在,没有则要生成
            if (pkgSetting != null) {
                primaryCpuAbiFromSettings = pkgSetting.primaryCpuAbiString;
                secondaryCpuAbiFromSettings = pkgSetting.secondaryCpuAbiString;
            } else {
                // Re-scanning a system package after uninstalling updates; need to derive ABI
                needToDeriveAbi = true;
            }
        }
        // sharedUser 不一致,需要重新生成  PackageSetting
        if (pkgSetting != null && pkgSetting.sharedUser != sharedUserSetting) {
            PackageManagerService.reportSettingsProblem(Log.WARN,
                                                        "Package " + pkg.packageName + " shared user changed from "
                                                        + (pkgSetting.sharedUser != null
                                                           ? pkgSetting.sharedUser.name : "<nothing>")
                                                        + " to "
                                                        + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
                                                        + "; replacing with new");
            pkgSetting = null;
        }
    
        String[] usesStaticLibraries = null;
        if (pkg.usesStaticLibraries != null) {
            usesStaticLibraries = new String[pkg.usesStaticLibraries.size()];
            pkg.usesStaticLibraries.toArray(usesStaticLibraries);
        }
        // 更新  PackageSetting 没有则要生成
        final boolean createNewPackage = (pkgSetting == null);
        if (createNewPackage) {
            final String parentPackageName = (pkg.parentPackage != null)
                ? pkg.parentPackage.packageName : null;
            final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
            final boolean virtualPreload = (scanFlags & SCAN_AS_VIRTUAL_PRELOAD) != 0;
            // REMOVE SharedUserSetting from method; update in a separate call
            pkgSetting = Settings.createNewSetting(pkg.packageName, originalPkgSetting,
                                                   disabledPkgSetting, realPkgName, sharedUserSetting, destCodeFile,
                                                   destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,
                                                   pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi,
                                                   pkg.mVersionCode, pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags,
                                                   user, true /*allowInstall*/, instantApp, virtualPreload,
                                                   parentPackageName, pkg.getChildPackageNames(),
                                                   UserManagerService.getInstance(), usesStaticLibraries,
                                                   pkg.usesStaticLibrariesVersions);
        } else {
            // REMOVE SharedUserSetting from method; update in a separate call.
            //
            // TODO(narayan): This update is bogus. nativeLibraryDir & primaryCpuAbi,
            // secondaryCpuAbi are not known at this point so we always update them
            // to null here, only to reset them at a later point.
            Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, sharedUserSetting,
                                          destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryDir,
                                          pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi,
                                          pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags,
                                          pkg.getChildPackageNames(), UserManagerService.getInstance(),
                                          usesStaticLibraries, pkg.usesStaticLibrariesVersions);
        }
        if (createNewPackage && originalPkgSetting != null) {
            // This is the initial transition from the original package, so,
            // fix up the new package's name now. We must do this after looking
            // up the package under its new name, so getPackageLP takes care of
            // fiddling things correctly.
            pkg.setPackageName(originalPkgSetting.name);
    
            // File a report about this.
            String msg = "New package " + pkgSetting.realName
                + " renamed to replace old package " + pkgSetting.name;
            reportSettingsProblem(Log.WARN, msg);
        }
    
        final int userId = (user == null ? UserHandle.USER_SYSTEM : user.getIdentifier());
        // for existing packages, change the install state; but, only if it's explicitly specified
        // 更改已存在应用包的安装状态
        if (!createNewPackage) {
            final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
            final boolean fullApp = (scanFlags & SCAN_AS_FULL_APP) != 0;
            setInstantAppForUser(pkgSetting, userId, instantApp, fullApp);
        }
        if (disabledPkgSetting != null) {
            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
        }
    
        // Apps which share a sharedUserId must be placed in the same selinux domain. If this
        // package is the first app installed as this shared user, set seInfoTargetSdkVersion to its
        // targetSdkVersion. These are later adjusted in PackageManagerService's constructor to be
        // the lowest targetSdkVersion of all apps within the shared user, which corresponds to the
        // least restrictive selinux domain.
        // NOTE: As new packages are installed / updated, the shared user's seinfoTargetSdkVersion
        // will NOT be modified until next boot, even if a lower targetSdkVersion is used. This
        // ensures that all packages continue to run in the same selinux domain.
        // 共享  sharedUserId 的应用必须放在同一个  selinux 域中。 如果此程序包是作为此共享用户安装的第一个应用程序,
        // 请将  seInfoTargetSdkVersion 设置为其  targetSdkVersion。 这些稍后在  PackageManagerService 的构造函
        // 数中调整为共享用户中所有应用程序的最低  targetSdkVersion,这对应于限制性最小的  selinux 域。
        // 注意:在安装/更新新软件包时,即使使用较低的  targetSdkVersion,共享用户的  seinfoTargetSdkVersion
        // 也不会被修改,直到下次引导。 这可确保所有包继续在同一  selinux 域中运行。
        final int targetSdkVersion =
            ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) ?
            sharedUserSetting.seInfoTargetSdkVersion : pkg.applicationInfo.targetSdkVersion;
        // TODO(b/71593002): isPrivileged for sharedUser and appInfo should never be out of sync.
        // They currently can be if the sharedUser apps are signed with the platform key.
        final boolean isPrivileged = (sharedUserSetting != null) ?
            sharedUserSetting.isPrivileged() | pkg.isPrivileged() : pkg.isPrivileged();
    
        pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged,
                                                           pkg.applicationInfo.targetSandboxVersion, targetSdkVersion);
        pkg.applicationInfo.seInfoUser = SELinuxUtil.assignSeinfoUser(pkgSetting.readUserState(
                                                                                               userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId));
    
        pkg.mExtras = pkgSetting;
        pkg.applicationInfo.processName = fixProcessName(
                                                         pkg.applicationInfo.packageName,
                                                         pkg.applicationInfo.processName);
    
        if (!isPlatformPackage) {
            // Get all of our default paths setup
            pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM);
        }
        // 更新  abi 引用
        final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
    
        if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
            if (needToDeriveAbi) {
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
                final boolean extractNativeLibs = !pkg.isLibrary();
                derivePackageAbi(pkg, cpuAbiOverride, extractNativeLibs);
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    
                // Some system apps still use directory structure for native libraries
                // in which case we might end up not detecting abi solely based on apk
                // structure. Try to detect abi based on directory structure.
                if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() &&
                    pkg.applicationInfo.primaryCpuAbi == null) {
                    setBundledAppAbisAndRoots(pkg, pkgSetting);
                    setNativeLibraryPaths(pkg, sAppLib32InstallDir);
                }
            } else {
                // This is not a first boot or an upgrade, don't bother deriving the
                // ABI during the scan. Instead, trust the value that was stored in the
                // package setting.
                pkg.applicationInfo.primaryCpuAbi = primaryCpuAbiFromSettings;
                pkg.applicationInfo.secondaryCpuAbi = secondaryCpuAbiFromSettings;
    
                setNativeLibraryPaths(pkg, sAppLib32InstallDir);
    
                if (DEBUG_ABI_SELECTION) {
                    Slog.i(TAG, "Using ABIS and native lib paths from settings : " +
                           pkg.packageName + " " + pkg.applicationInfo.primaryCpuAbi + ", " +
                           pkg.applicationInfo.secondaryCpuAbi);
                }
            }
        } else {
            if ((scanFlags & SCAN_MOVE) != 0) {
                // We haven't run dex-opt for this move (since we've moved the compiled output too)
                // but we already have this packages package info in the PackageSetting. We just
                // use that and derive the native library path based on the new codepath.
                pkg.applicationInfo.primaryCpuAbi = pkgSetting.primaryCpuAbiString;
                pkg.applicationInfo.secondaryCpuAbi = pkgSetting.secondaryCpuAbiString;
            }
    
            // Set native library paths again. For moves, the path will be updated based on the
            // ABIs we've determined above. For non-moves, the path will be updated based on the
            // ABIs we determined during compilation, but the path will depend on the final
            // package path (after the rename away from the stage path).
            setNativeLibraryPaths(pkg, sAppLib32InstallDir);
        }
    
        // This is a special case for the "system" package, where the ABI is
        // dictated by the zygote configuration (and init.rc). We should keep track
        // of this ABI so that we can deal with "normal" applications that run under
        // the same UID correctly.
        if (isPlatformPackage) {
            pkg.applicationInfo.primaryCpuAbi = VMRuntime.getRuntime().is64Bit() ?
                Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
        }
    
        // If there's a mismatch between the abi-override in the package setting
        // and the abiOverride specified for the install. Warn about this because we
        // would've already compiled the app without taking the package setting into
        // account.
        if ((scanFlags & SCAN_NO_DEX) == 0 && (scanFlags & SCAN_NEW_INSTALL) != 0) {
            if (cpuAbiOverride == null && pkg.packageName != null) {
                Slog.w(TAG, "Ignoring persisted ABI override " + cpuAbiOverride +
                       " for package " + pkg.packageName);
            }
        }
    
        pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
        pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
        pkgSetting.cpuAbiOverrideString = cpuAbiOverride;
    
        // Copy the derived override back to the parsed package, so that we can
        // update the package settings accordingly.
        pkg.cpuAbiOverride = cpuAbiOverride;
    
        // Push the derived path down into PackageSettings so we know what to
        // clean up at uninstall time.
        pkgSetting.legacyNativeLibraryPathString = pkg.applicationInfo.nativeLibraryRootDir;
    
        if ((scanFlags & SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
            // We don't do this here during boot because we can do it all
            // at once after scanning all existing packages.
            //
            // We also do this *before* we perform dexopt on this package, so that
            // we can avoid redundant dexopts, and also to make sure we've got the
            // code and package path correct.
            changedAbiCodePath =
                adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages, pkg);
        }
    
        if (isUnderFactoryTest && pkg.requestedPermissions.contains(
                                                                    android.Manifest.permission.FACTORY_TEST)) {
            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
        }
    
        if (isSystemApp(pkg)) {
            pkgSetting.isOrphaned = true;
        }
    
        // Take care of first install / last update times.
        // 记录首次安装时间和最后更新时间
        final long scanFileTime = getLastModifiedTime(pkg);
        if (currentTime != 0) {
            if (pkgSetting.firstInstallTime == 0) {
                pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
            } else if ((scanFlags & SCAN_UPDATE_TIME) != 0) {
                pkgSetting.lastUpdateTime = currentTime;
            }
        } else if (pkgSetting.firstInstallTime == 0) {
            // We need *something*.  Take time time stamp of the file.
            pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
        } else if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
            if (scanFileTime != pkgSetting.timeStamp) {
                // A package on the system image has changed; consider this
                // to be an update.
                pkgSetting.lastUpdateTime = scanFileTime;
            }
        }
        pkgSetting.setTimeStamp(scanFileTime);
    
        pkgSetting.pkg = pkg;
        pkgSetting.pkgFlags = pkg.applicationInfo.flags;
        if (pkg.getLongVersionCode() != pkgSetting.versionCode) {
            pkgSetting.versionCode = pkg.getLongVersionCode();
        }
        // Update volume if needed
        final String volumeUuid = pkg.applicationInfo.volumeUuid;
        if (!Objects.equals(volumeUuid, pkgSetting.volumeUuid)) {
            Slog.i(PackageManagerService.TAG,
                   "Update" + (pkgSetting.isSystem() ? " system" : "")
                   + " package " + pkg.packageName
                   + " volume from " + pkgSetting.volumeUuid
                   + " to " + volumeUuid);
            pkgSetting.volumeUuid = volumeUuid;
        }
    
        return new ScanResult(true, pkgSetting, changedAbiCodePath);
    }
  • commitScanResultsLocked()

    提交包扫描并修改系统状态。

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    
    @GuardedBy("mPackages")
    private void commitScanResultsLocked(@NonNull ScanRequest request, @NonNull ScanResult result)
        throws PackageManagerException {
        final PackageParser.Package pkg = request.pkg;
        final PackageParser.Package oldPkg = request.oldPkg;
        final @ParseFlags int parseFlags = request.parseFlags;
        final @ScanFlags int scanFlags = request.scanFlags;
        final PackageSetting oldPkgSetting = request.oldPkgSetting;
        final PackageSetting originalPkgSetting = request.originalPkgSetting;
        final PackageSetting disabledPkgSetting = request.disabledPkgSetting;
        final UserHandle user = request.user;
        final String realPkgName = request.realPkgName;
        final PackageSetting pkgSetting = result.pkgSetting;
        final List<String> changedAbiCodePath = result.changedAbiCodePath;
        final boolean newPkgSettingCreated = (result.pkgSetting != request.pkgSetting);
        // 新旧包  sharedUser 不一致
        if (newPkgSettingCreated) {
            if (originalPkgSetting != null) {
                mSettings.addRenamedPackageLPw(pkg.packageName, originalPkgSetting.name);
            }
            // 新建用户
            mSettings.addUserToSettingLPw(pkgSetting);
            // 原应用包数据传给新包,原包数据将不会保留
            if (originalPkgSetting != null && (scanFlags & SCAN_CHECK_ONLY) == 0) {
                mTransferedPackages.add(originalPkgSetting.name);
            }
        }
        pkg.applicationInfo.uid = pkgSetting.appId;
        // 更新用户状态
        mSettings.writeUserRestrictionsLPw(pkgSetting, oldPkgSetting);
    
        if ((scanFlags & SCAN_CHECK_ONLY) == 0 && realPkgName != null) {
            mTransferedPackages.add(pkg.packageName);
        }
    
        if ((scanFlags & SCAN_BOOTING) == 0
            && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
            // Check all shared libraries and map to their actual file path.
            // We only do this here for apps not on a system dir, because those
            // are the only ones that can fail an install due to this.  We
            // will take care of the system apps by updating all of their
            // library paths after the scan is done. Also during the initial
            // scan don't update any libs as we do this wholesale after all
            // apps are scanned to avoid dependency based scanning.
            // 检查所有非系统目录上的共享库并映射到它们的实际文件路径。
            updateSharedLibrariesLPr(pkg, null);
        }
    
        // All versions of a static shared library are referenced with the same
        // package name. Internally, we use a synthetic package name to allow
        // multiple versions of the same shared library to be installed. So,
        // we need to generate the synthetic package name of the latest shared
        // library in order to compare signatures.
        // 使用相同的包名称引用静态共享库的所有版本。 在内部,我们使用合成包名称来允许安装同一共享库的多个版本。
        // 因此,我们需要生成最新共享库的合成包名称,以便比较签名。
        // 以下处理应用包的签名信息
        PackageSetting signatureCheckPs = pkgSetting;
        if (pkg.applicationInfo.isStaticSharedLibrary()) {
            SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
            if (libraryEntry != null) {
                signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
            }
        }
    
        final KeySetManagerService ksms = mSettings.mKeySetManagerService;
        if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) {
            if (ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) {
                // We just determined the app is signed correctly, so bring
                // over the latest parsed certs.
                pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
            } else {
                if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                    throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                                                      "Package " + pkg.packageName + " upgrade keys do not match the "
                                                      + "previously installed version");
                } else {
                    pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
                    String msg = "System package " + pkg.packageName
                        + " signature changed; retaining data.";
                    reportSettingsProblem(Log.WARN, msg);
                }
            }
        } else {
            try {
                final boolean compareCompat = isCompatSignatureUpdateNeeded(pkg);
                final boolean compareRecover = isRecoverSignatureUpdateNeeded(pkg);
                final boolean compatMatch = verifySignatures(signatureCheckPs, disabledPkgSetting,
                                                             pkg.mSigningDetails, compareCompat, compareRecover);
                // The new KeySets will be re-added later in the scanning process.
                if (compatMatch) {
                    synchronized (mPackages) {
                        ksms.removeAppKeySetDataLPw(pkg.packageName);
                    }
                }
                // We just determined the app is signed correctly, so bring
                // over the latest parsed certs.
                pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
    
    
                // if this is is a sharedUser, check to see if the new package is signed by a newer
                // signing certificate than the existing one, and if so, copy over the new details
                if (signatureCheckPs.sharedUser != null) {
                    if (pkg.mSigningDetails.hasAncestor(
                                                        signatureCheckPs.sharedUser.signatures.mSigningDetails)) {
                        signatureCheckPs.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails;
                    }
                    if (signatureCheckPs.sharedUser.signaturesChanged == null) {
                        signatureCheckPs.sharedUser.signaturesChanged = Boolean.FALSE;
                    }
                }
            } catch (PackageManagerException e) {
                if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                    throw e;
                }
                // The signature has changed, but this package is in the system
                // image...  let's recover!
                pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
    
                // If the system app is part of a shared user we allow that shared user to change
                // signatures as well as part of an OTA. We still need to verify that the signatures
                // are consistent within the shared user for a given boot, so only allow updating
                // the signatures on the first package scanned for the shared user (i.e. if the
                // signaturesChanged state hasn't been initialized yet in SharedUserSetting).
                // OTA 更改了签名信息,更新签名信息
                if (signatureCheckPs.sharedUser != null) {
                    if (signatureCheckPs.sharedUser.signaturesChanged != null &&
                        compareSignatures(
                                          signatureCheckPs.sharedUser.signatures.mSigningDetails.signatures,
                                          pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH) {
                        throw new PackageManagerException(
                                                          INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
                                                          "Signature mismatch for shared user: " + pkgSetting.sharedUser);
                    }
    
                    signatureCheckPs.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails;
                    signatureCheckPs.sharedUser.signaturesChanged = Boolean.TRUE;
                }
                // File a report about this.
                String msg = "System package " + pkg.packageName
                    + " signature changed; retaining data.";
                reportSettingsProblem(Log.WARN, msg);
            } catch (IllegalArgumentException e) {
            }
        }
        // 权限相关
        if ((scanFlags & SCAN_CHECK_ONLY) == 0 && pkg.mAdoptPermissions != null) {
            // This package wants to adopt ownership of permissions from
            // another package.
            for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
                final String origName = pkg.mAdoptPermissions.get(i);
                final PackageSetting orig = mSettings.getPackageLPr(origName);
                if (orig != null) {
                    if (verifyPackageUpdateLPr(orig, pkg)) {
                        Slog.i(TAG, "Adopting permissions from " + origName + " to "
                               + pkg.packageName);
                        mSettings.mPermissions.transferPermissions(origName, pkg.packageName);
                    }
                }
            }
        }
        // 处理  cpu abi
        if (changedAbiCodePath != null && changedAbiCodePath.size() > 0) {
            for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) {
                final String codePathString = changedAbiCodePath.get(i);
                try {
                    mInstaller.rmdex(codePathString,
                                     getDexCodeInstructionSet(getPreferredInstructionSet()));
                } catch (InstallerException ignored) {
                }
            }
        }
    
        if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
            if (oldPkgSetting != null) {
                synchronized (mPackages) {
                    mSettings.mPackages.put(oldPkgSetting.name, oldPkgSetting);
                }
            }
        } else {
            final int userId = user == null ? 0 : user.getIdentifier();
            // Modify state for the given package setting
            // 提交扫描结果到  PackageManagerService
            commitPackageSettings(pkg, oldPkg, pkgSetting, user, scanFlags,
                                  (parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/);
            if (pkgSetting.getInstantApp(userId)) {
                mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId);
            }
        }
    }
  • commitPackageSettings()

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    
    private void commitPackageSettings(PackageParser.Package pkg,
                                       @Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting, UserHandle user,
                                       final @ScanFlags int scanFlags, boolean chatty) {
        final String pkgName = pkg.packageName;
        // mCustomResolverComponentName 定义于:R.string.config_customResolverActivity
        if (mCustomResolverComponentName != null &&
            mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
            // 用自定义的替换默认的  ResolverActivity;前面说过  ResolverActivity 的用处
            // Intent 有多个匹配项时,展示这些匹配项供用户选择一个
            setUpCustomResolverActivity(pkg);
        }
        // 处理特殊包名:android
        if (pkg.packageName.equals("android")) {
            synchronized (mPackages) {
                if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
                    // Set up information for our fall-back user intent resolution activity.
                    // 系统应用包
                    mPlatformPackage = pkg;
                    pkg.mVersionCode = mSdkVersion;
                    pkg.mVersionCodeMajor = 0;
                    mAndroidApplication = pkg.applicationInfo;
                    // 没有自定义  ResolverActivity;初始化默认  ResolverActivity
                    if (!mResolverReplaced) {
                        mResolveActivity.applicationInfo = mAndroidApplication;
                        mResolveActivity.name = ResolverActivity.class.getName();
                        mResolveActivity.packageName = mAndroidApplication.packageName;
                        mResolveActivity.processName = "system:ui";
                        mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
                        mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER;
                        mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
                        mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert;
                        mResolveActivity.exported = true;
                        mResolveActivity.enabled = true;
                        mResolveActivity.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
                        mResolveActivity.configChanges = ActivityInfo.CONFIG_SCREEN_SIZE
                            | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE
                            | ActivityInfo.CONFIG_SCREEN_LAYOUT
                            | ActivityInfo.CONFIG_ORIENTATION
                            | ActivityInfo.CONFIG_KEYBOARD
                            | ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
                        mResolveInfo.activityInfo = mResolveActivity;
                        mResolveInfo.priority = 0;
                        mResolveInfo.preferredOrder = 0;
                        mResolveInfo.match = 0;
                        mResolveComponentName = new ComponentName(
                                                                  mAndroidApplication.packageName, mResolveActivity.name);
                    }
                }
            }
        }
    
        ArrayList<PackageParser.Package> clientLibPkgs = null;
        // writer
        synchronized (mPackages) {
            boolean hasStaticSharedLibs = false;
    
            // Any app can add new static shared libraries
            // 更新链接库信息
            if (pkg.staticSharedLibName != null) {
                // Static shared libs don't allow renaming as they have synthetic package
                // names to allow install of multiple versions, so use name from manifest.
                if (addSharedLibraryLPw(null, pkg.packageName, pkg.staticSharedLibName,
                                        pkg.staticSharedLibVersion, SharedLibraryInfo.TYPE_STATIC,
                                        pkg.manifestPackageName, pkg.getLongVersionCode())) {
                    hasStaticSharedLibs = true;
                } else {
                    Slog.w(TAG, "Package " + pkg.packageName + " library "
                           + pkg.staticSharedLibName + " already exists; skipping");
                }
                // Static shared libs cannot be updated once installed since they
                // use synthetic package name which includes the version code, so
                // not need to update other packages's shared lib dependencies.
            }
            // 系统应用包更新时,链接库相关更新
            if (!hasStaticSharedLibs
                && (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                // Only system apps can add new dynamic shared libraries.
                if (pkg.libraryNames != null) {
                    for (int i = 0; i < pkg.libraryNames.size(); i++) {
                        String name = pkg.libraryNames.get(i);
                        boolean allowed = false;
                        if (pkg.isUpdatedSystemApp()) {
                            // New library entries can only be added through the
                            // system image.  This is important to get rid of a lot
                            // of nasty edge cases: for example if we allowed a non-
                            // system update of the app to add a library, then uninstalling
                            // the update would make the library go away, and assumptions
                            // we made such as through app install filtering would now
                            // have allowed apps on the device which aren't compatible
                            // with it.  Better to just have the restriction here, be
                            // conservative, and create many fewer cases that can negatively
                            // impact the user experience.
                            final PackageSetting sysPs = mSettings
                                .getDisabledSystemPkgLPr(pkg.packageName);
                            if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) {
                                for (int j = 0; j < sysPs.pkg.libraryNames.size(); j++) {
                                    if (name.equals(sysPs.pkg.libraryNames.get(j))) {
                                        allowed = true;
                                        break;
                                    }
                                }
                            }
                        } else {
                            allowed = true;
                        }
                        if ((scanFlags & SCAN_BOOTING) == 0) {
                            // If we are not booting, we need to update any applications
                            // that are clients of our shared library.  If we are booting,
                            // this will all be done once the scan is complete.
                            clientLibPkgs = updateAllSharedLibrariesLPw(pkg);
                        }
                    }
                }
            }
    
            if ((scanFlags & SCAN_BOOTING) != 0) {
                // No apps can run during boot scan, so they don't need to be frozen
            } else if ((scanFlags & SCAN_DONT_KILL_APP) != 0) {
                // Caller asked to not kill app, so it's probably not frozen
            } else if ((scanFlags & SCAN_IGNORE_FROZEN) != 0) {
                // Caller asked us to ignore frozen check for some reason; they
                // probably didn't know the package name
            } else {
                // We're doing major surgery on this package, so it better be frozen
                // right now to keep it from launching
                checkPackageFrozen(pkgName);
            }
    
            // Also need to kill any apps that are dependent on the library.
            if (clientLibPkgs != null) {
                for (int i=0; i<clientLibPkgs.size(); i++) {
                    PackageParser.Package clientPkg = clientLibPkgs.get(i);
                    killApplication(clientPkg.applicationInfo.packageName,
                                    clientPkg.applicationInfo.uid, "update lib");
                }
            }
    
            // writer
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
            // PackageManagerService 存储四大组件信息
            synchronized (mPackages) {
                // We don't expect installation to fail beyond this point
    
                // Add the new setting to mSettings
                mSettings.insertPackageSettingLPw(pkgSetting, pkg);
                // Add the new setting to mPackages
                mPackages.put(pkg.applicationInfo.packageName, pkg);
                // Make sure we don't accidentally delete its data.
                final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
                while (iter.hasNext()) {
                    PackageCleanItem item = iter.next();
                    if (pkgName.equals(item.packageName)) {
                        iter.remove();
                    }
                }
    
                // Add the package's KeySets to the global KeySetManagerService
                KeySetManagerService ksms = mSettings.mKeySetManagerService;
                ksms.addScannedPackageLPw(pkg);
                // Provider
                int N = pkg.providers.size();
                StringBuilder r = null;
                int i;
                for (i=0; i<N; i++) {
                    PackageParser.Provider p = pkg.providers.get(i);
    
                    // ......
    
                }
                // Service
                N = pkg.services.size();
                r = null;
                for (i=0; i<N; i++) {
                    PackageParser.Service s = pkg.services.get(i);
                    s.info.processName = fixProcessName(pkg.applicationInfo.processName,
                                                        s.info.processName);
                    mServices.addService(s);
                    if (chatty) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ');
                        }
                        r.append(s.info.name);
                    }
                }
                // Receiver
                N = pkg.receivers.size();
                r = null;
                for (i=0; i<N; i++) {
                    PackageParser.Activity a = pkg.receivers.get(i);
                    a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                                                        a.info.processName);
                    mReceivers.addActivity(a, "receiver");
                    if (chatty) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ');
                        }
                        r.append(a.info.name);
                    }
                }
                // Activity
                N = pkg.activities.size();
                r = null;
                for (i=0; i<N; i++) {
                    PackageParser.Activity a = pkg.activities.get(i);
                    a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                                                        a.info.processName);
                    mActivities.addActivity(a, "activity");
                    if (chatty) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ');
                        }
                        r.append(a.info.name);
                    }
                }
                // Permission 不允许临时应用程序定义新权限和权限组。
                // Don't allow ephemeral applications to define new permissions groups.
                if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
                } else {
                    mPermissionManager.addAllPermissionGroups(pkg, chatty);
                }
    
                // Don't allow ephemeral applications to define new permissions.
                if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
                } else {
                    mPermissionManager.addAllPermissions(pkg, chatty);
                }
                // Instrumentation
                N = pkg.instrumentation.size();
                r = null;
                for (i=0; i<N; i++) {
                    PackageParser.Instrumentation a = pkg.instrumentation.get(i);
                    a.info.packageName = pkg.applicationInfo.packageName;
                    a.info.sourceDir = pkg.applicationInfo.sourceDir;
                    a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
                    a.info.splitNames = pkg.splitNames;
                    a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs;
                    a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs;
                    a.info.splitDependencies = pkg.applicationInfo.splitDependencies;
                    a.info.dataDir = pkg.applicationInfo.dataDir;
                    a.info.deviceProtectedDataDir = pkg.applicationInfo.deviceProtectedDataDir;
                    a.info.credentialProtectedDataDir = pkg.applicationInfo.credentialProtectedDataDir;
                    a.info.primaryCpuAbi = pkg.applicationInfo.primaryCpuAbi;
                    a.info.secondaryCpuAbi = pkg.applicationInfo.secondaryCpuAbi;
                    a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
                    a.info.secondaryNativeLibraryDir = pkg.applicationInfo.secondaryNativeLibraryDir;
                    mInstrumentation.put(a.getComponentName(), a);
                    if (chatty) {
                        if (r == null) {
                            r = new StringBuilder(256);
                        } else {
                            r.append(' ');
                        }
                        r.append(a.info.name);
                    }
                }
                // Protected Broadcast
                if (pkg.protectedBroadcasts != null) {
                    N = pkg.protectedBroadcasts.size();
                    synchronized (mProtectedBroadcasts) {
                        for (i = 0; i < N; i++) {
                            mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
                        }
                    }
                }
    
            }