PKMS 钻研(2) - 构造函数

核心源码(Android_10.0)

关键类 路径
Process.java frameworks/base/core/java/android/os/Process.java
Settings.java frameworks/base/services/core/java/com/android/server/pm/Settings.java
SystemConfig.java frameworks/base/core/java/com/android/server/SystemConfig.java
SystemServer.java frameworks/base/services/java/com/android/server/SystemServer.java
PackageManagerService.java frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
ParallelPackageParser.java frameworks/base/services/core/java/com/android/server/pm/ParallelPackageParser.java

PackageManagerService 系列第一篇中,我们将 “构造函数” 分成了两部分研究,如下:

           ✂  构造函数(1) - 前期准备工作 (已分析)  请查阅:《PackageManagerService 钻研(1)- 启动流程》
           ✂  构造函数(2) - 扫描 Package 和 扫尾工作 (本篇文章要讨论的内容)

一、扫描 Package

PMS 构造函数第二阶段(我们前面分析的 Settings 和 XML 解析作为构造函数的第一部分)的工作就是 扫描系统中的 APK。由于需要逐个扫描文件,因此手机上装的程序越多,PMS 的工作量就越大,系统启动速度也就越慢,这就是为什么你的手机启动速度有快慢的原因(所以优化开机启动速度,了解 PMS 很关键!)

1.1 第一阶段(剩余工作)

接着前面的 PMS 构造函数继续分析:

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

public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
... ...

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) {
// 创建名为 "PackageManager" 的 handler 线程
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);
... ...

Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

// 清理那些代码路径不存在的异常 package
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 (!mOnlyCore && mFirstBoot) {
requestCopyPreoptedFiles();
}

// 设置模块来代替 framework-res.apk 中缺省的 ResolverActivity
if (!TextUtils.isEmpty(customResolverActivityName)) {
mCustomResolverComponentName = ComponentName.unflattenFromString(
customResolverActivityName);
}

// 记录扫描开始的时间
long startTime = SystemClock.uptimeMillis();

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);

// 需要系统提前加载的 jar
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!");
}

// 至此,第一阶段代码结束!
... ...

}

1.2 扫描系统 Package

接下来看 PMS 第二阶段工作的核心内容,即 扫描 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
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
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
... ...

synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
... ... // 构造函数第一阶段

// 定义 frameworkDir 指向 /system/frameworks 目录
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
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;
mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;

int preUpgradeSdkVersion = ver.sdkVersion;

// 是否需要提升权限
if (mPromoteSystemApps) {
Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
while (pkgSettingIter.hasNext()) {
PackageSetting ps = pkgSettingIter.next();
if (isSystemApp(ps)) {
// 遍历 Settings::mPackages 集合,
// 将系统 APP 加入到 PackageManagerService::mExistingSystemPackages
mExistingSystemPackages.add(ps.name);
}
}
}

mCacheDir = preparePackageParserCache(mIsUpgrade);

// 定义扫描参数
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;

if (mIsUpgrade || mFirstBoot) {
scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}

// Collect vendor/product/system_ext 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、product/overlay、system_ext/overlay 目录
final int systemParseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR;
final int systemScanFlags = scanFlags | SCAN_AS_SYSTEM;
for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
final SystemPartition partition = mDirsToScanAsSystem.get(i);
if (partition.overlayFolder == null) {
continue;
}
scanDirTracedLI(partition.overlayFolder, systemParseFlags,
systemScanFlags | partition.scanFlag, 0);
}

mParallelPackageParserCallback.findStaticOverlayPackages();

// 扫描 /system/frameworks 目录
scanDirTracedLI(frameworkDir, systemParseFlags,
systemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0);

if (!mPackages.containsKey("android")) {
throw new IllegalStateException(
"Failed to load frameworks package; check log for warnings");
}

// 扫描 /system/priv-app、/system/app、/vendor/app 等目录
for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {
final SystemPartition partition = mDirsToScanAsSystem.get(i);
if (partition.privAppFolder != null) {
scanDirTracedLI(partition.privAppFolder, systemParseFlags,
systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0);
}
scanDirTracedLI(partition.appFolder, systemParseFlags,
systemScanFlags | partition.scanFlag, 0);
}

... ...
}


我们发现 PMS 扫描了很多目录,我们列举几个重点说明:

         ✒ /system/frameworks :该目录中的文件都是系统库,例如:framework.jar、services.jar、framework-res.apk。不过 scanDirTracedLI 只扫描 APK 文件,所以 framework-res.apk 是该目录中唯一被扫描的文件。

         ✒ /system/app :该目录下全是默认的系统应用。例如:Browser.apk、SettingsProvider.apk 等。

         ✒ /vendor/app :该目录中的文件由厂商提供,即全是厂商定制的 APK 文件。

1.3 PackageManagerService.scanDirTracedLI

PackageManagerService 扫描目录统一调用 scanDirTracedLI() 方法,跟踪源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
... ...

private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags, long currentTime) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
try {
scanDirLI(scanDir, parseFlags, scanFlags, currentTime); // 跳转至 scanDirLI 方法
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}

}

1.4 PackageManagerService.scanDirLI

下面的重点就转移到 scanDirLI() 方法了:

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

public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
... ...

private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime) {
final File[] files = scanDir.listFiles(); // 扫描该目录下所有后缀为 .apk 的文件
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));
}

// ParallelPackageParser 是 Android 9.0 新增的一个类,我们可以理解它其实就是一个队列,
// 收集系统 apk 文件,然后从这个队列里面一个个取出 apk ,调用 PackageParser 解析!
try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
mParallelPackageParserCallback)) {
// Submit files for parsing in parallel --> 收集 apk
int fileCount = 0;
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) { // 过滤掉非 apk 文件,如果不是则跳过继续扫描
// Ignore entries which are not packages
continue;
}
parallelPackageParser.submit(file, parseFlags);
fileCount++;
}

// Process results one by one --> 解析 apk
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 {
/*
* Android 9.0 调用 scanPackageChildLI,
* Android 8.0 调用 scanPackageLI,
* Android 7.0 调用 scanPackageTracedLI,
*/
// 调用函数扫描一个特定的 apk 文件,返回值是 PackageParser 的内部类 Package
scanPackageChildLI(parseResult.pkg, parseFlags, scanFlags, currentTime, null);
} catch (PackageManagerException e) { // 扫描 APK 过程中发生异常
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 --> 如果解析失败,并且是非系统 apk
if ((scanFlags & SCAN_AS_SYSTEM) == 0 &&
errorCode != PackageManager.INSTALL_SUCCEEDED) {
logCriticalInfo(Log.WARN,
"Deleting invalid package at " + parseResult.scanFile);
removeCodePathLI(parseResult.scanFile); // 非系统 Package 扫描失败,删除文件
}
}
}
}

}

继续分析 scanPackageChildLI() 方法之前,我们看看 9.0 新增的 ParallelPackageParser 这个类。

1.4.1 ParallelPackageParser

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

/**
* Helper class for parallel parsing of packages using {@link PackageParser}.
* <p>Parsing requests are processed by a thread-pool of {@link #MAX_THREADS}.
* At any time, at most {@link #QUEUE_CAPACITY} results are kept in RAM</p>
*/
class ParallelPackageParser implements AutoCloseable {
... ...

private final BlockingQueue<ParseResult> mQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);

private final ExecutorService mService = ConcurrentUtils.newFixedThreadPool(MAX_THREADS,
"package-parsing-thread", Process.THREAD_PRIORITY_FOREGROUND);

ParallelPackageParser(String[] separateProcesses, boolean onlyCoreApps,
DisplayMetrics metrics, File cacheDir, PackageParser.Callback callback) {
mSeparateProcesses = separateProcesses;
mOnlyCore = onlyCoreApps;
mMetrics = metrics;
mCacheDir = cacheDir;
mPackageParserCallback = callback;
}
... ...

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

... ...
}

我们再看下 ParallelPackageParser 的内部类 ParseResult

1.4.2 ParallelPackageParser.ParseResult

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

class ParallelPackageParser implements AutoCloseable {
... ...

static class ParseResult {

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

@Override
public String toString() {
return "ParseResult{" +
"pkg=" + pkg +
", scanFile=" + scanFile +
", throwable=" + throwable +
'}';
}
}

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

... ...
}

1.5 PackageManagerService.scanPackageChildLI

接下来的重点就是分析 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
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
... ...

/**
* Scans a package and returns the newly parsed package. --> 扫描一个 apk 文件并返回 package!
* @throws PackageManagerException on a parse error.
*/
@GuardedBy({"mInstallLock", "mPackages"})
private PackageParser.Package scanPackageChildLI(PackageParser.Package pkg,
final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
@Nullable UserHandle user)
throws PackageManagerException {
// If the package has children and this is the first dive in the function
// we scan the package with the SCAN_CHECK_ONLY flag set to see whether all
// packages (parent and children) would be successfully scanned before the
// actual scan since scanning mutates internal state and we want to atomically
// install the package and its children.
if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
if (pkg.childPackages != null && pkg.childPackages.size() > 0) {
scanFlags |= SCAN_CHECK_ONLY;
}
} else {
scanFlags &= ~SCAN_CHECK_ONLY;
}

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

// Scan the children,调用 addForInitLI 方法
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;
}

}

1.6 PackageManagerService.addForInitLI

继续跟踪源码,调用 addForInitLI() 方法:

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

public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
... ...

@GuardedBy({"mInstallLock", "mPackages"})
private PackageParser.Package addForInitLI(PackageParser.Package pkg,
@ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
@Nullable UserHandle user)
throws PackageManagerException {
final boolean scanSystemPartition = (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0;
final String renamedPkgName;
final PackageSetting disabledPkgSetting;
final boolean isSystemPkgUpdated;
final boolean pkgAlreadyExists;
PackageSetting pkgSetting;
... ...

/*
* 判断系统 APK 是否需要更新
* final ArrayMap<String, PackageParser.Package> mPackages = new ArrayMap<String, PackageParser.Package>();
*/
synchronized (mPackages) {
renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage);
final String realPkgName = getRealPackageName(pkg, renamedPkgName);
if (realPkgName != null) {
ensurePackageRenamed(pkg, renamedPkgName);
}
... ...

if (scanSystemPartition) {
// Potentially prune child packages. If the application on the /system
// partition has been updated via OTA, but, is still disabled by a
// version on /data, cycle through all of its children packages and
// remove children that are no longer defined.
if (isSystemPkgUpdated) {
final int scannedChildCount = (pkg.childPackages != null)
? pkg.childPackages.size() : 0;
final int disabledChildCount = disabledPkgSetting.childPackageNames != null
? disabledPkgSetting.childPackageNames.size() : 0;
for (int i = 0; i < disabledChildCount; i++) {
String disabledChildPackageName =
disabledPkgSetting.childPackageNames.get(i);
boolean disabledPackageAvailable = false;
for (int j = 0; j < scannedChildCount; j++) {
PackageParser.Package childPkg = pkg.childPackages.get(j);
if (childPkg.packageName.equals(disabledChildPackageName)) {
disabledPackageAvailable = true;
break;
}
}
if (!disabledPackageAvailable) {
mSettings.removeDisabledSystemPackageLPw(disabledChildPackageName);
}
}
// we're updating the disabled package, so, scan it as the package setting
final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, null,
disabledPkgSetting /* pkgSetting */, null /* disabledPkgSetting */,
null /* originalPkgSetting */, null, parseFlags, scanFlags,
(pkg == mPlatformPackage), user);
applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage);
final ScanResult scanResult =
scanPackageOnlyLI(request, mInjector, mFactoryTest, -1L);
if (scanResult.existingSettingCopied && scanResult.request.pkgSetting != null) {
scanResult.request.pkgSetting.updateFrom(scanResult.pkgSetting);
}
}
}
}

final boolean newPkgChangedPaths =
pkgAlreadyExists && !pkgSetting.codePathString.equals(pkg.codePath);
final boolean newPkgVersionGreater =
pkgAlreadyExists && pkg.getLongVersionCode() > pkgSetting.versionCode;
final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated
&& newPkgChangedPaths && newPkgVersionGreater;

if (isSystemPkgBetter) {
synchronized (mPackages) { // 更新安装包到系统分区中
// just remove the loaded entries from package lists
mPackages.remove(pkgSetting.name); // 从 PackageManagerService 的安装包列表中删除该包
}
// 创建安装参数 InstallArgs
final InstallArgs args = createInstallArgsForExisting(
pkgSetting.codePathString,
pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting));
args.cleanUpResourcesLI();
synchronized (mPackages) {
mSettings.enableSystemPackageLPw(pkgSetting.name);
}
}
... ...

// 安装包校验
collectCertificatesLI(pkgSetting, pkg, forceCollect, skipVerify);

// Reset profile if the application version is changed
maybeClearProfilesForUpgradesLI(pkgSetting, pkg);

/*
* A new system app appeared, but we already had a non-system one of the
* same name installed earlier.
*
* 当我们安装一个系统 apk 的时候,发现已经有了一个相同包名的 apk,
* 而且这个相同包名 apk 是在非系统的分区中。
*/
boolean shouldHideSystemApp = false;
// A new application appeared on /system, but, we already have a copy of
// the application installed on /data.
if (scanSystemPartition && !isSystemPkgUpdated && pkgAlreadyExists
&& !pkgSetting.isSystem()) {
if (!pkg.mSigningDetails.checkCapability(pkgSetting.signatures.mSigningDetails,
PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)
&& !pkgSetting.signatures.mSigningDetails.checkCapability(
pkg.mSigningDetails,
PackageParser.SigningDetails.CertCapabilities.ROLLBACK)) {
logCriticalInfo(Log.WARN,
"System package signature mismatch;"
+ " name: " + pkgSetting.name);
try (PackageFreezer freezer = freezePackage(pkg.packageName,
"scanPackageInternalLI")) {
// 如果两个 apk 签名不匹配,则调用 deletePackageLI 方法清除 apk 文件及其数据
deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null);
}
pkgSetting = null;
} else if (newPkgVersionGreater) {
// The application on /system is newer than the application on /data.
// Simply remove the application on /data [keeping application data]
// and replace it with the version on /system.
logCriticalInfo(Log.WARN,
"System package enabled;"
+ " name: " + pkgSetting.name
+ "; " + pkgSetting.versionCode + " --> " + pkg.getLongVersionCode()
+ "; " + pkgSetting.codePathString + " --> " + pkg.codePath);
// 更新系统 apk 程序
InstallArgs args = createInstallArgsForExisting(
pkgSetting.codePathString,
pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
} else {
// The application on /system is older than the application on /data. Hide
// the application on /system and the version on /data will be scanned later
// and re-added like an update.
shouldHideSystemApp = true;
logCriticalInfo(Log.INFO,
"System package disabled;"
+ " name: " + pkgSetting.name
+ "; old: " + pkgSetting.codePathString + " @ " + pkgSetting.versionCode
+ "; new: " + pkg.codePath + " @ " + pkg.codePath);
}
}


// 重点方法
final ScanResult scanResult = scanPackageNewLI(pkg, parseFlags, scanFlags
| SCAN_UPDATE_SIGNATURE, currentTime, user);
... ...

// 如果新安装的系统 APK 会被旧的 APK 数据覆盖,所以需要隐藏隐藏系统应用程序,并重新扫描 /data/app 目录
if (shouldHideSystemApp) {
synchronized (mPackages) {
mSettings.disableSystemPackageLPw(pkg.packageName, true);
}
}
return scanResult.pkgSetting.pkg;
}

}

1.7 PackageManagerService.scanPackageNewLI

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

public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
... ...

@GuardedBy({"mInstallLock", "mPackages"})
private ScanResult scanPackageNewLI(@NonNull PackageParser.Package pkg,
final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
@Nullable UserHandle user) throws PackageManagerException {

final String renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage);
final String realPkgName = getRealPackageName(pkg, renamedPkgName);
if (realPkgName != null) {
ensurePackageRenamed(pkg, renamedPkgName);
}
final PackageSetting originalPkgSetting = getOriginalPackageLocked(pkg, renamedPkgName);
final PackageSetting pkgSetting = mSettings.getPackageLPr(pkg.packageName);
final PackageSetting disabledPkgSetting =
mSettings.getDisabledSystemPkgLPr(pkg.packageName);

if (mTransferedPackages.contains(pkg.packageName)) {
Slog.w(TAG, "Package " + pkg.packageName
+ " was transferred to another, but its .apk remains");
}

scanFlags = adjustScanFlags(scanFlags, pkgSetting, disabledPkgSetting, user, pkg);

synchronized (mPackages) {
applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage);
assertPackageIsValid(pkg, parseFlags, scanFlags);

SharedUserSetting sharedUserSetting = null;
if (pkg.mSharedUserId != null) {
// SIDE EFFECTS; may potentially allocate a new shared user
sharedUserSetting = mSettings.getSharedUserLPw(
pkg.mSharedUserId, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/);
if (DEBUG_PACKAGE_SCANNING) {
if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
Log.d(TAG, "Shared UserID " + pkg.mSharedUserId
+ " (uid=" + sharedUserSetting.userId + "):"
+ " packages=" + sharedUserSetting.packages);
}
}
final ScanRequest request = new ScanRequest(pkg, sharedUserSetting,
pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting,
originalPkgSetting, realPkgName, parseFlags, scanFlags,
(pkg == mPlatformPackage), user);
// 调用 scanPackageOnlyLI 方法,最终会调用到 commitPackageSettings 方法
return scanPackageOnlyLI(request, mInjector, mFactoryTest, currentTime);
}
}

}

1.8 PackageManagerService.commitPackageSettings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
... ...

/**
* Adds a scanned package to the system. When this method is finished, the package will
* be available for query, resolution, etc...
*/
private void commitPackageSettings(PackageParser.Package pkg,
@Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting,
final @ScanFlags int scanFlags, boolean chatty, ReconciledPackage reconciledPkg) {

final String pkgName = pkg.packageName;
if (mCustomResolverComponentName != null &&
mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
setUpCustomResolverActivity(pkg);
}

if (pkg.packageName.equals("android")) { // 针对包名为 "android" 的 apk 进行处理
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;
// 如果上面的代码中调用了 setUpCustomResolverActivity 方法,
// 在 setUpCustomResolverActivity 方法里面设置了 mResolverReplaced = true
// 如果没有调用 setUpCustomResolverActivity 方法,
// 配置相应 mResolveActivity 的属性。
if (!mResolverReplaced) {
mResolveActivity.applicationInfo = mAndroidApplication;
mResolveActivity.name = ResolverActivity.class.getName();
mResolveActivity.packageName = mAndroidApplication.packageName;
mResolveActivity.processName = "system:ui";
mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER;
mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert;
mResolveActivity.exported = true;
mResolveActivity.enabled = true;
mResolveActivity.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
mResolveActivity.configChanges = ActivityInfo.CONFIG_SCREEN_SIZE
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE
| ActivityInfo.CONFIG_SCREEN_LAYOUT
| ActivityInfo.CONFIG_ORIENTATION
| ActivityInfo.CONFIG_KEYBOARD
| ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
mResolveInfo.activityInfo = mResolveActivity;
mResolveInfo.priority = 0;
mResolveInfo.preferredOrder = 0;
mResolveInfo.match = 0;
mResolveComponentName = new ComponentName(
mAndroidApplication.packageName, mResolveActivity.name);
}
}
}
}

ArrayList<PackageParser.Package> clientLibPkgs = null;
// writer
synchronized (mPackages) {
if (!ArrayUtils.isEmpty(reconciledPkg.allowedSharedLibraryInfos)) {
for (SharedLibraryInfo info : reconciledPkg.allowedSharedLibraryInfos) {
commitSharedLibraryInfoLocked(info);
}
final Map<String, PackageParser.Package> combinedPackages =
reconciledPkg.getCombinedPackages();
try {
// Shared libraries for the package need to be updated.
updateSharedLibrariesLocked(pkg, null, combinedPackages);
} catch (PackageManagerException e) {
Slog.e(TAG, "updateSharedLibrariesLPr failed: ", e);
}
// Update all applications that use this library. Skip when booting
// since this will be done after all packages are scaned.
if ((scanFlags & SCAN_BOOTING) == 0) {
clientLibPkgs = updateAllSharedLibrariesLocked(pkg, combinedPackages);
}
}
}

... ...

// 这段函数后续还需要重新整理更新...
}

1.9 扫描非系统 Package

回到 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
/* 
* mOnlyCore 用于控制是否扫描非系统 Package
*/
if (!mOnlyCore) {
// do this first before mucking with mPackages for the "expecting better" case
final Iterator<PackageParser.Package> pkgIterator = mPackages.values().iterator();
while (pkgIterator.hasNext()) {
final PackageParser.Package pkg = pkgIterator.next();
if (pkg.isStub) {
stubSystemApps.add(pkg.packageName);
}
}

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

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

/*
* If the package is scanned, it's not erased.
*/
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
removePackageLI(scannedPkg, true);
mExpectingBetter.put(ps.name, ps.codePath);
}
continue;
}

if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
} else {
final PackageSetting disabledPs =
mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()
|| disabledPs.pkg == null) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
}
}
... ...

if (!mOnlyCore) {
// 扫描 /data/app 目录
scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);

// 扫描 /data/app-private 目录
scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
| PackageParser.PARSE_FORWARD_LOCK,
scanFlags | SCAN_REQUIRE_KNOWN, 0);

// 这里检查用户目录下升级文件是否还存在,然后进行处理
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);

// 从 mSettings.mDisabledSysPackages 变量中移除去此应用
mSettings.removeDisabledSystemPackageLPw(deletedAppName);
final String msg;

// 用户目录中也没有升级包,则肯定是残留的应用信息,则把它的数据目录删除掉
if (deletedPkg == null) {
msg = "Updated system package " + deletedAppName
+ " no longer exists; removing its data";
} else {
// 如果在用户空间找到了文件,则说明系统目录下的文件可能被删除了,
// 因此,把应用的系统属性去掉,以普通应用的方式运行
msg = "Updated system package + " + deletedAppName
+ " no longer exists; revoking system privileges";

final PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
}
// 报告系统发生了不一致的情况
logCriticalInfo(Log.WARN, msg);
}

// 处理 mExpectingBetter 列表,这个列表的应用是带有升级包的系统的应用,
// 前面把他们从 mPackages 列表中清除了并放到 mExpectingBetter 列表,
// 最后也对他们进行扫描处理,但不会放到 mPackages 中。
for (int i = 0; i < mExpectingBetter.size(); i++) {
final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
final File scanFile = mExpectingBetter.valueAt(i);

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 {
// 重新扫描一下这个文件,会添加一个 <update-package> 标签
scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 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);
}

... ...    // 扫描非系统 apk 工作完成
}

二、扫尾工作

这部分任务比较简单,就是将第二阶段 APK 的信息再集中整理一次,可自行研究。