[toc]
基于 Android 7.1.1 源码分析 PackageManagerService 的架构和逻辑实现,本文是作者原创,转载请说明出处!
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... ... ... ...// 接上面
long startTime = SystemClock.uptimeMillis();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);
// 设置扫描参数!
final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING | SCAN_INITIAL;
// 获得环境变量:BOOTCLASSPATH 和 SYSTEMSERVERCLASSPATH!
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!");
}
// 获得系统指令集合!
final List<String> allInstructionSets = InstructionSets.getAllInstructionSets();
final String[] dexCodeInstructionSets =
getDexCodeInstructionSets(
allInstructionSets.toArray(new String[allInstructionSets.size()]));
// 对所有的共享库执行 odex 操作!
if (mSharedLibraries.size() > 0) {
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
for (SharedLibraryEntry libEntry : mSharedLibraries.values()) {
final String lib = libEntry.path;
if (lib == null) {
continue;
}
try {
// Shared libraries do not have profiles so we perform a full
// AOT compilation (if needed).
int dexoptNeeded = DexFile.getDexOptNeeded(
lib, dexCodeInstructionSet,
getCompilerFilterForReason(REASON_SHARED_APK),
false /* newProfile */);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
getCompilerFilterForReason(REASON_SHARED_APK),
StorageManager.UUID_PRIVATE_INTERNAL,
SKIP_SHARED_LIBRARY_CHECK);
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Library not found: " + lib);
} catch (IOException | InstallerException e) {
Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
+ e.getMessage());
}
}
}
}
// 获得目录 /system/framework,对其目录下的文件进行优化 !
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
// 获得系统版本信息
final VersionInfo ver = mSettings.getInternalVersion();
// 判断是否是 OTA 升级,如果当前版本的指纹与历史版本的指纹信息不一致,表示当前版本是一次 OTA 升级上来更新版本!
mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
// 判断是否是从 Android M 之前的版本升级过来的,如果是就需要把系统 app 的权限从安装时提高到运行时!
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.
// 判断是否是从 Android 7.0 升级过来的!
mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;
mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
// 保存从 Android 6.0 升级前已经存在的系统应用,并对他们进行优先扫描!
// 扫描过程会将安装时权限变为运行时权限!
if (mPromoteSystemApps) {
Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
while (pkgSettingIter.hasNext()) {
PackageSetting ps = pkgSettingIter.next();
if (isSystemApp(ps)) {
mExistingSystemPackages.add(ps.name);
}
}
}
//【1】扫描收集目录 /vendor/overlay 下的供应商应用包!
File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
scanDirTracedLI(vendorOverlayDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
// Find base frameworks (resource packages without code).
//【2】扫描收集目录 /system/framework 下的应用包!
scanDirTracedLI(frameworkDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_NO_DEX, 0);
//【3】扫描收集目录 /system/priv-app 下的应用包!
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirTracedLI(privilegedAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
//【4】扫描收集目录 /system/app 下的应用包!
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
//【5】扫描收集目录 /vendor/app 下的应用包!
File vendorAppDir = new File("/vendor/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
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
//【6】扫描收集目录 /oem/app 下的应用包!
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// 收集可能已经被删掉的系统应用包!
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
if (!mOnlyCore) {
// 遍历上一次安装的信息!
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
// 如果不是系统应用,跳过!
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
continue;
}
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
// 如果系统应用包不仅被扫描过(在mPackages中),并且在不可用列表中!
// 说明一定是通过覆盖更新的,移除之前扫描的结果,保证之前用户安装的应用能够被扫描!
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
logCriticalInfo(Log.WARN, "Expecting better updated system app for "
+ ps.name + "; removing system app. Last known codePath="
+ ps.codePathString + ", installStatus=" + ps.installStatus
+ ", versionCode=" + ps.versionCode + "; scanned versionCode="
+ scannedPkg.mVersionCode);
// 将之前的扫描结果移除!
removePackageLI(scannedPkg, true);
// 将这包添加到 mExpectingBetter 列表中!
mExpectingBetter.put(ps.name, ps.codePath);
}
// 跳出循环,确保不会被删掉!
continue;
}
// 如果系统应用包没有被扫描,并且他也不在不可用的列表中,移除它,这个包不存在!
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
logCriticalInfo(Log.WARN, "System package " + ps.name
+ " no longer exists; it's data will be wiped");
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
// 如果系统应用包没有被扫描,却在不可用的列表中,就将他加入到
// possiblyDeletedUpdatedSystemApps 集合中,需要被删除!
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
}
}
// 清理所有安装不完全的应用包!
ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
for (int i = 0; i < deletePkgsList.size(); i++) {
// Actual deletion of code and data will be handled by later
// reconciliation step
final String packageName = deletePkgsList.get(i).name;
logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName);
synchronized (mPackages) {
mSettings.removePackageLPw(packageName);
}
}
// 移除临时文件
deleteTempPackageFiles();
// 移除没有和应用程序包相关联的共享用户 id!
mSettings.pruneSharedUsersLPw();
... ... ... ...// 见,第三阶段
主要流程如下:
- 对所有的共享库执行 odex 操作!
- 扫描手机系统目录信息!
- 收集那些可能已经不存在的系统应用包,在扫描完 data 分区后再处理!
- 清理所有安装不完全的应用包!
我们接下来继续分析:
1 对共享库执行 odex 操作
主要代码块如下: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// 对所有的共享库执行 odex 操作!
if (mSharedLibraries.size() > 0) {
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
for (SharedLibraryEntry libEntry : mSharedLibraries.values()) {
final String lib = libEntry.path;
if (lib == null) {
continue;
}
try {
// Shared libraries do not have profiles so we perform a full
// AOT compilation (if needed).
// 判断共享库是否需要执行 odex 操作
int dexoptNeeded = DexFile.getDexOptNeeded(
lib, dexCodeInstructionSet,
getCompilerFilterForReason(REASON_SHARED_APK),
false /* newProfile */);
// 如果需要 odex 操作,对共享库进行一次预编译(AOT)
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
getCompilerFilterForReason(REASON_SHARED_APK),
StorageManager.UUID_PRIVATE_INTERNAL,
SKIP_SHARED_LIBRARY_CHECK);
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Library not found: " + lib);
} catch (IOException | InstallerException e) {
Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
+ e.getMessage());
}
}
}
}
主要流程:
- 判断共享库是否需要执行 odex 操作;
- 如果需要执行 odex 操作,就对共享库进行预(AOT)处理;
2 系统目录扫描 - 开始阶段
主要代码如下: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// 设置扫描参数!
final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING | SCAN_INITIAL;
... ... ... ...
// 扫描收集目录 /vendor/overlay 下的供应商应用包,用于资源替换!!
File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
scanDirTracedLI(vendorOverlayDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
// Find base frameworks (resource packages without code).
// 扫描收集目录 /system/framework 下的应用包!
scanDirTracedLI(frameworkDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_NO_DEX, 0);
// 扫描收集目录 /system/priv-app 下的应用包!
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirTracedLI(privilegedAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
// 扫描收集目录 /system/app 下的应用包!
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// 扫描收集目录 /vendor/app 下的应用包!
File vendorAppDir = new File("/vendor/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
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// 扫描收集目录 /oem/app 下的应用包!
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
扫描参数的设置为:int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING | SCAN_INITIAL;
按照顺序扫描的目录有:
- /vendor/overlay
- /system/framework
- /system/priv-app
- /system/app
- /vendor/app
- /oem/app
调用 PMS.scanDirTracedLI 进行扫描,需要注意的是被扫描目录的顺序,这个顺序意味着:先被扫描到的文件,就是最终被用到的文件。
下面我们以 /system/app 目录为例,跟踪系统路径扫描的全过程!!
2.1 PMS.scanDirTracedLI
调用 scanDirTracedLI 方法进行目录扫描:1
2
3
4
5
6
7
8
9
10
11private void scanDirTracedLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir");
try {
//【2.2】进一步调用 scanDirLI 方法!
scanDirLI(dir, parseFlags, scanFlags, currentTime);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
2.2 PMS.scanDirLI
1 | private void scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime) { |
注意这里的 try catch 语句,后面方法抛出的异常都是在这个进行 catch 的!
判断 file 是否是 Package,必须要同时满足下面 2 个条件:
- file 以 “.apk” 结尾或者 file 是一个目录;
- file 不是存储类型的文件:
- file 不以 vmdl 开头且不以 .tmp 结尾;
- file 不以 smdl 开头且不以 .tmp 结尾;
- file 不以 smdl2tmp 开头;
2.3 PMS.scanPackageTracedLI
1 | private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags, |
继续:
2.4 PMS.scanPackageLI
1 | private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags, |
下面我们来分析扫描的过程!
3 系统目录扫描 - 扫描阶段
下面,我把 PackageParser 简称为 PParser!
3.1 PParser.parsePackage
参数 flags 为 parseFlags,不同的目录取值不同:
1 | public Package parsePackage(File packageFile, int flags) throws PackageParserException { |
这里有 2 中解析方式:
- 如果 packageFile 是一个目录的话,比如 /system/app/TimeService,那就采用第一种解析方式!
- 如果 packageFile 是一个非目录文件的话,比如 /system/app/MyService.apk,那就采用第二种解析方式!
这里给大家解释一下:
Android 5.0 以前,apk 都是直接位于 app 目录下的,比如:/system/app/MyService.apk;
从 5.0 以后,谷歌引入了 apk 拆分机制,就是支持将一个 apk 拆分成很多个具有相同签名的子 apk,为了支持 apk 拆分,谷歌增加了一级目录:/system/app/MyService/,这个目录里会存放一到多个 apk,比如 base.apk,split.apk;
pms 在解析 package 时,会把多个 apk 的数据封装成一个 Package,加载到内存中!!
3.1.1 PParser.parseClusterPackage
1 | private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException { |
这里我们分为 3 个阶段来看:
- 对目录下的所有 apk 进行整体解析;
- 对目录中的核心 apk 进行解析;
- 如果 apk 被拆分了,对非核心应用进行解析;
3.1.1.1 PParser.parseClusterPackageLite
首先,对目录下的所有 apk 进行整体解析: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
83private static PackageLite parseClusterPackageLite(File packageDir, int flags)
throws PackageParserException {
final File[] files = packageDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
"No packages found in split");
}
String packageName = null;
int versionCode = 0;
final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
//【1】遍历目录下的所有 apk 文件,包括主 apk 和子 apk!
for (File file : files) {
if (isApkFile(file)) {
//【3.1.1.1.1】解析 apk,将解析数据保存到 ApkLite 中!
final ApkLite lite = parseApkLite(file, flags);
if (packageName == null) {
packageName = lite.packageName;
versionCode = lite.versionCode;
} else {
if (!packageName.equals(lite.packageName)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Inconsistent package " + lite.packageName + " in " + file
+ "; expected " + packageName);
}
if (versionCode != lite.versionCode) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Inconsistent version " + lite.versionCode + " in " + file
+ "; expected " + versionCode);
}
}
// 将解析得到的 ApkLite 对象添加到一个 ArrayMap 集合中!
// 注意:对于核心 apk,splitName 为 null!
if (apks.put(lite.splitName, lite) != null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Split name " + lite.splitName
+ " defined more than once; most recent was " + file);
}
}
}
//【2】从列表中移除核心 apk,保存到 baseApk 中,之所以 remove null,是因为 base apk 的 splitName 为 null!
// 如果没有 base apk,那就报错!!
final ApkLite baseApk = apks.remove(null);
if (baseApk == null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Missing base APK in " + packageDir);
}
//【3】处理非核心的 apk!
final int size = apks.size();
String[] splitNames = null;
String[] splitCodePaths = null;
int[] splitRevisionCodes = null;
if (size > 0) {
//【3.1】获得非核心 apk 的 splitName,codePath 和 splitRevisionCodes!
splitNames = new String[size];
splitCodePaths = new String[size];
splitRevisionCodes = new int[size];
splitNames = apks.keySet().toArray(splitNames);
Arrays.sort(splitNames, sSplitNameComparator);
for (int i = 0; i < size; i++) {
splitCodePaths[i] = apks.get(splitNames[i]).codePath;
splitRevisionCodes[i] = apks.get(splitNames[i]).revisionCode;
}
}
final String codePath = packageDir.getAbsolutePath();
//【3.1.1.1.2】创建所有应用的 PackageLite 解析对象,返回!
return new PackageLite(codePath, baseApk, splitNames, splitCodePaths,
splitRevisionCodes);
}
这里调用了 parseApkLite 方法,解析 dir 下的核心 apk 和非核心 apk(如果有),然后获得非核心 apk 的 splitNames、splitCodePaths 和 splitRevisionCodes,最后创建 package 的 PackageLite 对象,并返回!
3.1.1.1.1 PParser.parseApkLite[2]
解析 apk 文件!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
64public static ApkLite parseApkLite(File apkFile, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
AssetManager assets = null;
XmlResourceParser parser = null;
try {
// 创建资源管理器
assets = new AssetManager();
assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
// 首先将 apk 中的资源加载到资源管理器 asserts 中。
int cookie = assets.addAssetPath(apkPath);
if (cookie == 0) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
"Failed to parse " + apkPath);
}
final DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
final Resources res = new Resources(assets, metrics, null);
//【1】创建解析器,用来解析 apk 的 AndroidMenifest.xml 文件。
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final Signature[] signatures;
final Certificate[][] certificates;
if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
// TODO: factor signature related items out of Package object
final Package tempPkg = new Package(null);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
try {
// 进行签名验证,并将签名保存在 signatures 中。
collectCertificates(tempPkg, apkFile, 0 /*parseFlags*/);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
signatures = tempPkg.mSignatures;
certificates = tempPkg.mCertificates;
} else {
signatures = null;
certificates = null;
}
// 将 <manifest> 标签的属性付给 attrs!
final AttributeSet attrs = parser;
//【3.1.1.1.1.1】接着调用 parseApkLite 继续解析!
return parseApkLite(apkPath, res, parser, attrs, flags, signatures, certificates);
} catch (XmlPullParserException | IOException | RuntimeException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to parse " + apkPath, e);
} finally {
IoUtils.closeQuietly(parser);
IoUtils.closeQuietly(assets);
}
}
调用重载函数 parseApkLite 函数,继续解析,参数传递:
3.1.1.1.1.1 PParser.parseApkLite[7]
1 | private static ApkLite parseApkLite(String codePath, Resources res, XmlPullParser parser, |
3.1.1.1.1.2 PParser.parsePackageSplitNames
该方法用于解析 apk 的 “manifest” 标签的 package 属性和 split 属性!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
46private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
AttributeSet attrs) throws IOException, XmlPullParserException,
PackageParserException {
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
}
if (type != XmlPullParser.START_TAG) {
throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"No start tag found");
}
if (!parser.getName().equals(TAG_MANIFEST)) { // 如果不是 manifest 标签!
throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"No <manifest> tag");
}
//【1】解析 manifest 标签的 package 属性!
final String packageName = attrs.getAttributeValue(null, "package");
if (!"android".equals(packageName)) {
// 如果 package 不是 android,那需要校验格式!
final String error = validateName(packageName, true, true);
if (error != null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
"Invalid manifest package: " + error);
}
}
//【2】解析 manifest 标签的 split 属性!
String splitName = attrs.getAttributeValue(null, "split");
if (splitName != null) {
if (splitName.length() == 0) {
splitName = null;
} else {
final String error = validateName(splitName, false, false);
if (error != null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
"Invalid manifest split: " + error);
}
}
}
//【3】返回 packageName 和 splitName 的 Pair 对象!
return Pair.create(packageName.intern(),
(splitName != null) ? splitName.intern() : splitName);
}
接着创建一个 ApkLite 对象,用来封装 apk 的解析信息!
3.1.1.1.1.3 new ApkLite
最后,将结果封装为一个 ApkLite 对象,并返回!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
34public static class ApkLite {
public final String codePath; // apk 路径,就是 apk 文件的绝对路径!
public final String packageName; // 应用程序包名
public final String splitName; // 非核心 apk 包名
public final int versionCode; // 版本号
public final int revisionCode; // 修订版本号
public final int installLocation; // 安装位置
public final VerifierInfo[] verifiers; // 校验信息
public final Signature[] signatures; // 签名信息
public final Certificate[][] certificates; // 证书信息
public final boolean coreApp; // 是否是核心应用
public final boolean multiArch; // 是否支持多软件架构
public final boolean use32bitAbi; // 是否使用 32 位系统指令集
public final boolean extractNativeLibs; // 是否依赖额外的本地库
public ApkLite(String codePath, String packageName, String splitName, int versionCode,
int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Signature[] signatures, Certificate[][] certificates, boolean coreApp,
boolean multiArch, boolean use32bitAbi, boolean extractNativeLibs) {
this.codePath = codePath;
this.packageName = packageName;
this.splitName = splitName;
this.versionCode = versionCode;
this.revisionCode = revisionCode;
this.installLocation = installLocation;
this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
this.signatures = signatures;
this.certificates = certificates;
this.coreApp = coreApp;
this.multiArch = multiArch;
this.use32bitAbi = use32bitAbi;
this.extractNativeLibs = extractNativeLibs;
}
}
然后返回,回到 PP.parseClusterPackageLite 函数中,根据解析的结果,创建 PackageLite 对象:
3.1.1.1.2 new PackageLite
PackageLite 用来封装一个应用程序包的信息,PackageLite 的构造器如下:
1 | public static class PackageLite { |
这里我们不在过多分析!!
3.1.1.2 PParser.parseBaseApk[3]
解析 base apk: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
52private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
String volumeUuid = null;
if (apkPath.startsWith(MNT_EXPAND)) { // 解析 /mnt/expand/
final int end = apkPath.indexOf('/', MNT_EXPAND.length());
volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
}
mParseError = PackageManager.INSTALL_SUCCEEDED;
mArchiveSourcePath = apkFile.getAbsolutePath();
if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
Resources res = null;
XmlResourceParser parser = null;
try {
res = new Resources(assets, mMetrics, null);
assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
//【1】用于解析 AndroidManifest.xml 文件!
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final String[] outError = new String[1];
//【3.1.1.2】解析核心 apk!
final Package pkg = parseBaseApk(res, parser, flags, outError);
if (pkg == null) {
throw new PackageParserException(mParseError,
apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
}
pkg.setVolumeUuid(volumeUuid);
pkg.setApplicationVolumeUuid(volumeUuid);
pkg.setBaseCodePath(apkPath);
pkg.setSignatures(null);
return pkg;
} catch (PackageParserException e) {
throw e;
} catch (Exception e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to read manifest from " + apkPath, e);
} finally {
IoUtils.closeQuietly(parser);
}
}
接着,调用重载 parseBaseApk 方法:
3.1.1.2.1 PParser.parseBaseApk[4]
我们继续来看: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
52private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
String[] outError) throws XmlPullParserException, IOException {
final String splitName;
final String pkgName;
try {
//【3.1.1.1.1.2】解析 <manifest> 标签,获得 packageName 和 splitName,
// 以 Pair<packageName, splitName> 的形式返回!
Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
pkgName = packageSplit.first;
splitName = packageSplit.second;
if (!TextUtils.isEmpty(splitName)) {
outError[0] = "Expected base APK, but found split " + splitName;
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
return null;
}
} catch (PackageParserException e) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
return null;
}
//【3.1.3】创建一个 Package 对象,用于保存最终的解析信息!
final Package pkg = new Package(pkgName);
// 解析 <manifest> 标签,获得 versionCode、revisionCode、versionName、coreApp 值!
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifest);
pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
pkg.baseRevisionCode = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
pkg.mVersionName = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifest_versionName, 0);
if (pkg.mVersionName != null) {
pkg.mVersionName = pkg.mVersionName.intern();
}
pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
sa.recycle();
//【3.1.1.2.2】接着,调用 parseBaseApkCommon 方法,继续解析!
return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
}
3.1.1.2.2 PParser.parseBaseApkCommon [6]
进入最终的解析方法中:
- Package pkg:应用程序的信息封装对象;
- Set
acceptedTags:需要解析的标签,如果传入 null ,表示解析所有,这里传入 null; - Resources res:
- XmlResourceParser parser:
- int flags:
- String[] outError:用于保存解析过程中的错误信息;
1 | private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res, |
在这个方法中,解析 apk 中的四大组件,权限等信息,核心 apk 解析到此为止!
3.1.1.2.2.1 PParser.parsePermissionGroup - 解析 permission-group
parsePermissionGroup 用于解析该应用所使用到的 permission-group:
1 | private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res, |
这里就不多说了!
3.1.1.2.2.2 PParser.parsePermission - 解析 permission
parsePermission 解析该应用中定义的权限!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
69private Permission parsePermission(Package owner, Resources res,
XmlResourceParser parser, String[] outError)
throws XmlPullParserException, IOException {
//【1】创建 Permission 对象
Permission perm = new Permission(owner);
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestPermission);
if (!parsePackageItemInfo(owner, perm.info, outError,
"<permission>", sa, true /*nameRequired*/,
com.android.internal.R.styleable.AndroidManifestPermission_name,
com.android.internal.R.styleable.AndroidManifestPermission_label,
com.android.internal.R.styleable.AndroidManifestPermission_icon,
com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
com.android.internal.R.styleable.AndroidManifestPermission_logo,
com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
sa.recycle();
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
}
// 解析 android:permissionGroup 属性
perm.info.group = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
if (perm.info.group != null) {
perm.info.group = perm.info.group.intern();
}
perm.info.descriptionRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestPermission_description,
0);
// 解析 android:protectionLevel 属性
perm.info.protectionLevel = sa.getInt(
com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
PermissionInfo.PROTECTION_NORMAL);
// 解析 android:permissionFlags 属性
perm.info.flags = sa.getInt(
com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
sa.recycle();
if (perm.info.protectionLevel == -1) {
outError[0] = "<permission> does not specify protectionLevel";
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
}
perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
PermissionInfo.PROTECTION_SIGNATURE) {
outError[0] = "<permission> protectionLevel specifies a flag but is "
+ "not based on signature type";
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
}
}
if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
}
// 将解析的权限信息保存到 owner.permissions 中!
owner.permissions.add(perm);
return perm;
}
解析很简单,不多说了!
3.1.1.2.2.3 PParser.parsePermissionTree - 解析 permission-tree
parsePermissionTree 用于解析该应用所使用到的 permission-tree:
1 | private Permission parsePermissionTree(Package owner, Resources res, |
3.1.1.2.2.4 PParser.parseUsesPermission - 解析 uses-permission
parseUsesPermission 解析该应用所使用的权限!
1 | private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser) |
解析很简单,不多说了!
3.1.1.2.3 PParser.parseBaseApplication
调用 parseBaseApplication 方法来解析核心 apk 的 applicaiton 标签和内部的四大组件信息!!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
443private boolean parseBaseApplication(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
//【1】解析 application 标签的属性!
final ApplicationInfo ai = owner.applicationInfo;
final String pkgName = owner.applicationInfo.packageName;
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestApplication);
// 解析 android:name android:label android:icon android:roundIcon android:logo android:banner 属性!
if (!parsePackageItemInfo(owner, ai, outError,
"<application>", sa, false /*nameRequired*/,
com.android.internal.R.styleable.AndroidManifestApplication_name,
com.android.internal.R.styleable.AndroidManifestApplication_label,
com.android.internal.R.styleable.AndroidManifestApplication_icon,
com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
com.android.internal.R.styleable.AndroidManifestApplication_logo,
com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
sa.recycle();
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
if (ai.name != null) {
ai.className = ai.name;
}
// 解析 android:manageSpaceActivity 属性!
String manageSpaceActivity = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
Configuration.NATIVE_CONFIG_VERSION);
if (manageSpaceActivity != null) {
ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
outError);
}
//【1】解析 android:allowBackup 属性,为 true 表示应用允许备份!
boolean allowBackup = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
if (allowBackup) {
ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP; // 如果为 true,设置 FLAG_ALLOW_BACKUP 标志位
// 解析 android:backupAgent 属性!
String backupAgent = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
Configuration.NATIVE_CONFIG_VERSION);
if (backupAgent != null) {
ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
if (DEBUG_BACKUP) {
Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
+ " from " + pkgName + "+" + backupAgent);
}
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
true)) {
// 解析 android:killAfterRestore 属性,为 true 设置 FLAG_KILL_AFTER_RESTORE 标志位
ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
}
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
false)) {
// 解析 android:restoreAnyVersion 属性,为 true 设置 FLAG_RESTORE_ANY_VERSION 标志位
ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
}
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
false)) {
// 解析 android:fullBackupOnly 属性,为 true 设置 FLAG_FULL_BACKUP_ONLY 标志位
ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
}
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
false)) {
// 解析 android:backupInForeground 属性,为 true 设置 PRIVATE_FLAG_BACKUP_IN_FOREGROUND 标志位
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
}
}
// 解析 android:fullBackupContent 属性!
TypedValue v = sa.peekValue(
com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
if (DEBUG_BACKUP) {
Slog.v(TAG, "fullBackupContent specified as boolean=" +
(v.data == 0 ? "false" : "true"));
}
// "false" => -1, "true" => 0
ai.fullBackupContent = (v.data == 0 ? -1 : 0);
}
if (DEBUG_BACKUP) {
Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
}
}
// 解析 android:theme android:description 属性!
ai.theme = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
ai.descriptionRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
// 如果设置了 PARSE_IS_SYSTEM,并且 android:persistent 为 true
// 那么 ai.flags 设置 ApplicationInfo.FLAG_PERSISTENT 标志位,其为 persistent 属性!
if ((flags&PARSE_IS_SYSTEM) != 0) {
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_persistent,
false)) {
ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
}
}
// 解析 android:requiredForAllUsers 属性,为true,表示该应用在所有 user 下都可用!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
false)) {
owner.mRequiredForAllUsers = true;
}
// 解析 android:requiredAccountType android:restrictedAccountType 的属性!
String restrictedAccountType = sa.getString(com.android.internal.R.styleable
.AndroidManifestApplication_restrictedAccountType);
if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
owner.mRestrictedAccountType = restrictedAccountType;
}
String requiredAccountType = sa.getString(com.android.internal.R.styleable
.AndroidManifestApplication_requiredAccountType);
if (requiredAccountType != null && requiredAccountType.length() > 0) {
owner.mRequiredAccountType = requiredAccountType;
}
// 解析 android:debuggable android:vmSafeMode 属性!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
false)) {
ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
}
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
false)) {
ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
}
// 解析 android:hardwareAccelerated 属性!
owner.baseHardwareAccelerated = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
if (owner.baseHardwareAccelerated) {
ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
}
// 解析 android:hasCode 属性!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
true)) {
ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
}
// 解析 android:allowTaskReparenting 属性,这个属性很重要,决定了 acivity 和 task 的关系
// 在 application 标签上设置该属性对内部的所有 activity 生效!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
false)) {
ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
}
// 解析 android:allowClearUserData 属性!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
true)) {
ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
}
// The parent package controls installation, hence specify test only installs.
if (owner.parentPackage == null) {
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
false)) {
ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
}
}
// 解析 android:largeHeap 属性!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
false)) {
ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
}
// 解析 android:usesCleartextTraffic 属性!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
true)) {
ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
}
// 解析 android:supportsRtl 属性!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
false /* default is no RTL support*/)) {
ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
}
// 解析 android:multiArch 属性!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
false)) {
ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
}
// 解析 android:extractNativeLibs 属性!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
true)) {
ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
}
// 解析 android:defaultToDeviceProtectedStorage 属性!
if (sa.getBoolean(
R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
false)) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
}
// 解析 android:directBootAware 属性!
if (sa.getBoolean(
R.styleable.AndroidManifestApplication_directBootAware,
false)) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
}
// 解析 android:resizeableActivity 属性!
if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity,
owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N)) {
ai.privateFlags |= PRIVATE_FLAG_RESIZEABLE_ACTIVITIES;
}
// 解析 android:networkSecurityConfig 属性!
ai.networkSecurityConfigRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
0);
// 解析 android:permission 属性!
String str;
str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
// 解析 android:taskAffinity 属性,这个属性很重要,决定了 acivity 和 task 的关系
// 在 application 标签上设置该属性对内部的所有 activity 生效!
if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
Configuration.NATIVE_CONFIG_VERSION);
} else {
str = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
}
ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
str, outError);
if (outError[0] == null) {
CharSequence pname;
// 解析 android:process 属性,这个属性很重要,决定了组件运行所在的进程名
// 在 application 标签上设置该属性对内部的所有组件生效!
if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
pname = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_process,
Configuration.NATIVE_CONFIG_VERSION);
} else {
pname = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestApplication_process);
}
ai.processName = buildProcessName(ai.packageName, null, pname,
flags, mSeparateProcesses, outError);
// 解析 android:isGame android:enabled 属性,
ai.enabled = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
ai.flags |= ApplicationInfo.FLAG_IS_GAME;
}
if (false) {
// 解析 android:cantSaveState 属性,这里由于 if 为 false,所以不会解析!
// 主要用于 height-weight 类型的应用!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
false)) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
// 对于 height-weight 类型的应用,其所在进程的进程名只能是包名,我们无法自定义其进程名!
if (ai.processName != null && ai.processName != ai.packageName) {
outError[0] = "cantSaveState applications can not use custom processes";
}
}
}
}
// 解析 android:uiOptions 属性!
ai.uiOptions = sa.getInt(
com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
sa.recycle();
if (outError[0] != null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
//【2】解析四大组件!
final int innerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
//【2.1】解析 "activity" 组件
if (tagName.equals("activity")) {
Activity a = parseActivity(owner, res, parser, flags, outError, false,
owner.baseHardwareAccelerated);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.activities.add(a);
//【2.2】解析 "receiver" 组件
} else if (tagName.equals("receiver")) {
Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.receivers.add(a);
//【2.3】解析 "service" 组件
} else if (tagName.equals("service")) {
Service s = parseService(owner, res, parser, flags, outError);
if (s == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.services.add(s);
//【2.4】解析 "provider" 组件
} else if (tagName.equals("provider")) {
Provider p = parseProvider(owner, res, parser, flags, outError);
if (p == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.providers.add(p);
} else if (tagName.equals("activity-alias")) {
//【2.5】解析 "activity-alias" 组件
Activity a = parseActivityAlias(owner, res, parser, flags, outError);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.activities.add(a);
} else if (parser.getName().equals("meta-data")) {
//【2.6】解析 "meta-data" 组件
if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
outError)) == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
} else if (tagName.equals("library")) {
//【2.6】解析 "library" 组件
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestLibrary);
String lname = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestLibrary_name);
sa.recycle();
if (lname != null) {
lname = lname.intern();
if (!ArrayUtils.contains(owner.libraryNames, lname)) {
owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);
}
}
XmlUtils.skipCurrentTag(parser);
} else if (tagName.equals("uses-library")) {
//【2.7】解析 "uses-library" 组件
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestUsesLibrary);
// Note: don't allow this value to be a reference to a resource
// that may change.
String lname = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
boolean req = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
true);
sa.recycle();
if (lname != null) {
lname = lname.intern();
if (req) {
owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
} else {
owner.usesOptionalLibraries = ArrayUtils.add(
owner.usesOptionalLibraries, lname);
}
}
XmlUtils.skipCurrentTag(parser);
} else if (tagName.equals("uses-package")) {
// Dependencies for app installers; we don't currently try to
// enforce this.
XmlUtils.skipCurrentTag(parser);
} else {
if (!RIGID_PARSER) {
Slog.w(TAG, "Unknown element under <application>: " + tagName
+ " at " + mArchiveSourcePath + " "
+ parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
continue;
} else {
outError[0] = "Bad element under <application>: " + tagName;
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
}
}
modifySharedLibrariesForBackwardCompatibility(owner);
if (hasDomainURLs(owner)) {
owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
} else {
owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
}
return true;
}
这里重点的是四大组件的解析:
3.1.1.2.3.1 PParser.parseActivity - 解析 activity 和 receiver
我们来看看 activity 的解析过程:
1 | private Activity parseActivity(Package owner, Resources res, |
整个解析过程很清晰,就是不断读取对应标签的属性,然后设置 Activity 的属性和标志位!
3.1.1.2.3.2 PParser.parseService - 解析 service
1 | private Service parseService(Package owner, Resources res, |
3.1.1.2.3.3 PParser.parseProvider - 解析 parseProvider
接下来是解析 provider: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
137private Provider parseProvider(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestProvider);
// 解析 android:name android:label android:icon android:roundIcon android:logo android:banner 属性!
if (mParseProviderArgs == null) {
mParseProviderArgs = new ParseComponentArgs(owner, outError,
com.android.internal.R.styleable.AndroidManifestProvider_name,
com.android.internal.R.styleable.AndroidManifestProvider_label,
com.android.internal.R.styleable.AndroidManifestProvider_icon,
com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
com.android.internal.R.styleable.AndroidManifestProvider_logo,
com.android.internal.R.styleable.AndroidManifestProvider_banner,
mSeparateProcesses,
com.android.internal.R.styleable.AndroidManifestProvider_process,
com.android.internal.R.styleable.AndroidManifestProvider_description,
com.android.internal.R.styleable.AndroidManifestProvider_enabled);
mParseProviderArgs.tag = "<provider>";
}
mParseProviderArgs.sa = sa;
mParseProviderArgs.flags = flags;
// 创建一个 Provider 对象!
Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
if (outError[0] != null) {
sa.recycle();
return null;
}
boolean providerExportedDefault = false;
if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
// For compatibility, applications targeting API level 16 or lower
// should have their content providers exported by default, unless they
// specify otherwise.
providerExportedDefault = true;
}
// 解析 android:exported 属性!
p.info.exported = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestProvider_exported,
providerExportedDefault);
// 解析 android:authorities 属性!
String cpname = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
// 解析 android:syncable 属性!
p.info.isSyncable = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestProvider_syncable,
false);
// 解析 android:permission 属性!
String permission = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
// 解析 android:readPermission 属性!
String str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
if (str == null) {
str = permission;
}
if (str == null) {
p.info.readPermission = owner.applicationInfo.permission;
} else {
p.info.readPermission =
str.length() > 0 ? str.toString().intern() : null;
}
// 解析 android:writePermission 属性!
str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
if (str == null) {
str = permission;
}
if (str == null) {
p.info.writePermission = owner.applicationInfo.permission;
} else {
p.info.writePermission =
str.length() > 0 ? str.toString().intern() : null;
}
// 解析 android:grantUriPermissions 属性!
p.info.grantUriPermissions = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
false);
// 解析 android:multiprocess 属性!
p.info.multiprocess = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
false);
// 解析 android:initOrder 属性!
p.info.initOrder = sa.getInt(
com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
0);
p.info.flags = 0;
// 解析 android:singleUser 属性!
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
false)) {
p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
if (p.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Slog.w(TAG, "Provider exported request ignored due to singleUser: "
+ p.className + " at " + mArchiveSourcePath + " "
+ parser.getPositionDescription());
p.info.exported = false;
}
}
// 解析 android:directBootAware 属性!
p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
R.styleable.AndroidManifestProvider_directBootAware,
false);
if (p.info.directBootAware) {
owner.applicationInfo.privateFlags |=
ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
}
sa.recycle();
// 如果应用设置为 height-weight 类型的应用,对进程名要做校验!
if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
!= 0) {
if (p.info.processName == owner.packageName) {
outError[0] = "Heavy-weight applications can not have providers in main process";
return null;
}
}
if (cpname == null) {
outError[0] = "<provider> does not include authorities attribute";
return null;
}
if (cpname.length() <= 0) {
outError[0] = "<provider> has empty authorities attribute";
return null;
}
p.info.authority = cpname.intern();
if (!parseProviderTags(res, parser, p, outError)) {
return null;
}
return p;
}
对 provider 的解析就分析到这里!
3.1.1.2.3.4 PParser.parseIntent - 解析 intent-filter
接下来,我们来看看对 activity receiver provider 的 intent-filter 的解析!
1 | private boolean parseIntent(Resources res, XmlResourceParser parser, |
对 intent-filter 的解析就到这里!
3.1.1.3 PParser.parseSplitApk[4]
核心 apk 解析完成后,会返回一个 Package 对象,传入 parseSplitApk,用于解析非核心 apk: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
41private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = pkg.splitCodePaths[splitIndex];
mParseError = PackageManager.INSTALL_SUCCEEDED;
mArchiveSourcePath = apkPath;
if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
Resources res = null;
XmlResourceParser parser = null;
try {
res = new Resources(assets, mMetrics, null);
assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
// 用于解析 AndroidManifest.xml 文件!
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final String[] outError = new String[1];
//【3.1.1.3.1】解析非核心 apk!
pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
if (pkg == null) {
throw new PackageParserException(mParseError,
apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
}
} catch (PackageParserException e) {
throw e;
} catch (Exception e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to read manifest from " + apkPath, e);
} finally {
IoUtils.closeQuietly(parser);
}
}
这个过程个解析 base apk 一样,我们不多关注!
3.1.1.3.1 PParser.parseSplitApk[5]
1 | private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags, |
进入 parseSplitApplication 方法!
3.1.1.3.2 PParser.parseSplitApplication
1 | private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser, |
到这里,应用程序包就已经被解析完了,最终,所有 apk 的数据都会封装到一个 Package 对象中返回!
3.1.2 PParser.parseMonolithicPackage
对于不支持 apk 拆分的 package,PMS 使用 parseMonolithicPackage 进行解析,典型的不支持拆分的 apk,是 /system/framework/framework-res.apk,下面我们来看看这个方法:
1 |
|
3.1.2.1 PParser.parseMonolithicPackageLite
继续调用 parseMonolithicPackageLite 方法:1
2
3
4
5
6
7
8
9
10private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
throws PackageParserException {
// 同样的,调用 parseApkLite 直接对 apk 进行解析,返回 ApkLite 对象!
final ApkLite baseApk = parseApkLite(packageFile, flags);
final String packagePath = packageFile.getAbsolutePath();
// 创建 PackageLite 对象!
return new PackageLite(packagePath, baseApk, null, null, null);
}
最后,同样的,还是返回一个 PackageParser.Package 对象!
这里就不多说了!
3.1.3 Package
我们来看看 Pacakge 结构体,他用来分装一个应用程序包的完整信息: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
130public final static class Package {
public String packageName; // 应用程序包名
public String[] splitNames; // 非核心 apk 的名称
public String volumeUuid;
public String codePath; // 应用程序包的路径
public String baseCodePath; // 核心 apk 的路径
public String[] splitCodePaths; // 非核心 apk 的路径
public int baseRevisionCode; // 核心 apk
public int[] splitRevisionCodes;
public int[] splitFlags;
public int[] splitPrivateFlags;
public boolean baseHardwareAccelerated;
// For now we only support one application per package.
public final ApplicationInfo applicationInfo = new ApplicationInfo(); // 核心 apk 的 application 对象!
public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
public final ArrayList<Service> services = new ArrayList<Service>(0);
public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
public final ArrayList<String> requestedPermissions = new ArrayList<String>();
public ArrayList<String> protectedBroadcasts;
public Package parentPackage;
public ArrayList<Package> childPackages;
public ArrayList<String> libraryNames = null;
public ArrayList<String> usesLibraries = null;
public ArrayList<String> usesOptionalLibraries = null;
public String[] usesLibraryFiles = null;
public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
public ArrayList<String> mOriginalPackages = null;
public String mRealPackage = null;
public ArrayList<String> mAdoptPermissions = null;
// We store the application meta-data independently to avoid multiple unwanted references
public Bundle mAppMetaData = null;
// The version code declared for this package.
public int mVersionCode;
// The version name declared for this package.
public String mVersionName;
// The shared user id that this package wants to use.
public String mSharedUserId;
// The shared user label that this package wants to use.
public int mSharedUserLabel;
// Signatures that were read from the package.
public Signature[] mSignatures;
public Certificate[][] mCertificates;
// For use by package manager service for quick lookup of
// preferred up order.
public int mPreferredOrder = 0;
// For use by package manager to keep track of when a package was last used.
public long[] mLastPackageUsageTimeInMills =
new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
// // User set enabled state.
// public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
//
// // Whether the package has been stopped.
// public boolean mSetStopped = false;
// Additional data supplied by callers.
public Object mExtras;
// Applications hardware preferences
public ArrayList<ConfigurationInfo> configPreferences = null;
// Applications requested features
public ArrayList<FeatureInfo> reqFeatures = null;
// Applications requested feature groups
public ArrayList<FeatureGroupInfo> featureGroups = null;
public int installLocation;
public boolean coreApp;
/* An app that's required for all users and cannot be uninstalled for a user */
public boolean mRequiredForAllUsers;
/* The restricted account authenticator type that is used by this application */
public String mRestrictedAccountType;
/* The required account type without which this application will not function */
public String mRequiredAccountType;
public String mOverlayTarget;
public int mOverlayPriority;
public boolean mTrustedOverlay;
public ArraySet<PublicKey> mSigningKeys;
public ArraySet<String> mUpgradeKeySets;
public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
public String cpuAbiOverride;
public boolean use32bitAbi;
public byte[] restrictUpdateHash;
public Package(String packageName) {
this.packageName = packageName;
applicationInfo.packageName = packageName;
applicationInfo.uid = -1;
}
... ... ... ...
}
通过 PParser.parsePackage 方法,最终会返回一个 Package 对象,封装了应用程序包的所有信息!!
3.2 PMS.scanPackageLI
参数 policyFlags 为 paraseFlags!
前一个阶段,通过解析获得了 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
35private PackageParser.Package scanPackageLI(PackageParser.Package pkg, File scanFile,
final int policyFlags, int scanFlags, long currentTime, UserHandle user)
throws PackageManagerException {
//【1】SCAN_CHECK_ONLY 标签是为了检测是否所有的包(parent 和 child)都可以被成功的扫描到!
if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
if (pkg.childPackages != null && pkg.childPackages.size() > 0) {
scanFlags |= SCAN_CHECK_ONLY; // 设置 SCAN_CHECK_ONLY 位!
}
} else {
scanFlags &= ~SCAN_CHECK_ONLY; // 取消 SCAN_CHECK_ONLY 位!
}
//【3.2.1】继续扫描当前 package,返回扫描结果 scannedPkg!
PackageParser.Package scannedPkg = scanPackageInternalLI(pkg, scanFile, policyFlags,
scanFlags, currentTime, user);
// 扫描当前 package 的子 pacakge(如果有)
final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageParser.Package childPackage = pkg.childPackages.get(i);
// 解析子包!
scanPackageInternalLI(childPackage, scanFile, policyFlags, scanFlags,
currentTime, user);
}
if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
// 如果设置了 SCAN_CHECK_ONLY 位, 就调用自身,再次处理!
return scanPackageLI(pkg, scanFile, policyFlags, scanFlags, currentTime, user);
}
return scannedPkg;
}
如果被扫描的 package 有 child package,并且是第一次进入该方法的话,就需要检测是否所有的包(parent 和 child)都可以被成功的扫描到,scanFlags 本来是没有 SCAN_CHECK_ONLY 位的,所以这里会将其 SCAN_CHECK_ONLY 置为 1,这样在方法的最后,又会调用自身,这次又会将 SCAN_CHECK_ONLY 位置为 0!
继续看:
3.2.1 PMS.scanPackageInternalLI
我们继续来看,通过前面的扫描解析,我们获得了应用程序的 PackageParser.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
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
257private PackageParser.Package scanPackageInternalLI(PackageParser.Package pkg, File scanFile,
int policyFlags, int scanFlags, long currentTime, UserHandle user)
throws PackageManagerException {
PackageSetting ps = null;
PackageSetting updatedPkg;
synchronized (mPackages) {
// package 是否被重命名过,有的话,获得其 oldName!
String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
//【3.2.1.1】如果 package 有源包,并且源包的名字是当前扫描的 package 的旧名字,
// 那就用源包的 PackageSetting 作为当前 package 的数据!
if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
ps = mSettings.peekPackageLPr(oldName);
}
// 如果没有源包,就用当前 package 的包名查找一个已的 PackageSetting!
if (ps == null) {
ps = mSettings.peekPackageLPr(pkg.packageName);
}
//【3.2.1.2】如果当前系统 package 被更新过,就查找到被更新之前的 PackageSetting!
updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
// 如果系统 package,并且被更新过,需要处理新旧 child package 的差异!
// 比较更新后的 child package 和更新前的 child package,如果更新前的 child package 不存在了;
// 就要移除!
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(pkg.packageName);
if (disabledPs != null) {
// 当前 package 的 child package 个数!
final int scannedChildCount = (pkg.childPackages != null)
? pkg.childPackages.size() : 0;
// 更新之前的 child package 个数!
final int disabledChildCount = disabledPs.childPackageNames != null
? disabledPs.childPackageNames.size() : 0;
for (int i = 0; i < disabledChildCount; i++) {
String disabledChildPackageName = disabledPs.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) {
//【3.2.1.3】更新前的 child package,不包含在更新后的 child package 中,无效,
// 就从 mDisabledSysPackages 中删除掉!
mSettings.removeDisabledSystemPackageLPw(disabledChildPackageName);
}
}
}
}
}
boolean updatedPkgBetter = false;
//【A】处理覆盖更新的情况!
// 如果当前解析的系统 apk,并且他之前被覆盖更新过!
// 注意:ps 是上次安装的信息,updatedPkg 是由于覆盖安装更新前的信息!,pkg 则是本次扫描的 system app 的信息!
if (updatedPkg != null && (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
if (locationIsPrivileged(scanFile)) {
// 对于 /system/priv-app 目录下的 app,需要增加 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED 的 flag!
updatedPkg.pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
} else {
updatedPkg.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
}
// 上次更新后的应用路径和这次扫描解析的路径不一样,上次更新到了 data 分区,而这次扫描的是 system 分区,
// 就需要比较一下 versionCode 的大小,
if (ps != null && !ps.codePath.equals(scanFile)) {
if (DEBUG_INSTALL) Slog.d(TAG, "Path changing from " + ps.codePath);
// pkg 的 versioncode 小于等于上次更新后的 versioncode,说明 data 分区的 apk 仍然是最新的
// 那就用本次扫描解析的数据,来更新上次更新前的旧数据!
if (pkg.mVersionCode <= ps.versionCode) {
if (DEBUG_INSTALL) Slog.i(TAG, "Package " + ps.name + " at " + scanFile
+ " ignored: updated version " + ps.versionCode
+ " better than this " + pkg.mVersionCode);
// updatedPkg.codePath 不等于当前的扫描目录,说明该 system app 目录发生了变化!
// 而该 system apk 是被覆盖更新了,所以也需要更新 updatedPkg 的数据~
if (!updatedPkg.codePath.equals(scanFile)) {
Slog.w(PackageManagerService.TAG, "Code path for hidden system pkg "
+ ps.name + " changing from " + updatedPkg.codePathString
+ " to " + scanFile);
updatedPkg.codePath = scanFile;
updatedPkg.codePathString = scanFile.toString();
updatedPkg.resourcePath = scanFile;
updatedPkg.resourcePathString = scanFile.toString();
}
updatedPkg.pkg = pkg;
updatedPkg.versionCode = pkg.mVersionCode;
final int childCount = updatedPkg.childPackageNames != null
? updatedPkg.childPackageNames.size() : 0;
for (int i = 0; i < childCount; i++) {
String childPackageName = updatedPkg.childPackageNames.get(i);
PackageSetting updatedChildPkg = mSettings.getDisabledSystemPkgLPr(
childPackageName);
if (updatedChildPkg != null) {
updatedChildPkg.pkg = pkg;
updatedChildPkg.versionCode = pkg.mVersionCode;
}
}
throw new PackageManagerException(Log.WARN, "Package " + ps.name + " at "
+ scanFile + " ignored: updated version " + ps.versionCode
+ " better than this " + pkg.mVersionCode);
} else {
// pkg 的 versioncode 大于上次更新后的 versioncode,
// 说明当前在 system 分区的 apk 要比 data 分区的新,这说明 system app 又通过 OTA 升级更新了
// 那就要保留本次扫描解析的数据,删除上一次更新的数据!
synchronized (mPackages) {
// 从 PMS.mPackages 中删除上一次的扫描数据!
mPackages.remove(ps.name);
}
logCriticalInfo(Log.WARN, "Package " + ps.name + " at " + scanFile
+ " reverting from " + ps.codePathString
+ ": new version " + pkg.mVersionCode
+ " better than installed " + ps.versionCode);
// 创建一个安装参数对象,封装了上次安装的信息!!
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
// 移除 data 分区的 apk 和 相应的 dex 文件!
args.cleanUpResourcesLI();
}
synchronized (mPackages) {
//【3.2.1.4】将更新前的旧数据 PackageSetting ,从 mDisabledSysPackages 中移除,
// 并复用旧数据,创建一个新的PackageSetting,添加到 Setting 的 mPackage 中!
mSettings.enableSystemPackageLPw(ps.name);
}
updatedPkgBetter = true; // 设置 updatedPkgBetter 为 true!
}
}
}
if (updatedPkg != null) { // 对于被更新的系统 app 的 flag 进行设置!
policyFlags |= PackageParser.PARSE_IS_SYSTEM;
if ((updatedPkg.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
policyFlags |= PackageParser.PARSE_IS_PRIVILEGED;
}
}
collectCertificatesLI(ps, pkg, scanFile, policyFlags);
//【B】处理没有覆盖,但是 data 和 system 分区出现了相同的 apk 的情况!
// package 并没有发生覆盖更新,但之前 apk 是安装在 data 分区,而后来出现了相同包名的新 apk 安装在了 system 分区
//(比如系统 OTA 升级导致的 apk 分区改变,或者 root 后 push 一个相同 apk 到 system 分区然后重启)!
// 或者还有一种是之前安装在 data 分区,然后应用移动到了 system 分区!
// 那就要判断是否隐藏 system 分区的这个 apk 了!
boolean shouldHideSystemApp = false;
if (updatedPkg == null && ps != null
&& (policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
// 校验签名,如果不匹配的话,就冻结掉安装在 system 分区的 apk,并清除数据!
if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
!= PackageManager.SIGNATURE_MATCH) {
logCriticalInfo(Log.WARN, "Package " + ps.name + " appeared on system, but"
+ " signatures don't match existing userdata copy; removing");
// 创建一个 PackageFreezer 用来冻结指定的 package!
try (PackageFreezer freezer = freezePackage(pkg.packageName,
"scanPackageInternalLI")) {
deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null);
}
ps = null;
} else {
// 如果新添加的位于 system 分区的 apk 的版本号小于等于位于 data 分区的 apk;
// 那就要隐藏 system 分区的 apk;
if (pkg.mVersionCode <= ps.versionCode) {
shouldHideSystemApp = true; // 设置 shouldHideSystemApp 为 true!
logCriticalInfo(Log.INFO, "Package " + ps.name + " appeared at " + scanFile
+ " but new version " + pkg.mVersionCode + " better than installed "
+ ps.versionCode + "; hiding system");
} else {
// system 分区的应用版本更高,删除 data 分区的 apk,同时保留数据!
logCriticalInfo(Log.WARN, "Package " + ps.name + " at " + scanFile
+ " reverting from " + ps.codePathString + ": new version "
+ pkg.mVersionCode + " better than installed " + ps.versionCode);
// 创建一个安装参数!
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
// 删除 data 分区的 apk,并保留用户数据!
args.cleanUpResourcesLI();
}
}
}
}
// 系统 apk 不进入!
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
policyFlags |= PackageParser.PARSE_FORWARD_LOCK;
}
}
String resourcePath = null;
String baseResourcePath = null;
if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
if (ps != null && ps.resourcePathString != null) {
resourcePath = ps.resourcePathString;
baseResourcePath = ps.resourcePathString;
} else {
Slog.e(TAG, "Resource path not set for package " + pkg.packageName);
}
} else {
resourcePath = pkg.codePath;
baseResourcePath = pkg.baseCodePath;
}
// 设置 Package.ApplicationInfo 对象的 path 属性!
pkg.setApplicationVolumeUuid(pkg.volumeUuid);
pkg.setApplicationInfoCodePath(pkg.codePath);
pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath);
pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths);
pkg.setApplicationInfoResourcePath(resourcePath);
pkg.setApplicationInfoBaseResourcePath(baseResourcePath);
pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
//【3.2.1.7】接着调用 scanPackageLI,继续处理扫描数据!
PackageParser.Package scannedPkg = scanPackageLI(pkg, policyFlags, scanFlags
| SCAN_UPDATE_SIGNATURE, currentTime, user);
//【3.2.1.8】如果确认 data 分区的 apk 版本比 system 分区的版本高
// 就隐藏 system 分区的 app,让 data 分区的 apk 显示出来!
if (shouldHideSystemApp) {
synchronized (mPackages) {
mSettings.disableSystemPackageLPw(pkg.packageName, true);
}
}
return scannedPkg;
}
到这里,我们先来总结一下,对于一个系统 app 而言, app 升级有如下两种途径:
- 覆盖安装:这种方式 PMS 会动态修改 packages.xml 文件!
- OTA 升级方式:这种方式并不会动态修改 package.xml 文件!
下面我们来分开分析一下:
- 覆盖安装
- 对于系统 app,覆盖安装的话,新的 app 会安装到 data 分区,packages.xml 中相应数据会发生如下变化:
1
2
3
4
5
6
7
8<package name="com.android.pic" codePath="/data/app/com.android.pic-1" nativeLibraryPath="/data/app/com.android.pic-1/lib"
primaryCpuAbi="arm64-v8a" publicFlags="944258757" privateFlags="0" ft="15c38695c40" it="15baf6278f0"
ut="15c38695e98" version="3002" sharedUserId="1000" installer="com.android.packageinstaller" isOrphaned="true">
</package>
<updated-package name="com.android.pic" codePath="/system/app/pic"
ft="15baf6278f0" it="15baf6278f0" ut="15baf6278f0" version="3002"
nativeLibraryPath="/system/app/pic/lib" primaryCpuAbi="arm64-v8a" sharedUserId="1000" />
- 对于系统 app,覆盖安装的话,新的 app 会安装到 data 分区,packages.xml 中相应数据会发生如下变化:
可以看到,package 的 codePath、nativeLibraryPath 都发生了变化,根据上面的解析过程,data 分区的覆盖安装的 apk 将被保存到 mPackages 中,system 分区原来的旧 apk 将被保存到 mDisablePackage 中!
- OTA 升级方式
- 这种方式是通过进入 Recovery 升级(或者是 A/B 升级方式),通过 patch 和文件覆盖方式来升级,这种方式不会即时更改 Packages.xml 文件,真正的修改是在重启后的 PMS 中去做的!
3.2.1.1 Settings.peekPackageLPr
1 | PackageSetting peekPackageLPr(String name) { |
该方法用于获得 packageName 对应的 PackageSetting 对象!
3.2.1.2 Settings.getDisabledSystemPkgLPr
1 | public PackageSetting getDisabledSystemPkgLPr(String name) { |
我们知道 mDisabledSysPackages 中的数据来自 updated-package 标签!
3.2.1.3 Settings.removeDisabledSystemPackageLPw
1 | void removeDisabledSystemPackageLPw(String name) { |
3.2.1.4 Settings.enableSystemPackageLPw
这里用于恢复一个 system pacakge!
1 | PackageSetting enableSystemPackageLPw(String name) { |
方法的流程很简单,不多说了!
3.2.1.6 PMS.deletePackageLIF
对于之前 apk 是安装在 data 分区,而后来出现了相同包名的新 apk 安装在了 system 分区这种情况,需要校验签名,如果不匹配的话,就要删掉 data 分区的 apk!
首先创建了一个 PackageFreezer 对象,用来冻结这个应用!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
28public PackageFreezer(String packageName, int userId, String killReason) {
synchronized (mPackages) {
// 添加到 mFrozenPackages 集合中!
mPackageName = packageName;
mWeFroze = mFrozenPackages.add(mPackageName);
final PackageSetting ps = mSettings.mPackages.get(mPackageName);
if (ps != null) {
// 杀掉应用的进程
killApplication(ps.name, ps.appId, userId, killReason);
}
// 对子包进行相同的操作!
final PackageParser.Package p = mPackages.get(packageName);
if (p != null && p.childPackages != null) {
final int N = p.childPackages.size();
mChildren = new PackageFreezer[N];
for (int i = 0; i < N; i++) {
mChildren[i] = new PackageFreezer(p.childPackages.get(i).packageName,
userId, killReason);
}
} else {
mChildren = null;
}
}
mCloseGuard.open("close");
}
接着,调用 deletePackageLIF 方法来处理这个 package,传入参数:
- String packageName:传入 pkg.packageName;
- UserHandle user:传入 null;
- boolean deleteCodeAndResources:传入 true;
- int[] allUserHandles:传入 null;
- int flags:传入 0;
- PackageRemovedInfo outInfo:传入 null;
- boolean writeSettings:传入 false;
- PackageParser.Package replacingPackage:传入 null;
1 | private boolean deletePackageLIF(String packageName, UserHandle user, |
关于 apk 删除的逻辑,我们在另开一篇讲解,这个的逻辑是会删掉之前已经安装的 data 分区的 apk 的!
继续看:
3.2.1.7 PMS.scanPackageLI
接下来,进一步的扫描:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21private PackageParser.Package scanPackageLI(PackageParser.Package pkg, final int policyFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
boolean success = false;
try {
//【3.2.1.7.1】继续调用 scanPackageDirtyLI 处理扫描数据!
final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags,
currentTime, user);
success = true;
return res;
} finally {
if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
// DELETE_DATA_ON_FAILURES is only used by frozen paths
// 失败了就清楚掉数据!
destroyAppDataLIF(pkg, UserHandle.USER_ALL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
destroyAppProfilesLIF(pkg, UserHandle.USER_ALL);
}
}
}
下面,我们继续看 scanPackageDirtyLI 方法中的逻辑!
3.2.1.7.1 *PMS.scanPackageDirtyLI
最终调用 scanPackageDirtyLI 方法处理扫描得到的数据:
因为我们本次扫描的是 system app,所以 PackageParser.Package pkg 分装了扫描的结果信息!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
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946private 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);
if (pkg.applicationInfo.getCodePath() == null ||
pkg.applicationInfo.getResourcePath() == null) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Code and resource paths haven't been set correctly");
}
//【1】处理系统 apk 标志位;
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
// 对于系统 app,增加 ApplicationInfo.FLAG_SYSTEM 的 flags,表示是系统 apk!
//【1.1】注意系统和非系统的区别是,apk 所在的目录!
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
// 处理 Direct Boot Mode 属性,设备启动后进入的一个新模式,直到用户解锁(unlock)设备此阶段结束!
if (pkg.applicationInfo.isDirectBootAware()) {
for (PackageParser.Service s : pkg.services) {
s.info.encryptionAware = s.info.directBootAware = true;
}
for (PackageParser.Provider p : pkg.providers) {
p.info.encryptionAware = p.info.directBootAware = true;
}
for (PackageParser.Activity a : pkg.activities) {
a.info.encryptionAware = a.info.directBootAware = true;
}
for (PackageParser.Activity r : pkg.receivers) {
r.info.encryptionAware = r.info.directBootAware = true;
}
}
} else {
pkg.coreApp = false;
pkg.applicationInfo.privateFlags &=
~ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
pkg.applicationInfo.privateFlags &=
~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
}
pkg.mTrustedOverlay = (policyFlags&PackageParser.PARSE_TRUSTED_OVERLAY) != 0;
//【2】设置 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED 标记位,说明这个 apk 是特权 apk!
if ((policyFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
}
if ((policyFlags & PackageParser.PARSE_ENFORCE_CODE) != 0) {
enforceCodePolicy(pkg);
}
if (mCustomResolverComponentName != null &&
mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
setUpCustomResolverActivity(pkg);
}
//【3】处理包名为 "android" 的 apk,也就是 framework-res.apk,属于系统平台包!
if (pkg.packageName.equals("android")) {
synchronized (mPackages) {
if (mAndroidApplication != null) {
Slog.w(TAG, "*************************************************");
Slog.w(TAG, "Core android package being redefined. Skipping.");
Slog.w(TAG, " file=" + scanFile);
Slog.w(TAG, "*************************************************");
throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
"Core android package being redefined. Skipping.");
}
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) { // 建立 ResolverActivity 的内存对象。
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);
}
}
}
}
if (DEBUG_PACKAGE_SCANNING) {
if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
Log.d(TAG, "Scanning package " + pkg.packageName);
}
synchronized (mPackages) {
//【4】如果 PMS.mPackages 已经包含当前的 Package,说明这个包已经被扫描过了,抛异常,不继续处理!
if (mPackages.containsKey(pkg.packageName)
|| mSharedLibraries.containsKey(pkg.packageName)) {
throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
"Application package " + pkg.packageName
+ " already installed. Skipping duplicate.");
}
//【5】系统 apk 不进入这个分支,SCAN_REQUIRE_KNOWN 只有在扫描 data 分区是才会被设置!!
if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) {
//【5.1】扫描 data 分区时,会判断 mExpectingBetter 中是否包含该 package!
if (mExpectingBetter.containsKey(pkg.packageName)) {
logCriticalInfo(Log.WARN,
"Relax SCAN_REQUIRE_KNOWN requirement for package " + pkg.packageName);
} else {
PackageSetting known = mSettings.peekPackageLPr(pkg.packageName);
if (known != null) {
if (DEBUG_PACKAGE_SCANNING) {
Log.d(TAG, "Examining " + pkg.codePath
+ " and requiring known paths " + known.codePathString
+ " & " + known.resourcePathString);
}
if (!pkg.applicationInfo.getCodePath().equals(known.codePathString)
|| !pkg.applicationInfo.getResourcePath().equals(
known.resourcePathString)) {
throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
"Application package " + pkg.packageName
+ " found at " + pkg.applicationInfo.getCodePath()
+ " but expected at " + known.codePathString
+ "; ignoring.");
}
}
}
}
}
//【6】获得扫描到的 apk 和资源的路径,下面会用到!
File destCodeFile = new File(pkg.applicationInfo.getCodePath());
File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
SharedUserSetting suid = null;
PackageSetting pkgSetting = null;
//【7】系统 apk 才能有 mOriginalPackages,mRealPackage 和 mAdoptPermissions!
if (!isSystemApp(pkg)) {
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;
synchronized (mPackages) {
//【8】当前的系统(三方) package 是共享 uid 的,要判断其对应的共享 uid 是否存在,
// 不存在就抛出异常!
if (pkg.mSharedUserId != null) {
suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, 0, true);
if (suid == null) {
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
"Creating application package " + pkg.packageName
+ " for shared user failed");
}
if (DEBUG_PACKAGE_SCANNING) {
if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
+ "): packages=" + suid.packages);
}
}
//【9】对于系统 package,如果有源包,那就要尝试将 package 的名字改为源包的名字!
// 需要找到一个合适的源包,用来改名!
PackageSetting origPackage = null;
String realName = null
if (pkg.mOriginalPackages != null) {
final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
//【9.1】如果当前 package 被重命名过,并且有源包的名字是重命名前的名字,就将 package 的名字改为以前的!
if (pkg.mOriginalPackages.contains(renamed)) {
realName = pkg.mRealPackage;
if (!pkg.packageName.equals(renamed)) {
pkg.setPackageName(renamed);
}
} else {
for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
if ((origPackage = mSettings.peekPackageLPr(
pkg.mOriginalPackages.get(i))) != null) {
//【9.2】对当前 package 和其源包进行校验
// 如果源包是非系统 package,不是同一分区,无法重命名为源包名,返回 false;
// 或者源包是系统 package,但是 PMS.mPackage 中仍然有其扫描数据,源包仍然存在,返回 false;
if (!verifyPackageUpdateLPr(origPackage, pkg)) {
origPackage = null;
continue;
} else if (origPackage.sharedUser != null) {
//【9.3】源包是系统 package,并且共享用户 uid;
// 如果当前的 package 和源包的共享 uid 不匹配,也会返回 false!
// 表示无法迁移数据;
if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Slog.w(TAG, "Unable to migrate data from " + origPackage.name
+ " to " + pkg.packageName + ": old uid "
+ origPackage.sharedUser.name
+ " differs from " + pkg.mSharedUserId);
origPackage = null;
continue;
}
} else {
// 可以看到,如果找到用于重命名的源包,origPackage 不会为 null!
if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
+ pkg.packageName + " to old name " + origPackage.name);
}
break;
}
}
}
}
// mTransferedPackages 用于保存那些自身数据已经被转移到其他 package 的 package!
if (mTransferedPackages.contains(pkg.packageName)) {
Slog.w(TAG, "Package " + pkg.packageName
+ " was transferred to another, but its .apk remains");
}
// See comments in nonMutatedPs declaration
if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
PackageSetting foundPs = mSettings.peekPackageLPr(pkg.packageName);
if (foundPs != null) {
nonMutatedPs = new PackageSetting(foundPs);
}
}
//【3.2.1.7.1.1】获得当前扫描的这个 package 对应的 packageSetting 对象,如果已经存在就直接返回,
// 不存在就创建!如果 origPackage 不为 null,创建新的需要重命名为源包的名字!
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) {
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
"Creating application package " + pkg.packageName + " failed");
}
//【11】对于系统 package,如果 origPackage 不为 null,改名为源包的名字!
if (pkgSetting.origPackage != null) {
pkg.setPackageName(origPackage.name);
String msg = "New package " + pkgSetting.realName
+ " renamed to replace old package " + pkgSetting.name;
reportSettingsProblem(Log.WARN, msg);
if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
// 如果没有设置 SCAN_CHECK_ONLY,并且源包是存在的,就将源包添加到 mTransferedPackages 中!
mTransferedPackages.add(origPackage.name);
}
// 清空 originPackage 属性!
pkgSetting.origPackage = null;
}
if ((scanFlags & SCAN_CHECK_ONLY) == 0 && realName != null) {
mTransferedPackages.add(pkg.packageName);
}
//【12】如果当前的系统 apk 被覆盖更新过,就添加 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP 标签!
if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
updateSharedLibrariesLPw(pkg, null);
}
if (mFoundPolicyFile) {
//【13】给当前的 Package 分配一个标签,用于 seLinux!
SELinuxMMAC.assignSeinfoValue(pkg);
}
pkg.applicationInfo.uid = pkgSetting.appId;
pkg.mExtras = pkgSetting;
//【13】处理 keySet 更新和签名校验!
if (shouldCheckUpgradeKeySetLP(pkgSetting, scanFlags)) {
if (checkUpgradeKeySetLP(pkgSetting, pkg)) {
// 签名正确,更新本地的签名信息!
pkgSetting.signatures.mSignatures = pkg.mSignatures;
} else {
// 签名异常处理
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
"Package " + pkg.packageName + " upgrade keys do not match the "
+ "previously installed version");
} else {
pkgSetting.signatures.mSignatures = pkg.mSignatures;
String msg = "System package " + pkg.packageName
+ " signature changed; retaining data.";
reportSettingsProblem(Log.WARN, msg);
}
}
} else {
// 如果不检查 KetSet 更新的话,就直接校验签名!
try {
verifySignaturesLP(pkgSetting, pkg);
pkgSetting.signatures.mSignatures = pkg.mSignatures;
} catch (PackageManagerException e) {
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
throw e;
}
// 如果签名校验出现问题,这里会先恢复成本次解析的签名!
pkgSetting.signatures.mSignatures = pkg.mSignatures;
// 但是如果是 sharedUser 的情况,就会报错!
if (pkgSetting.sharedUser != null) {
if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
throw new PackageManagerException(
INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
"Signature mismatch for shared user: "
+ pkgSetting.sharedUser);
}
}
String msg = "System package " + pkg.packageName
+ " signature changed; retaining data.";
reportSettingsProblem(Log.WARN, msg);
}
}
//【14】安装的时候才会进入这个分支,这里不看!
// 判断这个 package 使用的 content providers 是否和已经存在 package 冲突!
if ((scanFlags & SCAN_NEW_INSTALL) != 0) {
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() : "?");
throw new PackageManagerException(
INSTALL_FAILED_CONFLICTING_PROVIDER,
"Can't install because provider name " + names[j]
+ " (in package " + pkg.applicationInfo.packageName
+ ") is already used by " + otherPackageName);
}
}
}
}
}
//【15】同样的,只有系统 apk 才能进入该分支,用于权限继承!
if ((scanFlags & SCAN_CHECK_ONLY) == 0 && pkg.mAdoptPermissions != null) {
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) {
//【15.1】校验要被继承权限的 package 一是否存在,二是否是系统应用!
// 条件不满足,无法权限继承!
if (verifyPackageUpdateLPr(orig, pkg)) {
Slog.i(TAG, "Adopting permissions from " + origName + " to "
+ pkg.packageName);
mSettings.transferPermissionsLPw(origName, pkg.packageName);
}
}
}
}
}
final String pkgName = pkg.packageName;
// 从 base.apk 和其 split.apk(如果有)中选择修改时间最晚的作为扫描时间!
final long scanFileTime = getLastModifiedTime(pkg, scanFile);
final boolean forceDex = (scanFlags & SCAN_FORCE_DEX) != 0; // 没用到,应该是废弃代码!
//【16】设置 pacakge 对应的进程名,如果 processName 为 null,默认进程名为包名!
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);
//【17】下面是设置本地库和系统平台相关的属性!!
if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
derivePackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */);
if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() &&
pkg.applicationInfo.primaryCpuAbi == null) {
setBundledAppAbisAndRoots(pkg, pkgSetting);
setNativeLibraryPaths(pkg);
}
} else {
if ((scanFlags & SCAN_MOVE) != 0) {
pkg.applicationInfo.primaryCpuAbi = pkgSetting.primaryCpuAbiString;
pkg.applicationInfo.secondaryCpuAbi = pkgSetting.secondaryCpuAbiString;
}
setNativeLibraryPaths(pkg);
}
if (mPlatformPackage == pkg) {
pkg.applicationInfo.primaryCpuAbi = VMRuntime.getRuntime().is64Bit() ?
Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
}
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;
pkg.cpuAbiOverride = cpuAbiOverride;
if (DEBUG_ABI_SELECTION) {
Slog.d(TAG, "Resolved nativeLibraryRoot for " + pkg.applicationInfo.packageName
+ " to root=" + pkg.applicationInfo.nativeLibraryRootDir + ", isa="
+ pkg.applicationInfo.nativeLibraryRootRequiresIsa);
}
pkgSetting.legacyNativeLibraryPathString = pkg.applicationInfo.nativeLibraryRootDir;
if (DEBUG_ABI_SELECTION) {
Log.d(TAG, "Abis for package[" + pkg.packageName + "] are" +
" primary=" + pkg.applicationInfo.primaryCpuAbi +
" secondary=" + pkg.applicationInfo.secondaryCpuAbi);
}
if ((scanFlags & SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
pkg, true /* boot complete */);
}
if (mFactoryTest && pkg.requestedPermissions.contains(
android.Manifest.permission.FACTORY_TEST)) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
}
// 如果是系统 package,设置 isOrphaned 的属性为 true!
if (isSystemApp(pkg)) {
pkgSetting.isOrphaned = true;
}
ArrayList<PackageParser.Package> clientLibPkgs = null;
if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
if (nonMutatedPs != null) {
synchronized (mPackages) {
mSettings.mPackages.put(nonMutatedPs.name, nonMutatedPs);
}
}
return pkg;
}
//【18】处理特权 apk 的子包,只有特权 apk 才能添加子包;
// 特权 apk 包括两部分:
// 1、特定 uid 的 app
// 2、framework-res.apk 和 system/priv-app 目录下的 apk!
if (pkg.childPackages != null && !pkg.childPackages.isEmpty()) {
if ((policyFlags & PARSE_IS_PRIVILEGED) == 0) {
throw new PackageManagerException("Only privileged apps and updated "
+ "privileged apps can add child packages. Ignoring package "
+ pkg.packageName);
}
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)) {
throw new PackageManagerException("Cannot override a child package of "
+ "another disabled system app. Ignoring package " + pkg.packageName);
}
}
}
synchronized (mPackages) {
//【19】如果是系统 package,并且他之前更新过,就要尝试对共享库 lib 进行更新!
// 只有系统 package 才能添加共享 lib
if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
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()) {
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) {
// 如果不是开机扫描,我们需要更新下该应用的共享库,对于开机扫描的情况,我们会在扫描完成后自动更新
clientLibPkgs = updateAllSharedLibrariesLPw(pkg);
}
}
}
}
//【20】处理和冻结相关的逻辑
if ((scanFlags & SCAN_BOOTING) != 0) {
// 如果是开机扫描,不需要冻结,因为没有应用在此时可以运行!
} else if ((scanFlags & SCAN_DONT_KILL_APP) != 0) {
// 如果扫描过程中不允许 kill app,那就不会冻结!
} else if ((scanFlags & SCAN_IGNORE_FROZEN) != 0) {
// 如果扫描过程中显式指定忽略冻结,那就不会冻结!
} else {
// 其他情况,我们会默认冻结该应用,防止其启动!
checkPackageFrozen(pkgName);
}
//【21】杀掉所以依赖于库文件的应用,因为库发生了更新!
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");
}
}
KeySetManagerService ksms = mSettings.mKeySetManagerService; // 校验 keyset 的真实性
ksms.assertScannedPackageValid(pkg);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings"); // 记录 trace 事件!
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);
}
//【3.2.1.7.1.2 important】将新创建或者更新后的 PackageSetting 重新添加到 mSettings 中!
mSettings.insertPackageSettingLPw(pkgSetting, pkg);
//【important】将本次扫描的 Package 添加到 PMS.mPackages 中去!
mPackages.put(pkg.applicationInfo.packageName, pkg);
//【22】将当前的 package 从 mSettings.mPackagesToBeCleaned 中移除,防止被清除!
final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
while (iter.hasNext()) {
PackageCleanItem item = iter.next();
if (pkgName.equals(item.packageName)) {
iter.remove();
}
}
//【23】处理 package 的第一次安装时间和最近更新时间!
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) {
pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
} else if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
if (scanFileTime != pkgSetting.timeStamp) {
pkgSetting.lastUpdateTime = scanFileTime;
}
}
ksms.addScannedPackageLPw(pkg); // 将 package 的 KeySets 添加到 KeySetManagerService 中!
//【24】处理四大组件!
//【24.1】处理该 Package 中 的 Provider 信息,添加到 PMS.mProviders 中!
int N = pkg.providers.size();
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); // 添加到 PMS.mProviders 中!
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];
}
if (DEBUG_PACKAGE_SCANNING) {
if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
Log.d(TAG, "Registered content provider: " + names[j]
+ ", className = " + p.info.name + ", isSyncable = "
+ p.info.isSyncable);
}
} 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);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
}
//【24.2】处理该 Package 中的 Service 信息,添加到 PMS.mService 中!
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); // 添加到 PMS.mServices 中!
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(s.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
}
//【24.3】处理该 Package 中的 BroadcastReceiver 信息,添加到 PMS.mReceivers 中。
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"); // 添加到 PMS.mReceivers 中!
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
}
//【24.4】处理该 Package 中的 activity 信息,添加到 PMS.mActivities 中!
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"); // 添加到 PMS.mActivities 中!
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
}
//【24.5】处理该 Package 中的 PermissionGroups 信息,添加到 PMS.mPermissionGroups 中!
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);
final String curPackageName = cur == null ? null : cur.info.packageName;
//【5.1】如果 isPackageUpdate 为 true,说明要更新权限组的信息!
// 如果 cur 为 null,说明是新添加的权限组信息!
final boolean isPackageUpdate = pg.info.packageName.equals(curPackageName);
if (cur == null || isPackageUpdate) {
mPermissionGroups.put(pg.info.name, pg); // 添加到 PMS.mPermissionGroups 中!
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
if (isPackageUpdate) {
r.append("UPD:");
}
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);
}
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
}
//【24.6】处理该 Package 中的定义 Permission 和 Permission-tree 信息!
N = pkg.permissions.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Permission p = pkg.permissions.get(i);
// 默认取消掉 PermissionInfo.FLAG_INSTALLED 标志位!
p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
//【6.1】设置权限所属的 group,前提是只有 Android5.1 以后才支持 Permission Groups!
if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
p.group = mPermissionGroups.get(p.info.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);
}
}
//【6.2】从 Settings 中获得权限管理集合,如果该权限是一个 Permission-tree,
// 那就返回 mSettings.mPermissionTrees;否则,返回 mSettings.mPermissions!
ArrayMap<String, BasePermission> permissionMap =
p.tree ? mSettings.mPermissionTrees
: mSettings.mPermissions;
//【6.3】尝试获得上次安装时该权限对应的 BasePermission 对象!
BasePermission bp = permissionMap.get(p.info.name);
//【6.4】允许系统应用来重新定义非系统权限!
// 如果上次安装时的 BasePermission 不为 null,但是当前解析的 package 不是上次安装时该权限的定义者!
if (bp != null && !Objects.equals(bp.sourcePackage, p.info.packageName)) {
//【6.4.1】判断上一次安装时,定义该权限的 package 是否是系统应用!
// 如果是 currentOwnerIsSystem 为 true!
final boolean currentOwnerIsSystem = (bp.perm != null
&& isSystemApp(bp.perm.owner));
// 如果当前解析的定义了该权限的 package 是系统 app,那么进入这里!
if (isSystemApp(p.owner)) {
// 如果上次安装时,该权限是一个 BasePermission.TYPE_BUILTIN 系统权限,且 bp.perm 为 null,
// 即:拥有者未知,那么这里我们将这个 system package 分配给这个权限!
if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) {
bp.packageSetting = pkgSetting;
bp.perm = p;
bp.uid = pkg.applicationInfo.uid;
bp.sourcePackage = p.info.packageName;
p.info.flags |= PermissionInfo.FLAG_INSTALLED;
// 判断上一次安装时,定义该权限的 package 不是系统应用,而定义相同权限的
// 本次解析的 package 是系统应用,那么该权限会被系统应用重新定义!
} 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!
bp = null;
}
}
}
// 因为 bp 为 null,所谓我们会使用系统应用重新定义权限,如果是 permission-tree,会被添加到
// mSettings.mPermissionTrees 中!
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);
}
// 如果上次安装时的权限的定义者,就是本次解析的 package,设置 protectionLevel!
if (bp.perm == p) {
bp.protectionLevel = p.info.protectionLevel;
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permissions: " + r);
}
N = pkg.instrumentation.size();
r = null;
for (i=0; i<N; i++) {
... ... ... ...// 这里省略掉,暂时不看!
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r);
}
//【25】处理该 Package 中的 protectedBroadcasts 信息!
if (pkg.protectedBroadcasts != null) {
N = pkg.protectedBroadcasts.size();
for (i=0; i<N; i++) {
mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
}
}
//【27】更新 PackageSettings 中的时间戳!
pkgSetting.setTimeStamp(scanFileTime);
// 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;
}
到这里,对于扫描的 package 的数据就处理完了!
3.2.1.7.1.1 Settings.getPackageLPw
上面又再次调用了 getPackageLPw 方法,注意根据参数传递:
- boolean add:传入的值为 false!
- boolean allowInstall:传入的值为 true;
该方法传入的参数的是本次扫描解析获得的 apk 的数据!
1 | // 最终进入这个方法! |
3.2.1.7.1.2 Settings.insertPackageSettingLPw
该方法会将 PackageSetting 保存到 mUserIds 或 mOtherIds 中去,同时用本次扫描的的 Package 更新 PackageSetting!
1 | void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) { |
这里就不多说了!
3.2.1.7.1.3 ActivityIntentResolver.addActivity - 添加 activity
这里先不关注~~
3.2.1.8 Settings.disableSystemPackageLPw
当需要隐藏掉 system app 的时候,会调用 disableSystemPackageLPw 方法:
参数传递:
- boolean replaced:true!
1 | boolean disableSystemPackageLPw(String name, boolean replaced) { |
这里面会设置到 pkgFlags 和 pkgPrivateFlags 的设置:1
2
3
4
5
6
7
8
9
10
11
12void setFlags(int pkgFlags) {
this.pkgFlags = pkgFlags
& (ApplicationInfo.FLAG_SYSTEM
| ApplicationInfo.FLAG_EXTERNAL_STORAGE);
}
void setPrivateFlags(int pkgPrivateFlags) {
this.pkgPrivateFlags = pkgPrivateFlags
& (ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
| ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK
| ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
}
到这里 system 分区的扫描流程就结束了!
3.2.1.8.1 Settings.replacePackageLPw
1 | private void replacePackageLPw(String name, PackageSetting newp) { |
更新 mPackages 中的数据!
3.2.1.8.1.1 Settings.replaceUserIdLPw
1 | private void replaceUserIdLPw(int uid, Object obj) { |
更新 mOtherUserIds 和 mUserIds 中的数据!
3.3 扫描总结
下面我们来总结下扫描过程:
3.3.1 扫描过程总结
接下来,用一张图来总结一下,扫描的过程:
流程很清晰了,不多说。
3.3.2 数据关系总结
下面我们来看看解析获得的数据之间的关系:
这个图展示了解析得到的一个 Package 对象在内存中的结果。
- 组件的基类是 Component,AndroidManifest.xml 中定义的组件 activity,service,provider,permission等,都继承了 Component;
- activity,service 这样的组件,都可以配置
属性,在 pms 中体现在 IntentInfo 这个数据结构中,从上图可以看到,每一种组件所依赖的 intentInfo 不同,Component 和 IntentInfo 之间的依赖关系采用了桥接模式,通过泛型实现!
4 系统目录扫描 - 收尾阶段
接下来,是收集可能被删掉的系统应用包!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//【×】用于收集可能已经被删掉的系统应用包!
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
if (!mOnlyCore) {
// 遍历上次安装的所有的 package!
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
//【×】如果是非系统应用,跳过,如果是被覆盖安装!
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
continue;
}
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
//【4.1】如果系统应用包不仅被扫描过(在mPackages中),并且在不可用列表中!
// 说明一定是通过覆盖安装的,移除之前扫描的结果,保证之前用户安装的应用能够被扫描!
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
logCriticalInfo(Log.WARN, "Expecting better updated system app for "
+ ps.name + "; removing system app. Last known codePath="
+ ps.codePathString + ", installStatus=" + ps.installStatus
+ ", versionCode=" + ps.versionCode + "; scanned versionCode="
+ scannedPkg.mVersionCode);
//【4.2】将之前的扫描结果移除!
removePackageLI(scannedPkg, true);
// 将这包添加到 mExpectingBetter 列表中!
mExpectingBetter.put(ps.name, ps.codePath);
}
// 跳出循环,确保不会被删掉!
continue;
}
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
// 如果系统应用包没有被扫描,并且他也不在不可用的列表中,说明其没有被更新过,
// 可能被删除了,也可能被移动到了 data 分区,那就清楚其前面的数据!
// 如果移动到了 data 分区,那就在扫描 data 的过程中处理!
psit.remove();
logCriticalInfo(Log.WARN, "System package " + ps.name
+ " no longer exists; it's data will be wiped");
} else {
// 如果系统应用包没有被扫描,却在不可用的列表中,说明其被更新过了,但是 apk 被删除了
// 就将他加入到 possiblyDeletedUpdatedSystemApps 集合中!
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
}
}
//【×】清理所有安装不完全的应用包!
ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
for (int i = 0; i < deletePkgsList.size(); i++) {
final String packageName = deletePkgsList.get(i).name;
logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName);
synchronized (mPackages) {
mSettings.removePackageLPw(packageName);
}
}
// 移除临时文件
deleteTempPackageFiles();
// 移除没有和应用程序包相关联的共享用户 id!
mSettings.pruneSharedUsersLPw();
对于已经被扫描到的系统 app,如果发现他存在于被更新过的列表中,说明这个系统 apk 在 data 分区有更新的版本了,那就需要把之前扫描的清楚掉,这样我们要确保在扫描 data 分区时,data 分区的 app 能够显示出来!!
4.1 PMS.isDisabledSystemPackageLPr
1 | boolean isDisabledSystemPackageLPr(String name) { |
4.2 PMS.removePackageLI
removePackageLI 会移除指定 pacakge 的扫描结果!
1 | private void removePackageLI(PackageParser.Package pkg, boolean chatty) { |
5 总结
我们用一张流程图来总结一下系统 apk 的扫描解析处理过程:
- 需要隐藏的系统 apk 都会被添加到 mExpectingBetter 列表中:
1、系统 apk 被覆盖安装过,且 system 分区的 versionCode 的是不高于 data 分区的;
2、之前已经有一相同包名的 apk 安装在 data 分区中了,这次有同样的包名的 app 出现在了 system 分区, versionCode 不高于 data 分区的;