文章目录
  1. 1. Apk安装
    1. 1.1. 安装过程
    2. 1.2. 核心函数scanPackageDirtyLI
  2. 2. 安装后目录结构
  3. 3. Apk卸载
  4. 4. 参考资料

写多了业务逻辑, 咱们来看看系统的”业务逻辑”.

本文介绍apk如何安装, 卸载以及更新.
众所周知, apk本质上就是一个zip包, 在阅读本文前, 各位同学可以猜测一下安装一个压缩包是个什么流程, 如果有用adb安装过的同学应该会非常熟悉adb install这个命令, 但是可能不太熟悉adb shell amadb shell pm这两个命令.

Apk安装

常见的apk安装方式有三种:

  1. 系统自带的应用和厂商预装的应用. 没错, 系统自带的应用其实也是apk, 其安装是在系统首次启动时完成的. 这也就是为什么root后可以卸载系统自带应用.
  2. 通过存储介质安装. 最常见的就是通过sd卡放置apk或者网上下载apk方式安装.
  3. adb命令安装. 这应该是开发者最熟悉的安装方式了, 包括adb installadb pm install.

三种安装方式, 在安装apk时最终都是同一套流程, 即处理apk文件的流程. 安装过程可以归结为以下几个步骤:

  1. 将apk文件拷贝到指定目录下. 系统应用是在/system/app, 第三方应用在/data/app上.
  2. 解压apk, 拷贝文件. 创建UID, 创建/data/data/${package_name}目录, 设置权限. 这个就是应用的数据目录.
  3. 从apk中提取dex, 放到/data/dalvik-cache目录.
  4. 解析AndroidManifest.xml文件, 提取信息添加到PMS中, 更新PMS中相应的数据结构. 具体是, 将提取到的包信息更新到/data/system/packages.list/data/system/packages.xml.
  5. 发送广播Intent.ACTION_PACKAGE_ADDED或者Intent.ACTION_PACKAGE_REPLACED. 从名字可以判断分别对应全新安装和覆盖安装.

系统自带的以及厂商预装的app, 在手机首次启动时, 会通过扫描/system/app /system/framework /vendor/app等目录下面的APK文件, 完成安装. 原生系统没有vendor目录.
至于通过adb push的方式, 如果root过, 完全可以推送到系统目录, 以系统应用的方式进行安装. 系统应用的好处是系统在启动的时候就会将apk进行解压复制, 坏处是没办法热更新等. 推送到一般目录, 则可以使用系统命令/bin/pm安装apk文件. pm就是一个可执行文件版的PackageManager. 最终调用PackageManager.installPackage() -> PackageManagerService.installPacakge()进行安装. 顺便一提, 具有INSTALL_PACKAGES权限就可以自己调用这个方法进行apk安装.

安装过程

启动的时候, 主要是PackageManagerService进行安装包扫描和解析工作. 信息解析完毕后存在特定数据结构中(PackageParser.Package), 此后需要进行信息同步工作. 这是因为, 扫描到的APK可能是已经更名的包/disable的包/需要升级的包/已经安装但签名冲突的包/替换了系统包的非系统包等情况, 需要处理这些情况, 保证最终信息正确.
如果包需要进行Rename或者Update, 则需要签名比较.

adb shell pm略有不同, 是由com.android.commands.pm.Pm中的runInstall实现的(adb install最终也是调用的shell pm).

核心函数scanPackageDirtyLI

程序最初调用installPackageAsUser检查是否有安装权限, 安装APK的整个过程在PackageHandler中进行, 主要分为 拷贝APK(检查是否有足够空间)->扫描APK->安装后处理(主要是发送广播信息), 其中最关键的一步就是扫描APK, 由函数scanPackageLI完成, 该函数里面调用scanPackageDirtyLI.
下面就请看该方法的源码(基于Android 7.0)

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
// 位于frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
// 该方法相当长, 因此我去掉了调试&&异常处理的代码, 并加上了中文注释, 部分内容以注释代替源码, 如有需要请读者自行阅读源码.
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
throws PackageManagerException {
final File scanFile = new File(pkg.codePath);
// codePath或resourcePath为空, 抛出异常
...

// Apply policy
if ((policyFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
// 系统应用, 设置标记
} else {
// 非系统应用, 设置标记
}
// 检查其他标记位, 并执行对应操作

// TODO 知识盲区
if (mCustomResolverComponentName != null &&
mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
setUpCustomResolverActivity(pkg);
}

// 包名为android, 即系统核心包
if (pkg.packageName.equals("android")) {
synchronized (mPackages) {
if (mAndroidApplication != null) {
// 核心包重复定义, 抛出异常
}

if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
// 设置包解析信息
// Set up information for our fall-back user intent resolution activity.
mPlatformPackage = pkg;
pkg.mVersionCode = mSdkVersion;
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);
}
}
}
}

synchronized (mPackages) {
if (mPackages.containsKey(pkg.packageName)
|| mSharedLibraries.containsKey(pkg.packageName)) {
// 包名重复, 抛出异常
}

// If we're only installing presumed-existing packages, require that the
// scanned APK is both already known and at the path previously established
// for it. Previously unknown packages we pick up normally, but if we have an
// a priori expectation about this package's install presence, enforce it.
// With a singular exception for new system packages. When an OTA contains
// a new system package, we allow the codepath to change from a system location
// to the user-installed location. If we don't allow this change, any newer,
// user-installed version of the application will be ignored.
if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) {
if (mExpectingBetter.containsKey(pkg.packageName)) {
} else {
PackageSetting known = mSettings.peekPackageLPr(pkg.packageName);
if (known != null) {
if (!pkg.applicationInfo.getCodePath().equals(known.codePathString)
|| !pkg.applicationInfo.getResourcePath().equals(
known.resourcePathString)) {
// 包被修改, 抛出异常
}
}
}
}
}

// Initialize package source and resource directories
File destCodeFile = new File(pkg.applicationInfo.getCodePath());
File destResourceFile = new File(pkg.applicationInfo.getResourcePath());

SharedUserSetting suid = null;
PackageSetting pkgSetting = null;

if (!isSystemApp(pkg)) {
// Only system apps can use these features.
pkg.mOriginalPackages = null;
pkg.mRealPackage = null;
pkg.mAdoptPermissions = null;
}

// Getting the package setting may have a side-effect, so if we
// are only checking if scan would succeed, stash a copy of the
// old setting to restore at the end.
PackageSetting nonMutatedPs = null;

// writer
synchronized (mPackages) {
if (pkg.mSharedUserId != null) {
suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, 0, true);
if (suid == null) {
// 存储空间不足
}
}

// Check if we are renaming from an original package name.
PackageSetting origPackage = null;
String realName = null;
if (pkg.mOriginalPackages != null) {
// 检查包名是否有更改(例如本地化成其他语言), 如果有, 更新包名信息
// This package may need to be renamed to a previously
// installed name. Let's check on that...
final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
if (pkg.mOriginalPackages.contains(renamed)) {
// This package had originally been installed as the
// original name, and we have already taken care of
// transitioning to the new one. Just update the new
// one to continue using the old name.
realName = pkg.mRealPackage;
if (!pkg.packageName.equals(renamed)) {
// Callers into this function may have already taken
// care of renaming the package; only do it here if
// it is not already done.
pkg.setPackageName(renamed);
}

} else {
for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
if ((origPackage = mSettings.peekPackageLPr(
pkg.mOriginalPackages.get(i))) != null) {
// We do have the package already installed under its
// original name... should we use it?
if (!verifyPackageUpdateLPr(origPackage, pkg)) {
// New package is not compatible with original.
origPackage = null;
continue;
} else if (origPackage.sharedUser != null) {
// Make sure uid is compatible between packages.
if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
origPackage = null;
continue;
}
// TODO: Add case when shared user id is added [b/28144775]
} else {
}
break;
}
}
}
}

if (mTransferedPackages.contains(pkg.packageName)) {
}

// See comments in nonMutatedPs declaration
if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
PackageSetting foundPs = mSettings.peekPackageLPr(pkg.packageName);
if (foundPs != null) {
nonMutatedPs = new PackageSetting(foundPs);
}
}

// Just create the setting, don't add it yet. For already existing packages
// the PkgSetting exists already and doesn't have to be created.
pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,
pkg.applicationInfo.primaryCpuAbi,
pkg.applicationInfo.secondaryCpuAbi,
pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags,
user, false);
if (pkgSetting == null) {
// 空间不足, 抛出异常
}

if (pkgSetting.origPackage != null) {
// If we are first transitioning from an original package,
// fix up the new package's name now. We need to do this after
// looking up the package under its new name, so getPackageLP
// can take care of fiddling things correctly.
pkg.setPackageName(origPackage.name);

// File a report about this.
String msg = "New package " + pkgSetting.realName
+ " renamed to replace old package " + pkgSetting.name;
reportSettingsProblem(Log.WARN, msg);

// Make a note of it.
if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
mTransferedPackages.add(origPackage.name);
}

// No longer need to retain this.
pkgSetting.origPackage = null;
}

if ((scanFlags & SCAN_CHECK_ONLY) == 0 && realName != null) {
// Make a note of it.
mTransferedPackages.add(pkg.packageName);
}

if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}

if ((policyFlags&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.
updateSharedLibrariesLPw(pkg, null);
}

if (mFoundPolicyFile) {
SELinuxMMAC.assignSeinfoValue(pkg);
}

pkg.applicationInfo.uid = pkgSetting.appId;
pkg.mExtras = pkgSetting;
if (shouldCheckUpgradeKeySetLP(pkgSetting, scanFlags)) {
if (checkUpgradeKeySetLP(pkgSetting, pkg)) {
// We just determined the app is signed correctly, so bring
// over the latest parsed certs.
pkgSetting.signatures.mSignatures = pkg.mSignatures;
} else {
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
// 非系统目录, 签名不正确, 抛出异常
} else {
pkgSetting.signatures.mSignatures = pkg.mSignatures;
String msg = "System package " + pkg.packageName
+ " signature changed; retaining data.";
reportSettingsProblem(Log.WARN, msg);
}
}
} else {
try {
verifySignaturesLP(pkgSetting, pkg);
// We just determined the app is signed correctly, so bring
// over the latest parsed certs.
pkgSetting.signatures.mSignatures = pkg.mSignatures;
} catch (PackageManagerException e) {
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
// 非系统目录, 检查签名的过程中发生异常, 抛出异常
}
// The signature has changed, but this package is in the system
// image... let's recover!
pkgSetting.signatures.mSignatures = pkg.mSignatures;
// However... if this package is part of a shared user, but it
// doesn't match the signature of the shared user, let's fail.
// What this means is that you can't change the signatures
// associated with an overall shared user, which doesn't seem all
// that unreasonable.
if (pkgSetting.sharedUser != null) {
if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
// 签名不一致, 抛出异常
}
}
// File a report about this.
String msg = "System package " + pkg.packageName
+ " signature changed; retaining data.";
reportSettingsProblem(Log.WARN, msg);
}
}
// Verify that this new package doesn't have any content providers
// that conflict with existing packages. Only do this if the
// package isn't already installed, since we don't want to break
// things that are installed.
if ((scanFlags & SCAN_NEW_INSTALL) != 0) {
// 全新安装, 检查ContentProvider是否与现有的冲突
final int N = pkg.providers.size();
int i;
for (i=0; i<N; i++) {
PackageParser.Provider p = pkg.providers.get(i);
if (p.info.authority != null) {
String names[] = p.info.authority.split(";");
for (int j = 0; j < names.length; j++) {
if (mProvidersByAuthority.containsKey(names[j])) {
PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
final String otherPackageName =
((other != null && other.getComponentName() != null) ?
other.getComponentName().getPackageName() : "?");
// ContentProvider冲突, 抛出异常
}
}
}
}
}

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.peekPackageLPr(origName);
if (orig != null) {
if (verifyPackageUpdateLPr(orig, pkg)) {
mSettings.transferPermissionsLPw(origName, pkg.packageName);
}
}
}
}
}

final String pkgName = pkg.packageName;

final long scanFileTime = scanFile.lastModified();
final boolean forceDex = (scanFlags & SCAN_FORCE_DEX) != 0;
pkg.applicationInfo.processName = fixProcessName(
pkg.applicationInfo.packageName,
pkg.applicationInfo.processName,
pkg.applicationInfo.uid);

if (pkg != mPlatformPackage) {
// Get all of our default paths setup
pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM);
}

final String path = scanFile.getPath();
final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);

if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
// 如果不是全新安装, 从包中获取abi信息
derivePackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */);

// 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) {
// 系统app, 设置native library路径
setBundledAppAbisAndRoots(pkg, pkgSetting);
setNativeLibraryPaths(pkg);
}

} 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);
}

// 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.
// 系统包的abi是从配置文件读取的, 应当保存下来, 在后续处理同一uid下的其他应用时可以使用
if (mPlatformPackage == pkg) {
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 && pkgSetting.cpuAbiOverrideString != 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) {
// 共享用户, 微调abi信息
// 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.
adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
pkg, true /* boot complete */);
}

ArrayList<PackageParser.Package> clientLibPkgs = null;

if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
// 如果扫描标记含有SCAN_CHECK_ONLY, 那么在此处就结束并返回了
if (nonMutatedPs != null) {
synchronized (mPackages) {
mSettings.mPackages.put(nonMutatedPs.name, nonMutatedPs);
}
}
return pkg;
}

// Only privileged apps and updated privileged apps can add child packages.
if (pkg.childPackages != null && !pkg.childPackages.isEmpty()) {
if ((policyFlags & PARSE_IS_PRIVILEGED) == 0) {
// 只允许特权包添加子包, 否则抛出异常
}
final int childCount = pkg.childPackages.size();
for (int i = 0; i < childCount; i++) {
PackageParser.Package childPkg = pkg.childPackages.get(i);
if (mSettings.hasOtherDisabledSystemPkgWithChildLPr(pkg.packageName,
childPkg.packageName)) {
// 不允许覆盖其他被禁止的系统应用的子包, 否则抛出异常
}
}
}

// writer
synchronized (mPackages) {
// 系统包, 添加新的共享库
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
// Only system apps can add new 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 (allowed) {
if (!mSharedLibraries.containsKey(name)) {
mSharedLibraries.put(name, new SharedLibraryEntry(null, pkg.packageName));
} else if (!name.equals(pkg.packageName)) {
Slog.w(TAG, "Package " + pkg.packageName + " library "
+ name + " already exists; skipping");
}
} else {
Slog.w(TAG, "Package " + pkg.packageName + " declares lib "
+ name + " that is not declared on system image; skipping");
}
}
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");
}
}

// Make sure we're not adding any bogus keyset info
KeySetManagerService ksms = mSettings.mKeySetManagerService;
ksms.assertScannedPackageValid(pkg);

// writer
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");

boolean createIdmapFailed = false;
synchronized (mPackages) {
// We don't expect installation to fail beyond this point

if (pkgSetting.pkg != null) {
// Note that |user| might be null during the initial boot scan. If a codePath
// for an app has changed during a boot scan, it's due to an app update that's
// part of the system partition and marker changes must be applied to all users.
maybeRenameForeignDexMarkers(pkgSetting.pkg, pkg,
(user != null) ? user : UserHandle.ALL);
}
// 存下包信息和设置信息
// Add the new setting to mSettings
mSettings.insertPackageSettingLPw(pkgSetting, pkg);
// Add the new setting to mPackages
mPackages.put(pkg.applicationInfo.packageName, pkg);
// 从mSettings.mPackagesToBeCleaned中移除当前包名,以防被误清除数据
// 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();
}
}

// 记录或更新安装时间戳
// Take care of first install / last update times.
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 ((policyFlags&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;
}
}

// Add the package's KeySets to the global KeySetManagerService
ksms.addScannedPackageLPw(pkg);

// 处理provider
int N = pkg.providers.size();
// 用来记录安装信息, 以便打log查看过程
StringBuilder r = null;
int i;
for (i=0; i<N; i++) {
PackageParser.Provider p = pkg.providers.get(i);
p.info.processName = fixProcessName(pkg.applicationInfo.processName,
p.info.processName, pkg.applicationInfo.uid);
mProviders.addProvider(p);
p.syncable = p.info.isSyncable;
if (p.info.authority != null) {
String names[] = p.info.authority.split(";");
p.info.authority = null;
for (int j = 0; j < names.length; j++) {
if (j == 1 && p.syncable) {
// We only want the first authority for a provider to possibly be
// syncable, so if we already added this provider using a different
// authority clear the syncable flag. We copy the provider before
// changing it because the mProviders object contains a reference
// to a provider that we don't want to change.
// Only do this for the second authority since the resulting provider
// object can be the same for all future authorities for this provider.
p = new PackageParser.Provider(p);
p.syncable = false;
}
if (!mProvidersByAuthority.containsKey(names[j])) {
mProvidersByAuthority.put(names[j], p);
if (p.info.authority == null) {
p.info.authority = names[j];
} else {
p.info.authority = p.info.authority + ";" + names[j];
}
} else {
PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
Slog.w(TAG, "Skipping provider name " + names[j] +
" (in package " + pkg.applicationInfo.packageName +
"): name already used by "
+ ((other != null && other.getComponentName() != null)
? other.getComponentName().getPackageName() : "?"));
}
}
}
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(p.info.name);
}
}

// 处理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, pkg.applicationInfo.uid);
mServices.addService(s);
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
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, pkg.applicationInfo.uid);
mReceivers.addActivity(a, "receiver");
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
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, pkg.applicationInfo.uid);
mActivities.addActivity(a, "activity");
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}

// 处理permissionGroup权限组
N = pkg.permissionGroups.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
if (cur == null) {
mPermissionGroups.put(pg.info.name, pg);
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(pg.info.name);
}
} else {
Slog.w(TAG, "Permission group " + pg.info.name + " from package "
+ pg.info.packageName + " ignored: original from "
+ cur.info.packageName);
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append("DUP:");
r.append(pg.info.name);
}
}
}

// 处理permission
N = pkg.permissions.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Permission p = pkg.permissions.get(i);

// Assume by default that we did not install this permission into the system.
p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;

// Now that permission groups have a special meaning, we ignore permission
// groups for legacy apps to prevent unexpected behavior. In particular,
// permissions for one app being granted to someone just becase they happen
// to be in a group defined by another app (before this had no implications).
if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
p.group = mPermissionGroups.get(p.info.group);
// Warn for a permission in an unknown group.
if (p.info.group != null && p.group == null) {
Slog.w(TAG, "Permission " + p.info.name + " from package "
+ p.info.packageName + " in an unknown group " + p.info.group);
}
}

ArrayMap<String, BasePermission> permissionMap =
p.tree ? mSettings.mPermissionTrees
: mSettings.mPermissions;
BasePermission bp = permissionMap.get(p.info.name);

// Allow system apps to redefine non-system permissions
if (bp != null && !Objects.equals(bp.sourcePackage, p.info.packageName)) {
final boolean currentOwnerIsSystem = (bp.perm != null
&& isSystemApp(bp.perm.owner));
if (isSystemApp(p.owner)) {
if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) {
// It's a built-in permission and no owner, take ownership now
bp.packageSetting = pkgSetting;
bp.perm = p;
bp.uid = pkg.applicationInfo.uid;
bp.sourcePackage = p.info.packageName;
p.info.flags |= PermissionInfo.FLAG_INSTALLED;
} else if (!currentOwnerIsSystem) {
String msg = "New decl " + p.owner + " of permission "
+ p.info.name + " is system; overriding " + bp.sourcePackage;
reportSettingsProblem(Log.WARN, msg);
bp = null;
}
}
}

if (bp == null) {
bp = new BasePermission(p.info.name, p.info.packageName,
BasePermission.TYPE_NORMAL);
permissionMap.put(p.info.name, bp);
}

if (bp.perm == null) {
if (bp.sourcePackage == null
|| bp.sourcePackage.equals(p.info.packageName)) {
BasePermission tree = findPermissionTreeLP(p.info.name);
if (tree == null
|| tree.sourcePackage.equals(p.info.packageName)) {
bp.packageSetting = pkgSetting;
bp.perm = p;
bp.uid = pkg.applicationInfo.uid;
bp.sourcePackage = p.info.packageName;
p.info.flags |= PermissionInfo.FLAG_INSTALLED;
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(p.info.name);
}
} else {
Slog.w(TAG, "Permission " + p.info.name + " from package "
+ p.info.packageName + " ignored: base tree "
+ tree.name + " is from package "
+ tree.sourcePackage);
}
} else {
Slog.w(TAG, "Permission " + p.info.name + " from package "
+ p.info.packageName + " ignored: original from "
+ bp.sourcePackage);
}
} else if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append("DUP:");
r.append(p.info.name);
}
if (bp.perm == p) {
bp.protectionLevel = p.info.protectionLevel;
}
}

// 处理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.splitSourceDirs = pkg.applicationInfo.splitSourceDirs;
a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs;
a.info.dataDir = pkg.applicationInfo.dataDir;
a.info.deviceProtectedDataDir = pkg.applicationInfo.deviceProtectedDataDir;
a.info.credentialProtectedDataDir = pkg.applicationInfo.credentialProtectedDataDir;

a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
a.info.secondaryNativeLibraryDir = pkg.applicationInfo.secondaryNativeLibraryDir;
mInstrumentation.put(a.getComponentName(), a);
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}

if (pkg.protectedBroadcasts != null) {
N = pkg.protectedBroadcasts.size();
for (i=0; i<N; i++) {
mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
}
}

// 设置时间戳为扫描文件的时间戳
pkgSetting.setTimeStamp(scanFileTime);

// 创建idmap文件
// Create idmap files for pairs of (packages, overlay packages).
// Note: "android", ie framework-res.apk, is handled by native layers.
if (pkg.mOverlayTarget != null) {
// This is an overlay package.
if (pkg.mOverlayTarget != null && !pkg.mOverlayTarget.equals("android")) {
if (!mOverlays.containsKey(pkg.mOverlayTarget)) {
mOverlays.put(pkg.mOverlayTarget,
new ArrayMap<String, PackageParser.Package>());
}
ArrayMap<String, PackageParser.Package> map = mOverlays.get(pkg.mOverlayTarget);
map.put(pkg.packageName, pkg);
PackageParser.Package orig = mPackages.get(pkg.mOverlayTarget);
if (orig != null && !createIdmapForPackagePairLI(orig, pkg)) {
createIdmapFailed = true;
}
}
} else if (mOverlays.containsKey(pkg.packageName) &&
!pkg.packageName.equals("android")) {
// This is a regular package, with one or more known overlay packages.
createIdmapsForPackageLI(pkg);
}
}

Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

if (createIdmapFailed) {
throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
"scanPackageLI failed to createIdmap");
}
return pkg;
}

安装后目录结构

安装后目录结构如下:

目录 含义
/data/app 第三方应用apk文件
/data/anr 存放anr信息
/data/data 应用程序数据
/data/data/${package_name} 特定应用程序数据目录
cache 临时文件,系统会自动清理
databases 数据库
files 一般文件
shared_pres SharedPreference
lib so文件
/data/dalvik-cache 存放odex文件
/data/system/packages.list 从AndroidManifest.xml提取的信息
/data/system/packages.xml 从AndroidManifest.xml提取的信息
/data/user/0 软链接,指向/data/data
/data/user_de/0/${package_name} 设备存储保护区,在快速启动模式可以访问这个文件夹
/proc/cpuinfo cpu信息
/proc/smaps 内存占用信息
/sdcard 软链接,最终指向/storage/emulated/0【跟Android版本和ROM版本有关】
/storage/emulated/0 外部存储的根目录
/storage/emulated/0/Android/data/${package_name} 应用的额外数据
/system/app 系统应用apk文件
/system/lib 系统应用so库

Apk卸载

卸载是安装的逆过程, 所以其实还比较好理解, 无非就是安装了啥就去掉啥, 不留下一片云彩. 它调用的函数是deletePackageAsUser, 同样位于/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java. 代码如下(需要注意, 卸载的源码在7.0以上和7.0以下差别较大, 如前所述, 本文基于7.0源码):

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
// 位于frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int userId,
int flags) {
deletePackage(packageName, new LegacyPackageDeleteObserver(observer).getBinder(), userId,
flags);
}

public void deletePackage(final String packageName,
final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
// 检查权限
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_PACKAGES, null);
// 不解释
Preconditions.checkNotNull(packageName);
Preconditions.checkNotNull(observer);
// 用户权限检查
final int uid = Binder.getCallingUid();
final boolean deleteAllUsers = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0;
final int[] users = deleteAllUsers ? sUserManager.getUserIds() : new int[]{ userId };
if (UserHandle.getUserId(uid) != userId || (deleteAllUsers && users.length > 1)) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
"deletePackage for user " + userId);
}

if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) {
try {
observer.onPackageDeleted(packageName,
PackageManager.DELETE_FAILED_USER_RESTRICTED, null);
} catch (RemoteException re) {
}
return;
}

if (!deleteAllUsers && getBlockUninstallForUser(packageName, userId)) {
try {
observer.onPackageDeleted(packageName,
PackageManager.DELETE_FAILED_OWNER_BLOCKED, null);
} catch (RemoteException re) {
}
return;
}

// Queue up an async operation since the package deletion may take a little while.
// 抛入线程处理卸载
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
int returnCode;
if (!deleteAllUsers) {
// 按用户来卸载包
returnCode = deletePackageX(packageName, userId, deleteFlags);
} else {
int[] blockUninstallUserIds = getBlockUninstallForUsers(packageName, users);
// If nobody is blocking uninstall, proceed with delete for all users
if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
returnCode = deletePackageX(packageName, userId, deleteFlags);
} else {
// Otherwise uninstall individually for users with blockUninstalls=false
// 有部分用户阻止卸载, 只对不阻止的用户执行卸载
final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
for (int userId : users) {
if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
returnCode = deletePackageX(packageName, userId, userFlags);
if (returnCode != PackageManager.DELETE_SUCCEEDED) {
Slog.w(TAG, "Package delete failed for user " + userId
+ ", returnCode " + returnCode);
}
}
}
// The app has only been marked uninstalled for certain users.
// We still need to report that delete was blocked
returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
}
}
try {
observer.onPackageDeleted(packageName, returnCode, null);
} catch (RemoteException e) {
Log.i(TAG, "Observer no longer exists.");
} //end catch
} //end run
});
}

private int deletePackageX(String packageName, int userId, int deleteFlags) {
final PackageRemovedInfo info = new PackageRemovedInfo();
final boolean res;

final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
? UserHandle.USER_ALL : userId;
// 有活动的管理员则不允许删除
if (isPackageDeviceAdmin(packageName, removeUser)) {
Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
}

PackageSetting uninstalledPs = null;

// for the uninstall-updates case and restricted profiles, remember the per-
// user handle installed state
int[] allUsers;
synchronized (mPackages) {
// 在mPackages里面查找对应的PackageSettings
uninstalledPs = mSettings.mPackages.get(packageName);
if (uninstalledPs == null) {
Slog.w(TAG, "Not removing non-existent package " + packageName);
return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
allUsers = sUserManager.getUserIds();
info.origUsers = uninstalledPs.queryInstalledUsers(allUsers, true);
}

// 冻结用户
final int freezeUser;
if (isUpdatedSystemApp(uninstalledPs)
&& ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0)) {
// We're downgrading a system app, which will apply to all users, so
// freeze them all during the downgrade
freezeUser = UserHandle.USER_ALL;
} else {
freezeUser = removeUser;
}

synchronized (mInstallLock) {
try (PackageFreezer freezer = freezePackageForDelete(packageName, freezeUser,
deleteFlags, "deletePackageX")) {
res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers,
deleteFlags | REMOVE_CHATTY, info, true, null);
}
synchronized (mPackages) {
if (res) {
mEphemeralApplicationRegistry.onPackageUninstalledLPw(uninstalledPs.pkg);
}
}
}

// 发送广播
if (res) {
final boolean killApp = (deleteFlags & PackageManager.DELETE_DONT_KILL_APP) == 0;
info.sendPackageRemovedBroadcasts(killApp);
info.sendSystemPackageUpdatedBroadcasts();
info.sendSystemPackageAppearedBroadcasts();
}
// Force a gc here.
// 强制gc
Runtime.getRuntime().gc();
// Delete the resources here after sending the broadcast to let
// other processes clean up before deleting resources.
if (info.args != null) {
synchronized (mInstallLock) {
info.args.doPostDeleteLI(true);
}
}

return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}

private boolean deletePackageLIF(String packageName, UserHandle user,
boolean deleteCodeAndResources, int[] allUserHandles, int flags,
PackageRemovedInfo outInfo, boolean writeSettings,
PackageParser.Package replacingPackage) {
if (packageName == null) {
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
}

PackageSetting ps;

synchronized (mPackages) {
ps = mSettings.mPackages.get(packageName);
if (ps == null) {
Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
return false;
}

// 删除非系统子包
if (ps.parentPackageName != null && (!isSystemApp(ps)
|| (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
final int removedUserId = (user != null) ? user.getIdentifier()
: UserHandle.USER_ALL;
if (!clearPackageStateForUserLIF(ps, removedUserId, outInfo)) {
return false;
}
markPackageUninstalledForUserLPw(ps, user);
scheduleWritePackageRestrictionsLocked(user);
return true;
}
}

// 对特定用户删除非系统包
if (((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
&& user.getIdentifier() != UserHandle.USER_ALL)) {
// The caller is asking that the package only be deleted for a single
// user. To do this, we just mark its uninstalled state and delete
// its data. If this is a system app, we only allow this to happen if
// they have set the special DELETE_SYSTEM_APP which requests different
// semantics than normal for uninstalling system apps.
markPackageUninstalledForUserLPw(ps, user);

if (!isSystemApp(ps)) {
// 非系统包
// Do not uninstall the APK if an app should be cached
boolean keepUninstalledPackage = shouldKeepUninstalledPackageLPr(packageName);
if (ps.isAnyInstalled(sUserManager.getUserIds()) || keepUninstalledPackage) {
// 有用户安装或者需要保存已卸载的包
// Other user still have this package installed, so all
// we need to do is clear this user's data and save that
// it is uninstalled.
// 清除数据, 将"该包已被该用户卸载"的信息记录下来.
if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
return false;
}
scheduleWritePackageRestrictionsLocked(user);
return true;
} else {
// We need to set it back to 'installed' so the uninstall
// broadcasts will be sent correctly.
ps.setInstalled(true, user.getIdentifier());
}
} else {
// This is a system app, so we assume that the
// other users still have this package installed, so all
// we need to do is clear this user's data and save that
// it is uninstalled.
if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
return false;
}
scheduleWritePackageRestrictionsLocked(user);
return true;
}
}

// 处理子包问题
// If we are deleting a composite package for all users, keep track
// of result for each child.
if (ps.childPackageNames != null && outInfo != null) {
synchronized (mPackages) {
final int childCount = ps.childPackageNames.size();
outInfo.removedChildPackages = new ArrayMap<>(childCount);
for (int i = 0; i < childCount; i++) {
String childPackageName = ps.childPackageNames.get(i);
PackageRemovedInfo childInfo = new PackageRemovedInfo();
childInfo.removedPackage = childPackageName;
outInfo.removedChildPackages.put(childPackageName, childInfo);
PackageSetting childPs = mSettings.peekPackageLPr(childPackageName);
if (childPs != null) {
childInfo.origUsers = childPs.queryInstalledUsers(allUserHandles, true);
}
}
}
}

boolean ret = false;
if (isSystemApp(ps)) {
// 系统应用的卸载实际上是清除数据并回退到系统自带的版本
// When an updated system application is deleted we delete the existing resources
// as well and fall back to existing code in system partition
ret = deleteSystemPackageLIF(ps.pkg, ps, allUserHandles, flags, outInfo, writeSettings);
} else {
ret = deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles,
outInfo, writeSettings, replacingPackage);
}

// Take a note whether we deleted the package for all users
if (outInfo != null) {
outInfo.removedForAllUsers = mPackages.get(ps.name) == null;
if (outInfo.removedChildPackages != null) {
synchronized (mPackages) {
final int childCount = outInfo.removedChildPackages.size();
for (int i = 0; i < childCount; i++) {
PackageRemovedInfo childInfo = outInfo.removedChildPackages.valueAt(i);
if (childInfo != null) {
childInfo.removedForAllUsers = mPackages.get(
childInfo.removedPackage) == null;
}
}
}
}
// If we uninstalled an update to a system app there may be some
// child packages that appeared as they are declared in the system
// app but were not declared in the update.
if (isSystemApp(ps)) {
synchronized (mPackages) {
PackageSetting updatedPs = mSettings.peekPackageLPr(ps.name);
final int childCount = (updatedPs.childPackageNames != null)
? updatedPs.childPackageNames.size() : 0;
for (int i = 0; i < childCount; i++) {
String childPackageName = updatedPs.childPackageNames.get(i);
if (outInfo.removedChildPackages == null
|| outInfo.removedChildPackages.indexOfKey(childPackageName) < 0) {
PackageSetting childPs = mSettings.peekPackageLPr(childPackageName);
if (childPs == null) {
continue;
}
PackageInstalledInfo installRes = new PackageInstalledInfo();
installRes.name = childPackageName;
installRes.newUsers = childPs.queryInstalledUsers(allUserHandles, true);
installRes.pkg = mPackages.get(childPackageName);
installRes.uid = childPs.pkg.applicationInfo.uid;
if (outInfo.appearedChildPackages == null) {
outInfo.appearedChildPackages = new ArrayMap<>();
}
outInfo.appearedChildPackages.put(childPackageName, installRes);
}
}
}
}
}

return ret;
}

参考资料

Android APK安装与卸载机制
Android PackageManagerService源码

文章目录
  1. 1. Apk安装
    1. 1.1. 安装过程
    2. 1.2. 核心函数scanPackageDirtyLI
  2. 2. 安装后目录结构
  3. 3. Apk卸载
  4. 4. 参考资料