我是靠谱客的博主 曾经龙猫,这篇文章主要介绍关于 PackageManagerService,现在分享给大家,希望可以做个参考。

文章目录

      • 了解 PackageManagerService
      • 了解 pm/Settings.java
      • 服务初始化过程
      • 处理 permission 文件
      • 扫描应用目录的过程
      • 当发出 Intent 时,如果系统中应用有多个相应,会弹出一个对话框让你选择?
      • 解析 APK

  • Android 中的应用简单可以分为两大类:系统应用和普通应用。

系统应用:系统应用是指 /system/app 或者 /system/priv-app 目录下的应用。priv-app 是4.4以后出现的,用来存放一些系统底层应用,比如 Setting、SystemUI 等。/system/app存放系统级别的应用,如 Phone、Contacts等。Android中所谓的系统应用就是这两个目录下的应用。private 应用指的是 priv-ap 目录下的。

普通应用:普通应用指的是用户安装的应用,位于 /data/app 下。普通应用还可以安装在 sd卡 系统应用不可以。

  • 通常情况下系统应用是不能删除的,但是可以升级。升级方法是安装一个包名相同但是具有更高版本好的应用在 /data/app 下,对于这种升级,Android会在 data/system/packages.xml 文件中标签 记录被覆盖系统应用的升级。

了解 PackageManagerService

  • 在应用中,如果使用 PMS 服务,是通过 Context 获取的
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override public PackageManager getPackageManager() { if (mPackageManager != null) { return mPackageManager; } IPackageManager pm = ActivityThread.getPackageManager(); if (pm != null) { // Doesn't matter if we make more than one instance. return (mPackageManager = new ApplicationPackageManager(this, pm)); } return null; }

上面代码可以看出,实际上方法返回的是 ApplicationPackageManager 对象,创建对象的时候使用了 IPackageManager 作为参数。IPackageManager 对象就是 PackageManagerService 的引用对象,因此 ApplicationPackageManager 对象就是 PackageManagerService 的代理对象。ApplicationPackageManager继承自 PackageManager,PackageManager内部定义了可操作 PackageManagerService 的接口。

了解 pm/Settings.java

  • Setting 类的构造方法
复制代码
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
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); // 创建File 记录的是 packages.xml 中所有安装应用的信息。包括 基本信息 签名 和 权限 mSettingsFilename = new File(mSystemDir, "packages.xml"); // packages.xml 的备份文件 当写 packages.xml 时会先备份,写成功再删除备份。 mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml"); // 保存普通应用的数据目录和 uid 等信息 mPackageListFilename = new File(mSystemDir, "packages.list"); FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID); final File kernelDir = new File("/config/sdcardfs"); mKernelMappingFilename = kernelDir.exists() ? kernelDir : null; // Deprecated: Needed for migration // 记录系统中被强制停止运行的应用信息。系统在强制停止运行某个应用时会把应用信息记录到这里 mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml"); // packages-stopped.xml 的备份 当写 packages-stopped.xml 时会先备份,写成功再删除备份 mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml"); }

服务初始化过程

  • PackageManagerService 也是在 SystemServer 中初始化的,在其 run 方法中的 startBootstrapServices() 方法中有下面代码:
复制代码
1
2
3
4
5
mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager();

PackageManagerService 的 main() 方法如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { // Self-check for initial settings. PackageManagerServiceCompilerMapping.checkProperties(); // 创建 PackageManagerService 对象 PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); m.enableSystemUserPackages(); // 在 ServiceManager 中注册 PackageManagerService ServiceManager.addService("package", m); // 注册 binder 服务 接收底层 final PackageManagerNative pmn = m.new PackageManagerNative(); ServiceManager.addService("package_native", pmn); return m; }
  • 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
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "create package manager"); // 第一个阶段开始 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis()); // 判断 sdk 版本 if (mSdkVersion <= 0) { Slog.w(TAG, "**** ro.build.version.sdk not set!"); } mContext = context; // 设置运行模式 工厂模式是一种测试模式 mFactoryTest = factoryTest; // onlyCore 如果为 true 只处理系统应用。一般为 false mOnlyCore = onlyCore; // 对象存储屏幕的显示信息 mMetrics = new DisplayMetrics(); // installer 是用来安装应用的 保存到全局变量中 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. LocalServices.addService( PackageManagerInternal.class, new PackageManagerInternalImpl()); // 创建用户管理服务,Android支持多用户管理;通常第一个注册用户为管理员 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*/); mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy(); // 初始化 Settings 用来存储设置信息 mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages); } } // 添加 SharedUserSetting对象到 Setting中,SharedUserId 相同的包可以运行在同一个进程中,或者相互读取资源 // 我记得夸进程的 Android 两个app 写 sp文件 的时候,如果设置了同一个 SharedUserId 的话,是两个进程同事可以读到sp存储的内容的 // 下面是添加了7种系统的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); // 系统中读取 debug.separate_processes 属性。属性可以强制使应用程序组件运行在他自己的进程 一般调试用的 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; } mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context, "*dexopt*"); DexManager.Listener dexManagerListener = DexLogger.getListener(this, installer, mInstallLock); // DexManager 会记录监听关于 dex 文件的加载通知等 mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock, dexManagerListener); // ArtManagerService Art 服务,这是Binder对象,可以使得编译时使用 ART编译 mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock); mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper()); mOnPermissionChangeListeners = new OnPermissionChangeListeners( FgThread.get().getLooper()); getDefaultDisplayMetrics(context, mMetrics); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "get system config"); // 获取系统配置 SystemConfig systemConfig = SystemConfig.getInstance(); mAvailableFeatures = systemConfig.getAvailableFeatures(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); mProtectedPackages = new ProtectedPackages(mContext); synchronized (mInstallLock) { // writer synchronized (mPackages) { // 创建用来处理消息的线程,并加入到 WatchDog 监控中。 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); } // 打开 SELinux 的 Policy 文件 // 加载mac_permissions.xml文件,其中包含所有用于 标签的应用。 // 加载的mac_permissions.xml文件分别是/system和/vendor分区上的plat_mac_permissions.xml和vendor_mac_permissions.xml。 SELinuxMMAC.readInstallPolicy(); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks"); FallbackCategoryProvider.loadFallbacks(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings"); // 解析 package.xml 中的内容 解析后插入到 mSettings 的 mPackages 变量中 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) { requestCopyPreoptedFiles(); } // 设置模块代替 framework-res.apk 中缺省的 ResolverActivity 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); final String bootClassPath = System.getenv("BOOTCLASSPATH"); final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH"); if (bootClassPath == null) { Slog.w(TAG, "No BOOTCLASSPATH found!"); } if (systemServerClassPath == null) { Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!"); } File frameworkDir = new File(Environment.getRootDirectory(), "framework"); 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 // 从pre-M升级时,将系统应用程序权限从安装提升到运行时 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); } } } // 》〉》〉》〉》〉》〉》〉下面扫描了很多文件夹》〉》〉》〉》〉》〉》〉》 // 第二阶段 扫描系统文件 比如扫描 framework文件夹 用户的应用 或者 内置的系统应用等 mCacheDir = preparePackageParserCache(mIsUpgrade); // Set flag to monitor and not change apk file paths when // scanning install directories. // 设置扫描模式 int scanFlags = SCAN_BOOTING | SCAN_INITIAL; if (mIsUpgrade || mFirstBoot) { scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE; } // 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. // 扫描 VENDOR_OVERLAY_DIR 这个文件夹下的信息 scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_VENDOR, 0); scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR), mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_PRODUCT, 0); mParallelPackageParserCallback.findStaticOverlayPackages(); // Find base frameworks (resource packages without code). // 扫描并收集 system/framework 信息 scanDirTracedLI(frameworkDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_NO_DEX | SCAN_AS_SYSTEM | SCAN_AS_PRIVILEGED, 0); // Collect privileged system packages. // 扫描并收集 /system/prov-app 下的信息 final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app"); scanDirTracedLI(privilegedAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_PRIVILEGED, 0); // Collect ordinary system packages. // 扫描并收集 /system/app 下的信息 final File systemAppDir = new File(Environment.getRootDirectory(), "app"); scanDirTracedLI(systemAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM, 0); // Collect privileged vendor packages. File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app"); try { privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile(); } catch (IOException e) { // failed to look up canonical path, continue with original one } scanDirTracedLI(privilegedVendorAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_VENDOR | SCAN_AS_PRIVILEGED, 0); // Collect ordinary vendor packages. File vendorAppDir = new File(Environment.getVendorDirectory(), "app"); try { vendorAppDir = vendorAppDir.getCanonicalFile(); } catch (IOException e) { // failed to look up canonical path, continue with original one } scanDirTracedLI(vendorAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_VENDOR, 0); // Collect privileged odm packages. /odm is another vendor partition // other than /vendor. File privilegedOdmAppDir = new File(Environment.getOdmDirectory(), "priv-app"); try { privilegedOdmAppDir = privilegedOdmAppDir.getCanonicalFile(); } catch (IOException e) { // failed to look up canonical path, continue with original one } scanDirTracedLI(privilegedOdmAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_VENDOR | SCAN_AS_PRIVILEGED, 0); // Collect ordinary odm packages. /odm is another vendor partition // other than /vendor. File odmAppDir = new File(Environment.getOdmDirectory(), "app"); try { odmAppDir = odmAppDir.getCanonicalFile(); } catch (IOException e) { // failed to look up canonical path, continue with original one } scanDirTracedLI(odmAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_VENDOR, 0); // Collect all OEM packages. final File oemAppDir = new File(Environment.getOemDirectory(), "app"); scanDirTracedLI(oemAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_OEM, 0); // Collected privileged product packages. File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app"); try { privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile(); } catch (IOException e) { // failed to look up canonical path, continue with original one } scanDirTracedLI(privilegedProductAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_AS_SYSTEM | SCAN_AS_PRODUCT | SCAN_AS_PRIVILEGED, 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<>(); // Stub packages must either be replaced with full versions in the /data // partition or be disabled. final List<String> stubSystemApps = new ArrayList<>(); // 第三阶段 扫描 data/app 或者 data/app-priv 下的文件 if (!mOnlyCore) { // 扫描并判断一些 app是否在对应的设置中存在,不存在则不能成为系统 app // 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(); // 循环处理 mPackages 里面的应用 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()); // 从扫描列表 mPackages 中移除 removePackageLI(scannedPkg, true); // 插入到 mExpectingBetter 列表 后面会进行处理 mExpectingBetter.put(ps.name, ps.codePath); } continue; } // 代表应用不再 mPackages 中,代表系统中不存在 如果这个应用也不在 <update-package> 标示中。则说明是残留应用。应该删除 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. // 这个应用不再 mPackages 中 但是在 <update-package> 标示中 加入到 possiblyDeletedUpdatedSystemApps 中 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); // 》〉》〉》〉》〉 到这里已经结束扫描系统app 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()); // 扫描 data/app 收集目录中文件信息 scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0); // 扫描 data/priv-app 收集文件信息 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. // 放在possiblyDeletedUpdatedSystemApps 总的应用是 package.xml 文件被标记为带升级的系统文件 // 但是文件却不存在。所以检查下 用户目录下是否有升级文件,看是否存在,再进行处理 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. */ // mExpectingBetter 里面的应用是带系统升级的应用,前面把它从 mPackages 中移除放到了 mExpectingBetter 中 // 最后对他们进行扫描处理 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)) { reparseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR; rescanFlags = scanFlags | SCAN_AS_SYSTEM; } else if (FileUtils.contains(privilegedVendorAppDir, scanFile) || FileUtils.contains(privilegedOdmAppDir, scanFile)) { reparseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR; rescanFlags = scanFlags | SCAN_AS_SYSTEM | SCAN_AS_VENDOR | SCAN_AS_PRIVILEGED; } else if (FileUtils.contains(vendorAppDir, scanFile) || FileUtils.contains(odmAppDir, scanFile)) { reparseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR; rescanFlags = scanFlags | SCAN_AS_SYSTEM | SCAN_AS_VENDOR; } else if (FileUtils.contains(oemAppDir, scanFile)) { reparseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR; rescanFlags = scanFlags | SCAN_AS_SYSTEM | SCAN_AS_OEM; } else if (FileUtils.contains(privilegedProductAppDir, scanFile)) { reparseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR; rescanFlags = scanFlags | SCAN_AS_SYSTEM | SCAN_AS_PRODUCT | SCAN_AS_PRIVILEGED; } else if (FileUtils.contains(productAppDir, scanFile)) { reparseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR; rescanFlags = scanFlags | SCAN_AS_SYSTEM | SCAN_AS_PRODUCT; } 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)) { if (DEBUG_FILTERS) { Slog.i(TAG, "Found setup wizard;" + " allow priority " + filter.getPriority() + ";" + " package: " + filter.activity.info.packageName + " activity: " + filter.activity.className + " priority: " + filter.getPriority()); } // skip setup wizard; allow it to keep the high priority filter continue; } if (DEBUG_FILTERS) { Slog.i(TAG, "Protected action; cap priority to 0;" + " package: " + filter.activity.info.packageName + " activity: " + filter.activity.className + " origPrio: " + filter.getPriority()); } 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 版本和上次启动的 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). 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"); 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; } // 创建 PackageInstallerService 管理安装会话的服务 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()); } 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); }

构造方法主要处理功能有:先读取 packages.xml 中上次扫描的结果,保存在 mSettings 的成员变量中,然后扫描几个目录下的应用,然后把结果保存在 PackagesServiceManager 的成员变量 mPackages 中,通过对比上次检查的结果来判断是否有升级覆盖的系统应用。如果有从 mPackages 中移除,这样 mPackages 和 mSettings 中记录一样了 再写回 packages.xml 中。

处理 permission 文件

  • 在 PackageManagerService 中的构造方法中,调用了下面代码
复制代码
1
2
SystemConfig systemConfig = SystemConfig.getInstance();
  • 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
SystemConfig() { // Read configuration from 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 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. 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 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 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); }
  • Permission 是通过 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
41
42
43
44
45
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 // 先不处理 platform.xml 文件 最后处理 if (f.getPath().endsWith("etc/permissions/platform.xml")) { platformFile = f; continue; } // 不是 xml 文件不处理 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; } // 解析 xml 文件 readPermissionsFromXml(f, permissionFlag); } // Read platform permissions last so it will take precedence // 单独处理 platformFile 文件 if (platformFile != null) { readPermissionsFromXml(platformFile, permissionFlag); } }

readPermissions 就是通过读取指定目录下的 xml 文件,然后通过调用 readPermissionsFromXml 解析文件。目录下存放的是 permission 相关的文件。其中 platform.xml 的文件内容和其他文件不同,比如 android.hardware.audio.low.latency.xml 文件如下

复制代码
1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?> <permissions> <feature name="android.hardware.audio.low_latency" /> </permissions>

文件只是定义了一个 feature 标签。除了 platform.xml 其他文件也一样,下面是 platform.xml 文件

复制代码
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
<permissions> <permission name="android.permission.BLUETOOTH_ADMIN" > <group gid="net_bt_admin" /> </permission> <permission name="android.permission.LOOP_RADIO" > <group gid="loop_radio" /> </permission> <!-- Hotword training apps sometimes need a GID to talk with low-level hardware; give them audio for now until full HAL support is added. --> <permission name="android.permission.MANAGE_VOICE_KEYPHRASES"> <group gid="audio" /> </permission> <permission name="android.permission.ACCESS_BROADCAST_RADIO" > <!-- /dev/fm is gid media, not audio --> <group gid="media" /> </permission> <permission name="android.permission.USE_RESERVED_DISK"> <group gid="reserved_disk" /> </permission> <permission name="android.permission.READ_EXTERNAL_STORAGE" /> <permission name="android.permission.WRITE_EXTERNAL_STORAGE" /> // ... // ... <assign-permission name="android.permission.DUMP" uid="incidentd" /> <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="incidentd" /> <assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="incidentd" /> <assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" /> <assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" /> // ... // ... <library name="android.test.base" file="/system/framework/android.test.base.jar" /> <library name="android.test.mock" file="/system/framework/android.test.mock.jar" /> <library name="android.test.runner" file="/system/framework/android.test.runner.jar" /> <library name="javax.obex" file="/system/framework/javax.obex.jar" /> <library name="org.apache.http.legacy" file="/system/framework/org.apache.http.legacy.boot.jar" /> <!-- Whitelist system providers --> <allow-in-power-save-except-idle package="com.android.providers.calendar" /> <allow-in-power-save-except-idle package="com.android.providers.contacts" /> <!-- These are the packages that are white-listed to be able to run as system user --> <system-user-whitelisted-app package="com.android.settings" /> <!-- These are the packages that shouldn't run as system user --> <system-user-blacklisted-app package="com.android.wallpaper.livepicker" /> </permissions>
  • 标签 permission :表示把属性 name 中的字符串表示的权限赋予 group 标签中的属性 gid 中的用户组。
  • 标签 assign-permission :表示把属性 name 中的权限赋予 uid 中的用户。
  • 标签 library :表示除了 framework 动态库以外,系统将为应用加载动态库。
  • readPermissionsFromXml() 方法主要工作就是解析上面那些标签。内部就是解析 xml 而已,解析的结果
  • 标签 permission 中的结果:把属性 name 中的字符串表示的权限和 group 中的 gid 都存到 mSettings中的 mPermissions 中,而所有gid 也被收集起来放到了 PackageManagerService 的 mGlobalGids 中。
  • 标签assign-permission 中的内容放到了 PackageManagerService 的成员变量 mSystemPermission 中
  • library 动态库放到了 PackageServiceManager 中的 mSharedLibraries 中。
  • 其他 xml 文件中的 feature 定义的字符串放到了 PackageManagerService 的成员变量 mAvailableFeature 中。
  • Android的很多功能需要 permission 来保护,应用中如果需要某个受保护的功能,需要在他的 AndroidManifest 中显示的声明该字符串。但是有些功能只能特定的用户组使用,platform.xml 就是定义这种限制规则。

扫描应用目录的过程

  • 在 PackageManagerService 的构造方法中,调用了很多次 scanDirTracedLI() 去扫描文件,scanDirTracedLI内部实际上调用了代码 scanDirLI() 扫描文件,代码如下
    // scanDirLI 本身并不扫描子目录,且只扫描apk文件。其内部调用了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
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
private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime) { // 获取所有文件 File final File[] files = scanDir.listFiles(); // 如果是空的直接返回 if (ArrayUtils.isEmpty(files)) { Log.d(TAG, "No files in app dir " + scanDir); return; } if (DEBUG_PACKAGE_SCANNING) { Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags + " flags=0x" + Integer.toHexString(parseFlags)); } try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser( mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mParallelPackageParserCallback)) { // Submit files for parsing in parallel int fileCount = 0; for (File file : files) { // 判断是否是应用文件 不处理不是应用的文件 final boolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName()); if (!isPackage) { // Ignore entries which are not packages continue; } // 内部解析创建了 PackageParser 并加入到 BlockingQueue<ParseResult> mQueue 阻塞队列中,等待执行 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()) { 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); } } } }
  • 继续扫描过程 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
39
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. // 判断是否有子目录 设置对应的 flag 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 // 对位于Rom的软件包进行检查,包括系统,供应商,签名,版本等信息检查,如果新包的版本低或者签名缺失等则会删除data/ 下的包(内部调用了 collectCertificatesLI 校验签名) 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; }

当发出 Intent 时,如果系统中应用有多个相应,会弹出一个对话框让你选择?

  • 在上面的代码中 调用了 addForInitLI() ,在addForInitLI中调用了 scanPackageNewLI() -> commitScanResultsLocked() -> commitPackageSettings() ;
    在 commitPackageSettings 中初始化了一个 ResolverActivity ;这个Activity 就是弹出对话框的页面。
复制代码
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
// mResolveActivity 为成员变量 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; 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); } } } }

解析 APK

  • 在构造器中调用的 scanDirLI() 方法中,通过 ParallelPackageParser 来解析 APK,ParallelPackageParser 内部则是创建了 PackageParser 对象来解析。下面是 PackageParser 解析方法。
复制代码
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, boolean useCaches) throws PackageParserException { // 从 Cached 中获取如果解析过直接返回 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null; if (parsed != null) { return parsed; } long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; if (packageFile.isDirectory()) { // 如果是文件夹调用parseClusterPackage 主要为了关联多个apk存储到一个文件夹下的情况 // 下面有介绍 parsed = parseClusterPackage(packageFile, flags); } else { // 如果是文件调用 parseMonolithicPackage // 下面有介绍 parsed = parseMonolithicPackage(packageFile, flags); } long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; // 缓存结果 cacheResult(packageFile, flags, parsed); // 打 Log 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; }
  • 接下来看解析文件夹的代码
    主要功能就是解析文件夹 查找到 核心 apk 然后继续解析非核心apk,可以没有非核心apk,然后把解析的信息封装到Package中返回。
复制代码
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
private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException { // 通过解析packageDir下所有的文件,找到 baseApk(核心apk) 如果没有baseAPK则会失败; // 返回的PackageLite 存储了APK对应的信息,如版本号、版本名、源码路径等。如果成功一定会有核心apk也就是baseAPk 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<int[]> splitDependencies = null; final SplitAssetLoader assetLoader; // 判断是需要多个apk组成的的还是单独的apk 获取到 assetLoader splitNames是解析时存储下来的所有apk名称 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 { // 通过 assetLoader 获取到 AssetManager(资源管理类) final AssetManager assets = assetLoader.getBaseAssetManager(); // 通过解析后的路径解析核心 apk final File baseApk = new File(lite.baseCodePath); // 解析核心 apk :如解析 AndroidManifest.xml 和 Resources 信息 存储到 Package 对象中 final Package pkg = parseBaseApk(baseApk, assets, flags); // 解析失败证明 apk文件有问题 if (pkg == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "Failed to parse base APK: " + baseApk); } // 如果是多个apk组成的 if (!ArrayUtils.isEmpty(lite.splitNames)) { // 一共有多少个apk final int num = lite.splitNames.length; // 给 pkg赋值各种对应的属性 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++) { final AssetManager splitAssets = assetLoader.getSplitAssetManager(i); // 分别解析每个非核心 apk 信息存储到 pkg 中 parseSplitApk(pkg, i, splitAssets, flags); } } pkg.setCodePath(packageDir.getCanonicalPath()); pkg.setUse32bitAbi(lite.use32bitAbi); // 最后返回解析的信息 Package return pkg; } catch (IOException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, "Failed to get path: " + lite.baseCodePath, e); } finally { IoUtils.closeQuietly(assetLoader); } }
  • 接下来看另外一个分支,如果不是文件夹走 parseMonolithicPackage() 方法。
    这个方法内部比较简单和上面解析文件夹的流程大体相同代码也很少,最后也是返回了 Package 对象。
复制代码
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
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException { // parseMonolithicPackageLite 代码很少 // 其内部和上面解析文件夹一样 调用了 parseApkLite() 进行初步解析返回了 PackageLite 对象。 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags); if (mOnlyCoreApps) { if (!lite.coreApp) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, "Not a coreApp: " + apkFile); } } // 直接创建 DefaultSplitAssetLoader final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags); try { // 一样调用了 parseBaseApk 解析apk文件 AndroidManifest.xml 等信息返回 Package 对象 final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags); pkg.setCodePath(apkFile.getCanonicalPath()); pkg.setUse32bitAbi(lite.use32bitAbi); // 返回 Package 对象 return pkg; } catch (IOException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, "Failed to get path: " + apkFile, e); } finally { IoUtils.closeQuietly(assetLoader); } }

到这里基本上解析apk的流程就差不多了。接下来就是安装应用了

最后

以上就是曾经龙猫最近收集整理的关于关于 PackageManagerService的全部内容,更多相关关于内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(116)

评论列表共有 0 条评论

立即
投稿
返回
顶部