0%

PackageManagerService启动篇整理2

1. PackageManagerService的启动过程

本篇主要介绍PKMS扫描包的流程


1.1. BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 阶段

1.1.1. 开始扫描apk

先扫描这两个目录的

1
2
/vendor/overlay
/system/framework

再扫描这几个目录下面的:

1
2
3
4
/system/priv-app
/system/app
/vendor/app
/oem/app

最后扫描这几个目录下面的:

1
2
3
4
/data/app
/data/app-private
/system/preloadapp
/system/app-ephemeral

先看一下扫描相关的代码流程

1.1.1.1. 扫描流程图

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
@startuml
PackageManagerService -> PackageManagerService:scanDirTracedLI
PackageManagerService -> PackageManagerService:scanDirLI
PackageManagerService -> PackageManagerService:scanPackageTracedLI
PackageManagerService ->PackageManagerService:scanPackageLI(scanFile, parseFlags, scanFlags, currentTime, user)
PackageManagerService ->PackageParser: parsePackage
opt packageFile.isDirectory
PackageParser -> PackageParser: parseClusterPackage
PackageParser -> PackageParser: parseClusterPackageLite
PackageParser -> PackageParser: parseApkLite
PackageParser -> AssetManager: setConfiguration
AssetManager -> AssetManager: native_setConfiguration
PackageParser -> AssetManager: addAssetPath
AssetManager -> AssetManager: addAssetPathNative
PackageParser -> AssetManager: parser = openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
AssetManager -> AssetManager:openXmlBlockAsset
PackageParser ->PackageParser: collectCertificates
PackageParser -> PackageParser: loadApkIntoAssetManager
PackageParser -> PackageParser: parseBaseApk
PackageParser ->PackageParser: parsePackageSplitNames
PackageParser -> PackageParser: parseBaseApkCommon
PackageParser -> PackageParser: parseBaseApplication
PackageParser -> PackageParser: parseActivity
PackageParser -> PackageParser: parseService
PackageParser -> PackageParser: parseProvider
PackageParser -> PackageParser: end [parseBaseApplication]
PackageParser -> PackageParser: end [parseBaseApkCommon]
PackageParser -> PackageParser: end [parseBaseApk]
PackageParser -> PackageParser: parseSplitApk
else packageFile is file
PackageParser ->PackageParser:parseMonolithicPackage
PackageParser ->PackageParser:parseMonolithicPackageLite
PackageParser ->PackageParser:parseApkLite
PackageParser ->PackageParser:parseBaseApk
end
PackageManagerService -> PackageManagerService:scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user)
PackageManagerService -> PackageManagerService: scanPackageInternalLI
PackageManagerService ->PackageManagerService: createInstallArgsForExisting
PackageManagerService -> AsecInstallArgs: new AsecInstallArgs(codePath, instructionSets ....)
PackageManagerService -> FileInstallArgs: new FileInstallArgs(codePath, resourcePath, instructionSets);
PackageManagerService -> PackageManagerService: collectCertificatesLI(ps, pkg, scanFile, policyFlags);
PackageManagerService ->> PackageManagerService: compareSignatures

PackageManagerService -> PackageManagerService: scanPackageLI(pkg, policyFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user)

PackageManagerService -> PackageManagerService: scanPackageDirtyLI(pkg, policyFlags, scanFlags, currentTime, user)

PackageManagerService -> NativeLibraryHelper:replaceUnityLibraries(res.packageName, res.applicationInfo.nativeLibraryDir, )

opt if scanPackageDirtyLI not success

PackageManagerService -> PackageManagerService:destroyAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE)

PackageManagerService ->> PackageManagerService: destroyAppProfilesLIF(pkg, UserHandle.USER_ALL)

else

end

PackageManagerService -> PackageManagerService: end [createInstallArgsForExisting]
PackageManagerService -> PackageManagerService: end [scanPackageInternalLI]
PackageManagerService -> PackageManagerService: end [scanPackageLI]
PackageManagerService ->> PackageManagerService: end [scanPackageLI]
@enduml

1.1.1.2. 扫描流程简要分析

scanDirTracedLI函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 扫描framework下的apk, 如 framework-res.apk
scanDirTracedLI(frameworkDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
// framework-res.apk中没有代码,因此不需要dex优化
scanFlags | SCAN_NO_DEX, 0);

private void scanDirTracedLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir");
try {
scanDirLI(dir, parseFlags, scanFlags, currentTime);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}

比较重要的参数

  • parseFlags
1
2
3
4
5
6
7
8
9
10
11
12
13
public final static int PARSE_IS_SYSTEM = 1<<0;
public final static int PARSE_CHATTY = 1<<1;
public final static int PARSE_MUST_BE_APK = 1<<2;
public final static int PARSE_IGNORE_PROCESSES = 1<<3;
public final static int PARSE_FORWARD_LOCK = 1<<4;
public final static int PARSE_EXTERNAL_STORAGE = 1<<5;
public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
public final static int PARSE_IS_PRIVILEGED = 1<<7;
public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
public final static int PARSE_ENFORCE_CODE = 1<<10;
public final static int PARSE_IS_EPHEMERAL = 1<<11;
public final static int PARSE_FORCE_SDK = 1<<12;
解析参数 关联到包相关的flag (ApplicationInfo) getter方法
PARSE_IS_SYSTEM FLAG_SYSTEM isSystemApp
PARSE_IS_PRIVILEGED PRIVATE_FLAG_PRIVILEGED isPrivilegedApp
PARSE_FORWARD_LOCK PRIVATE_FLAG_FORWARD_LOCK isForwardLocked
PARSE_IS_SYSTEM_DIR 没有指定 没有指定
PARSE_EXTERNAL_STORAGE FLAG_EXTERNAL_STORAGE isExternal
PARSE_IS_EPHEMERAL PRIVATE_FLAG_EPHEMERAL isEphemeral/isEphemeralApp
PARSE_MUST_BE_APK 没有指定(必须后缀名为.apk) 没有指定
  • scanFlags
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
static final int SCAN_NO_DEX = 1<<1;     // 指定此标志,不执行dex优化
static final int SCAN_FORCE_DEX = 1<<2; // 强制做dex优化
static final int SCAN_UPDATE_SIGNATURE = 1<<3; // 更新签名,一般扫描或安装时都会携带该参数
static final int SCAN_NEW_INSTALL = 1<<4; // 新安装apk时,携带该参数,如调用installPackage时
static final int SCAN_NO_PATHS = 1<<5;
static final int SCAN_UPDATE_TIME = 1<<6; //在apk升级时往往会指定该参数.指定后,会更新应用的lastUpdateTime
static final int SCAN_DEFER_DEX = 1<<7;
static final int SCAN_BOOTING = 1<<8; // 标记开机扫描阶段
static final int SCAN_TRUSTED_OVERLAY = 1<<9; // 关联mTrustedOverlay , 不再执行createIdmapForPackagePairLI
static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<10; // 应用安装失败, 删除应用数据
static final int SCAN_REPLACING = 1<<11;
static final int SCAN_REQUIRE_KNOWN = 1<<12;
static final int SCAN_MOVE = 1<<13; // 应用移动相关. 重用abi数据
static final int SCAN_INITIAL = 1<<14; // 应用升级有关,该标志标明应用为第一次扫描,不需要执行 shouldCheckUpgradeKeySetLP 函数,检查升级签名问题

// 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.
static final int SCAN_CHECK_ONLY = 1<<15;
static final int SCAN_DONT_KILL_APP = 1<<17; //与 DELETE_DONT_KILL_APP 关联, deletePackageX时不杀应用
static final int SCAN_IGNORE_FROZEN = 1<<18; // Sadly we don't know the package name yet to freeze it
// Caller asked us to ignore frozen check for some reason; they
// probably didn't know the package name
// 不掉用 checkPackageFrozen
1.1.1.2.1. scanDirLI 函数
  • 执行文件检查
1
2
3
4
5
6
7
final boolean isPackage = (isApkFile(file) || file.isDirectory())
// 排除stage file的情况, stage file不算 vmdl**.tmp smdl**.tmp smdl2tmp
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
  • 删除无效的用户apk
1
2
3
4
5
6
7
// Delete invalid userdata apps
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
// 删除codePath 如/data/app/**
removeCodePathLI(file);
}

调用scanPackageLI函数

1.1.1.2.2. scanPackageLI函数
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
/**
* Scans a package and returns the newly parsed package.
* Returns {@code null} in case of errors and the error code is stored in mLastScanError
*/
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
// 创建PackageParser
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);

Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final PackageParser.Package pkg;
// 调用 parsePackage函数
pkg = pp. parsePackage函数(scanFile, parseFlags);

/* Add for boot performance with multi-thread and preload scan @{*/
if(mPackageManagerServiceExUtils.isPreloadOrVitalApp(scanFile.getParent()) && mPackageManagerServiceExUtils.mDeleteRecord.exists()){
if(mPackageManagerServiceExUtils.isDeleteApp(pkg.packageName))return pkg;
}
/* @} */
// 调用scanPackageLI 进行apk的安装
return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
}
1.1.1.2.3. parsePackage函数
1
2
3
4
5
6
7
* Parse the package at the given location. Automatically detects if the
* package is a monolithic style (single APK file) or cluster style // 聚合apk
if (packageFile.isDirectory()) {
return parseClusterPackage(packageFile, flags);
} else {
return parseMonolithicPackage(packageFile, flags);
}
1.1.1.2.4. parseClusterPackage函数

这里只分析parseClusterPackage,省略parseMonolithicPackage函数的分析

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
private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
// 调用 parseClusterPackageLite 返回PackageLite对象
final PackageLite lite = parseClusterPackageLite(packageDir, 0);
// 磁盘加密相关, 如果直解析core app. 直接跳过
if (mOnlyCoreApps && !lite.coreApp) {
throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"Not a coreApp: " + packageDir);
}

final AssetManager assets = new AssetManager();
try {
// Load the base and all splits into the AssetManager
// so that resources can be overriden when parsing the manifests.
// 将lib库加载进 AssetManager 中
loadApkIntoAssetManager(assets, lite.baseCodePath, flags);

...
final File baseApk = new File(lite.baseCodePath);
//通过将baseApk的地址传入,解析baseApk, 返回Package对象
final Package pkg = parseBaseApk(baseApk, assets, flags);
....
pkg.setCodePath(packageDir.getAbsolutePath());
pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
} finally {
IoUtils.closeQuietly(assets);
}
}

这里用到的数据结构为PackageLite

1.1.1.2.5. parseClusterPackageLite函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private static PackageLite parseClusterPackageLite(File packageDir, int flags)
throws PackageParserException {
final File[] files = packageDir.listFiles();
.....
String packageName = null;
int versionCode = 0;

final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
for (File file : files) {
if (isApkFile(file)) {
// 对apk文件进行解析, 返回ApkLite对象, 包含baseApk和 splitApk,
final ApkLite lite = parseApkLite(file, flags);

// Assert that all package names and version codes are
// consistent with the first one we encounter.

if (packageName == null) {
packageName = lite.packageName;
versionCode = lite.versionCode;
}
// 以lite.splitName 为 key 保存 解析完成的ApkLite 对象,其中 baseApk 的 splitName为null
apks.put(lite.splitName, lite)
...
}
}
...
final ApkLite baseApk = apks.remove(null);
final String codePath = packageDir.getAbsolutePath();
// 生成PackageLite对象
return new PackageLite(codePath, baseApk, splitNames, splitCodePaths,
splitRevisionCodes);
}

parseClusterPackageLite函数用到了两个数据结构 ApkLite 和 PackageLite

1.1.1.2.6. parseBaseApk函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
// apk绑定 volumeUuid data分区还是sd卡格式化为内部存储的
String volumeUuid = null;
if (apkPath.startsWith(MNT_EXPAND)) {
final int end = apkPath.indexOf('/', MNT_EXPAND.length());
volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
}

if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
// 将apk载入到AssetManager中,加载入内存?
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);
// 通过 Jni 的方法将apk的manifest文件加载到内存,返回parser对象
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);

final String[] outError = new String[1];
// 调用 重载的方法真正进行解析
final Package pkg = parseBaseApk(res, parser, flags, outError);
....

pkg.setVolumeUuid(volumeUuid);
pkg.setApplicationVolumeUuid(volumeUuid);
pkg.setBaseCodePath(apkPath);
pkg.setSignatures(null);

return pkg;

}
...
}


private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
String[] outError) throws XmlPullParserException, IOException {
final String splitName;
final String pkgName;

... // 省略解析splitApk相关
//构造package对象
final Package pkg = new Package(pkgName);

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();
// 调用parseBaseApkCommon函数对apk进行解析
return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
}

这里用到的数据结构时Package

1.1.1.2.7. parseBaseApkCommon函数

对apk AndroidManifest进行解析,解析manifest节点

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
private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
IOException {
mParseInstrumentationArgs = null;
mParseActivityArgs = null;
mParseServiceArgs = null;
mParseProviderArgs = null;

int type;
boolean foundApp = false;

TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifest);

String str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
...

pkg.installLocation = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_installLocation,
PARSE_DEFAULT_INSTALL_LOCATION);
pkg.applicationInfo.installLocation = pkg.installLocation;


/* Set the global "forward lock" flag */
if ((flags & PARSE_FORWARD_LOCK) != 0) {
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
}

/* Set the global "on SD card" flag */
if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
}

if ((flags & PARSE_IS_EPHEMERAL) != 0) {
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_EPHEMERAL;
}

// Resource boolean are -1, so 1 means we don't know the value.
int supportsSmallScreens = 1;
int supportsNormalScreens = 1;
int supportsLargeScreens = 1;
int supportsXLargeScreens = 1;
int resizeable = 1;
int anyDensity = 1;

int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}

String tagName = parser.getName();

...

if (tagName.equals(TAG_APPLICATION)) {
// 只能有一个application节点
if (foundApp) {
// 刚性解析,直接跳出
if (RIGID_PARSER) {
outError[0] = "<manifest> has more than one <application>";
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
} else {
Slog.w(TAG, "<manifest> has more than one <application>");
XmlUtils.skipCurrentTag(parser);
continue;
}
}

foundApp = true;
// 解析application节点
if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
return null;
}
}
...
// 解析manifest节点下的其他节点
}
1.1.1.2.8. parseBaseApplication函数

解析application节点

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
private boolean parseBaseApplication(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
final ApplicationInfo ai = owner.applicationInfo;
final String pkgName = owner.applicationInfo.packageName;

TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestApplication);

String name = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_name, 0);


String manageSpaceActivity = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
Configuration.NATIVE_CONFIG_VERSION);


boolean allowBackup = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
...

ai.icon = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
ai.logo = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
ai.banner = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_banner, 0);
ai.theme = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
ai.descriptionRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_description, 0);

if ((flags&PARSE_IS_SYSTEM) != 0) {
// 只有 PARSE_IS_SYSTEM 标志的目录解析 带persistent的才会生效,常驻进程
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_persistent,
false)) {
ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
}
}

....
// debug标记
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
false)) {
ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
}
...
// 默认为true. 除了特殊情况, An application would not have any code of its own only if it's using nothing but built-in component classes, 比如AliasActivity
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
true)) {
ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
}


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

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
false)) {
ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
true)) {
ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
false /* default is no RTL support*/)) {
ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
false)) {
ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
true)) {
ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
}

if (sa.getBoolean(
R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
false)) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
}
if (sa.getBoolean(
R.styleable.AndroidManifestApplication_directBootAware,
false)) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
}

...
String str;
// 自定义权限
str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
ai.permission = (str != null && str.length() > 0) ? str.intern() : null;

ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
str, outError);

if (outError[0] == null) {
CharSequence pname;
if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
pname = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_process,
Configuration.NATIVE_CONFIG_VERSION);
} else {
// Some older apps have been seen to use a resource reference
// here that on older builds was ignored (with a warning). We
// need to continue to do this for them so they don't break.
pname = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestApplication_process);
}
//重设进程名?
ai.processName = buildProcessName(ai.packageName, null, pname,
flags, mSeparateProcesses, outError);

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


}


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();
if (tagName.equals("activity")) {
// 调用parseActivity对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);

} else if (tagName.equals("receiver")) {
// 调用parseActivity对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);

} else if (tagName.equals("service")) {
// 调用parseService对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);

} else if (tagName.equals("provider")) {
// 调用parseProvider对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")) {
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")) {
// note: application meta-data is stored off to the side, so it can
// remain null in the primary copy (we like to avoid extra copies because
// it can be large)
if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
outError)) == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

} else if (tagName.equals("library")) {
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestLibrary);

// 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.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")) {
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;
}
}
}

if (hasDomainURLs(owner)) {
owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
} else {
owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
}

return true;
}

解析的结果更新到Package owner对象中. 这里用到的数据结构是Activity 和 ApplicationInfo

1.1.1.2.9. parseActivity函数

activity节点进行解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
private Activity parseActivity(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError,
boolean receiver, boolean hardwareAccelerated)
throws XmlPullParserException, IOException {
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);

if (mParseActivityArgs == null) {
mParseActivityArgs = new ParseComponentArgs(owner, outError,
R.styleable.AndroidManifestActivity_name,
R.styleable.AndroidManifestActivity_label,
R.styleable.AndroidManifestActivity_icon,
R.styleable.AndroidManifestActivity_logo,
R.styleable.AndroidManifestActivity_banner,
mSeparateProcesses,
R.styleable.AndroidManifestActivity_process,
R.styleable.AndroidManifestActivity_description,
R.styleable.AndroidManifestActivity_enabled);
}

mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
mParseActivityArgs.sa = sa;
mParseActivityArgs.flags = flags;

Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
if (outError[0] != null) {
sa.recycle();
return null;
}
// Activity 是否可由其他应用的组件启动 若为“false”,则 Activity 只能由同一应用的组件或使用同一用户 ID 的不同应用(shareUserId)启动。
boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
if (setExported) {
a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
}

...
// Activity 逻辑父项的类名称。此处的名称必须与为相应 <activity> 元素的 android:name 属性指定的类名称一致。
//系统会读取该属性,以确定当用户按下操作栏中的“向上”按钮时应该启动哪一个 Activity。 系统还可以利用这些信息通过 TaskStackBuilder 合成 Activity 的返回栈。
String parentName = sa.getNonConfigurationString(
R.styleable.AndroidManifestActivity_parentActivityName,
Configuration.NATIVE_CONFIG_VERSION);
if (parentName != null) {
String parentClassName = buildClassName(a.info.packageName, parentName, outError);
if (outError[0] == null) {
a.info.parentActivityName = parentClassName;
} else {
Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
parentName);
outError[0] = null;
}
}

String str;
//客户端启动 Activity 或以其他方式令其响应 Intent 而必须具备的权限的名称。 如果系统尚未向 startActivity() 或 startActivityForResult() 的调用方授予指定权限,其 Intent 将不会传递给 Activity。
//如果未设置该属性,则对 Activity 应用 <application> 元素的 permission 属性设置的权限。 如果这两个属性均未设置,则 Activity 不受权限保护。
str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
if (str == null) {
a.info.permission = owner.applicationInfo.permission;
} else {
a.info.permission = str.length() > 0 ? str.toString().intern() : null;
}
// 与 Activity 有着亲和关系的任务。从概念上讲,具有相同亲和关系的 Activity 归属同一任务(从用户的角度来看,则是归属同一“应用”)。 任务的亲和关系由其根 Activity 的亲和关系确定。
//亲和关系确定两件事 - Activity 更改到的父项任务(请参阅 allowTaskReparenting 属性)和通过 FLAG_ACTIVITY_NEW_TASK 标志启动 Activity 时将用来容纳它的任务。
str = sa.getNonConfigurationString(
R.styleable.AndroidManifestActivity_taskAffinity,
Configuration.NATIVE_CONFIG_VERSION);
a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
owner.applicationInfo.taskAffinity, str, outError);

a.info.flags = 0;
... // 省略一系列标签,具体可参考Activity节点

if (a.info.directBootAware) {
owner.applicationInfo.privateFlags |=
ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
}

sa.recycle();

int outerDepth = parser.getDepth();
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG
|| parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}

if (parser.getName().equals("intent-filter")) {
ActivityIntentInfo intent = new ActivityIntentInfo(a);
// 调用parseIntent解析intent-filter标签
if (!parseIntent(res, parser, true, true, intent, outError)) {
return null;
}
if (intent.countActions() == 0) {
...
} else {
a.intents.add(intent);
}
// 首选应用标签.指定默认应用
} else if (!receiver && parser.getName().equals("preferred")) {
ActivityIntentInfo intent = new ActivityIntentInfo(a);
if (!parseIntent(res, parser, false, false, intent, outError)) {
return null;
}
if (intent.countActions() == 0) {
...
} else {
if (owner.preferredActivityFilters == null) {
owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
}
owner.preferredActivityFilters.add(intent);
}
} else if (parser.getName().equals("meta-data")) {
// 调用 parseMetaData 解析 meta-data标签
if ((a.metaData = parseMetaData(res, parser, a.metaData,
outError)) == null) {
return null;
}
// activity的布局相关
} else if (!receiver && parser.getName().equals("layout")) {
parseLayout(res, parser, a);
}
...
}
}

if (!setExported) {
a.info.exported = a.intents.size() > 0;
}

return a;
}
1.1.1.2.10. parseActivityAlias函数

activity-alias标签进行解析:

An alias for an activity, named by the targetActivity attribute. The target must be in the same application as the alias and it must be declared before the alias in the manifest.

指定targetActivity的应用别名

1.1.1.3. 扫描对应的数据结构简要分析

ScanPackage

当一切解析完成,返回解析的结果PackageParser.Package pkg

1.1.1.4. 安装流程

1.1.1.4.1. 过滤解析到的package对象
1
2
3
4
5
6
7
8
9
10
11
// Scan the parent
PackageParser.Package scannedPkg = scanPackageInternalLI(pkg, scanFile, policyFlags,
scanFlags, currentTime, user);

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

调用到了scanPackageInternalLI函数

1.1.1.4.2. scanPackageInternalLI函数
  • 获取原始包信息/解析到的包信息PackageSetting,以及查询是否是升级的系统包信息

从上一步parsePackage处返回的Package 的pkg对象和mSettings中保存的进行比较?

之前的mSettings中的值是从哪里来的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    // Look to see if we already know about this package.
String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
// This package has been renamed to its original name. Let's
// use that.
ps = mSettings.peekPackageLPr(oldName);
}
// If there was no original package, see one for the real package name.
if (ps == null) {
ps = mSettings.peekPackageLPr(pkg.packageName);
}
// Check to see if this package could be hiding/updating a system
// package. Must look for it either under the original or real
// package name depending on our state.
// 如果是hiding package
updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
}
1.1.1.4.2.1. 过滤要更新的系统包

当前解析的包信息是需要升级的系统级应用并且APK包路径发生变化时,根据版本信息选择跳过或者升级该包:

  • 当前扫描到的版本信息小于已安装版本信息:

直接返回null,不再进行后续的安装操作。相关代码如下:

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
if (ps != null && !ps.codePath.equals(scanFile)) {
// The path has changed from what was last scanned... check the
// version of the new path against what we have stored to determine
// what to do.
if (DEBUG_INSTALL) Slog.d(TAG, "Path changing from " + ps.codePath);
// 当前扫描到的版本信息小于已安装版本信息
if (pkg.mVersionCode <= ps.versionCode) {
// The system package has been updated and the code path does not match
// Ignore entry. Skip it.
if (DEBUG_INSTALL) Slog.i(TAG, "Package " + ps.name + " at " + scanFile
+ " ignored: updated version " + ps.versionCode
+ " better than this " + pkg.mVersionCode);
if (!updatedPkg.codePath.equals(scanFile)) {
Slog.w(PackageManagerService.TAG, "Code path for hidden system pkg "
+ ps.name + " changing from " + updatedPkg.codePathString
+ " to " + scanFile);
// 更新path
updatedPkg.codePath = scanFile;
updatedPkg.codePathString = scanFile.toString();
updatedPkg.resourcePath = scanFile;
updatedPkg.resourcePathString = scanFile.toString();
}
updatedPkg.pkg = pkg;
updatedPkg.versionCode = pkg.mVersionCode;

// Update the disabled system child packages to point to the package too.
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);
}
  • 扫描到的版本信息大于已安装版本信息:

首先从PackageManagerService.mPackages删除原始包信息,创建安装参数,删除dexFile,并将包从mSettings.mDisabledSysPackages中删除,将新的包信息添加到PackageManagerService.mPackages中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
else {
synchronized (mPackages) {
// Just remove the loaded entries from package lists.
// 从PackageManagerService.mPackages删除原始包信息
mPackages.remove(ps.name);
}
// 创建安装参数,删除dexFile
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
// 将包从mSettings.mDisabledSysPackages中删除,将新的包信息添加到PackageManagerService.mPackages中
synchronized (mPackages) {
mSettings.enableSystemPackageLPw(ps.name);
}
updatedPkgBetter = true;
}

同时由于要升级的系统级APK初始没有设置系统级标志,在此处添加;如果要更新的包原来是特权包,此处也要添加该标志。

1
2
3
4
5
6
7
8
9
10
11
if (updatedPkg != null) {
// An updated system app will not have the PARSE_IS_SYSTEM flag set
// initially
policyFlags |= PackageParser.PARSE_IS_SYSTEM;

// An updated privileged app will not have the PARSE_IS_PRIVILEGED
// flag set initially
if ((updatedPkg.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
policyFlags |= PackageParser.PARSE_IS_PRIVILEGED;
}
}
1.1.1.4.2.2. 进行证书验证
1
2
// Verify certificates against what was last scanned, 收集证书,并进行验证.验证文件内容和记录的hash值是否一致,不一致抛出异常.
collectCertificatesLI(ps, pkg, scanFile, policyFlags);

针对系统级APK,只验证AndroidManifest.xml文件;对于非系统级APK需验证所有的文件。将获得的证书和签名信息以及签名键值分别存入pkg.mCertificates、pkg.mSignatures以及pkg.mSigningKeys中。

在对非系统级APK进行证书验证时,开启了两个线程进行验证,加快了验证速度,从而减少了APK的安装时间,改善了性能。

1.1.1.4.2.3. 系统级包与同名非系统级包冲突

当要扫描安装的是新出现的系统级包,此时已经安装了同名的非系统级包,首先要验证签名信息:

  • 签名信息不匹配

调用deletePackageLI方法,删除已安装的应用和数据,但不更新pakcages.xml等文件。

1
2
3
4
5
6
7
8
9
10
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");
try (PackageFreezer freezer = freezePackage(pkg.packageName,
"scanPackageInternalLI")) {
deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null);
}
ps = null;
}
  • 签名信息匹配

当签名信息匹配时,如果当前系统包的版本低于已安装的非系统包,暂时隐藏该系统包,稍候再次扫描,如同更新一样添加该包。

当版本信息高于已安装的非系统包,删除这个已安装的应用,删除codepath及dex文件,用新的系统包代替,但是保留已安装包的数据信息

1
2
3
4
5
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
1.1.1.4.2.4. 后处理

对于非系统目录下的apk,当它的代码和资源在不同的文件中时,添加PARSE_FORWARD_LOCK标志。

接下来显式设置APK的应用信息路径,pkg.application.sourceDir设置为pkg.mScanPath; pkg.application.publicSourceDir则根据APk是否为前置锁类型,设置为 ps.resourcePathString/null(前置锁类型,可以扫描到包/不可以),或者pkg.mScanPath。主要是为前置锁类型的APK更新其代码和资源文件路径,分别为data/app-private/<包名>.apk和data/app/<包名>.zip,然后据此更新pkg.mPath、pkg.mScanpath、pkg.application.sourceDir和pkg.application.publicSourceDir。

接下来调用scanPackageLI解析和安装过滤后的pkg。

1.1.1.4.3. scanPackageLI函数

调用scanPackageDirtyLI函数进行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
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, final int policyFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
boolean success = false;
try {
// 调用scanPackageDirtyLI函数进行apk的安装
final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags,
currentTime, user);
if (true) {
if (res.applicationInfo.primaryCpuAbi != null
&& !res.applicationInfo.primaryCpuAbi.isEmpty()
&& res.applicationInfo.primaryCpuAbi.startsWith("arm")) {
//primaryCpuAbi 为arm开头的情况下, 替换统一的库
NativeLibraryHelper.replaceUnityLibraries(res.packageName,
res.applicationInfo.nativeLibraryDir, res.applicationInfo.primaryCpuAbi);
}
}
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);
}
}
}
1.1.1.4.4. scanPackageDirtyLI函数

根据要解析的apk类型(系统级/特权级/其它),更新pkg.applicationInfo.flags的值。

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
// Apply policy
if ((policyFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
if (pkg.applicationInfo.isDirectBootAware()) {
// we're direct boot aware; set for all components
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 {
// 不是system app不能有下面的特权
// Only allow system apps to be flagged as core apps.
pkg.coreApp = false;
// clear flags not applicable to regular apps
pkg.applicationInfo.privateFlags &=
~ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
pkg.applicationInfo.privateFlags &=
~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
}

在PackageManagerService的启动阶段,如果设置了mCustomResolverComponentName,并且要解析的包名与其包名相同,则用其值替换要解析的组件名,并设置解析信息:

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
if (mCustomResolverComponentName != null &&
mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
setUpCustomResolverActivity(pkg);
}

private void setUpCustomResolverActivity(PackageParser.Package pkg) {
synchronized (mPackages) {
mResolverReplaced = true;
// Set up information for custom user intent resolution activity.
mResolveActivity.applicationInfo = pkg.applicationInfo;
mResolveActivity.name = mCustomResolverComponentName.getClassName();
mResolveActivity.packageName = pkg.applicationInfo.packageName;
mResolveActivity.processName = pkg.applicationInfo.packageName;
mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS |
ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
mResolveActivity.theme = 0;
mResolveActivity.exported = true;
mResolveActivity.enabled = true;
mResolveInfo.activityInfo = mResolveActivity;
mResolveInfo.priority = 0;
mResolveInfo.preferredOrder = 0;
mResolveInfo.match = 0;
mResolveComponentName = mCustomResolverComponentName;
Slog.i(TAG, "Replacing default ResolverActivity with custom activity: " +
mResolveComponentName);
}
}
1.1.1.4.4.1. 处理framework-res.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
// framework-res.apk 相关
if (pkg.packageName.equals("android")) {
synchronized (mPackages) {
// 首先判定PackageManagerService.mAndroidApplication是否为null,因为framework-res.apk只能安装一次。
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;
// 该mResolveActivity用于用户自选activity
if (!mResolverReplaced) {
mResolveActivity.applicationInfo = mAndroidApplication;
mResolveActivity.name = ResolverActivity.class.getName();
mResolveActivity.packageName = mAndroidApplication.packageName;
mResolveActivity.processName = "system:ui";
mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER;
mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert;
mResolveActivity.exported = true;
mResolveActivity.enabled = true;
mResolveActivity.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
mResolveActivity.configChanges = ActivityInfo.CONFIG_SCREEN_SIZE
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE
| ActivityInfo.CONFIG_SCREEN_LAYOUT
| ActivityInfo.CONFIG_ORIENTATION
| ActivityInfo.CONFIG_KEYBOARD
| ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
mResolveInfo.activityInfo = mResolveActivity;
mResolveInfo.priority = 0;
mResolveInfo.preferredOrder = 0;
mResolveInfo.match = 0;
mResolveComponentName = new ComponentName(
mAndroidApplication.packageName, mResolveActivity.name);
}
}
}
}
1.1.1.4.4.2. 跳过已安装的APK
1
2
3
4
5
6
if (mPackages.containsKey(pkg.packageName)
|| mSharedLibraries.containsKey(pkg.packageName)) {
throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
"Application package " + pkg.packageName
+ " already installed. Skipping duplicate.");
}
1.1.1.4.4.3. 初始化应用信息
1
2
3
4
5
6
7
8
9
10
11
12
13
// Initialize package source and resource directories
File destCodeFile = new File(pkg.applicationInfo.getCodePath());
File destResourceFile = new File(pkg.applicationInfo.getResourcePath());

SharedUserSetting suid = null;
PackageSetting pkgSetting = null;

if (!isSystemApp(pkg)) {
// Only system apps can use these features.
pkg.mOriginalPackages = null;
pkg.mRealPackage = null;
pkg.mAdoptPermissions = null;
}
1.1.1.4.4.4. 检查并分配SharedUserId

pkg. mSharedUserId是在解析manifest标签的内置属性sharedUserId时赋值的。

当应用解析到该属性,调用mSettings.getSharesUserLPw方法,获取SharedUserSetting类型的对象s。

该方法首先从mSettings.mSharedUsers中根据pkg. SharedUserId查找是否存在该信息:若存在直接返回;否则,创建该数据类型,并调用mSettings.newUserIdLPw方法从mSettings.mUsersId中分配一个SharedUserSetting.userId(即在mUsersId中空位置插入s,获取索引号,或者在后面添加s获取索引号,或者mSettings.mUsersId已满则返回-1),如果成功获取SharedUserSetting.userId后,将新创建的对象s添加到mSettings.mSharedUsers中,返回该s。

最后根据获取到的共享用户信息s:为null时直接返回null,跳过后续部分;否则继续后续步骤。

1
2
3
4
5
6
7
8
9
if (pkg.mSharedUserId != null) {
// 添加shareUser到mSharedUsers中
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");
}
}
1.1.1.4.4.5. 检查并分配SharedUserId

pkg. mSharedUserId是在解析manifest标签的内置属性sharedUserId时赋值的。

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
if (pkg.mSharedUserId != null) {
// 添加shareUser到mSharedUsers中
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");
}
}
SharedUserSetting getSharedUserLPw(String name,
int pkgFlags, int pkgPrivateFlags, boolean create) {
// 查找数组中有没有该 shareUserName 名称, 比如开头的 android.uid.system
SharedUserSetting s = mSharedUsers.get(name);
if (s == null) {
// create 为true
if (!create) {
return null;
}
s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
// 调用mSettings.newUserIdLPw方法从mSettings.mUsersId中分配一个SharedUserSetting.userId
// 即在mUsersId中空位置插入s,获取索引号,或者在后面添加s获取索引号,或者mSettings.mUsersId已满则返回-1
s.userId = newUserIdLPw(s);
Log.i(PackageManagerService.TAG, "New shared user " + name + ": id=" + s.userId);
// < 0 means we couldn't assign a userid; fall out and return
// s, which is currently null
if (s.userId >= 0) {
mSharedUsers.put(name, s);
}
}

return s;
}
1.1.1.4.4.6. 处理系统级APK的原始包名mOriginalPackages(更名的包)

当AndroidManafest.xml文件指定了original-package标签(原来的包名),将name属性存入pkg. mOriginalPackages,当前包名存入pkg.mRealPackage.

只有系统级应用,pkg.mOriginalPackages才为非null,此步骤有效.

首先与mSettings.mRenamedPackages中pkg.mRealPackage对应的旧包名对比:

  • 旧包名包含在pkg.mOriginalPackages,沿用旧包名

当旧包名renamed包含在pkg. mOriginalPackages中时,如果当前的包名pkg.packageName与旧包名renamed不相同时,调用pkg.setPackageName方法,将当前的包名更换为旧包名,其它涉及到包名的也更换,即新包沿用旧包包名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// mRenamedPackages 中保存了所有经过重命名的包名,以其realName为键值.保存了 original-package标签的名字. 
// mSetting对应过去的对象
final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
// 当旧包名renamed包含在pkg. mOriginalPackages中时
if (pkg.mOriginalPackages.contains(renamed)) {
// This package had originally been installed as the
// original name, and we have already taken care of
// transitioning to the new one. Just update the new
// one to continue using the old name.
realName = pkg.mRealPackage;
// 如果当前包名不为 original-package , 就设为 original-package
if (!pkg.packageName.equals(renamed)) {
// Callers into this function may have already taken
// care of renaming the package; only do it here if
// it is not already done.
// 沿用旧包名
pkg.setPackageName(renamed);
}
}
  • 旧包名不包含在原始包名中,保留原始包信息

当旧包名不包含在pkg. mOriginalPackages中时,遍历pkg. mOriginalPackages,确定安装包是否在某个原始包名下进行了安装:如果已安装,首先验证是否是系统级应用的升级行为,接着确定已安装的包信息和当前包信息的共享用户信息是否一致,当全部匹配时结束遍历。

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
else {
for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
// 最终返回不符合下面条件的包名, origPackage后面构造PackageSetting时会用到
if ((origPackage = mSettings.peekPackageLPr(
pkg.mOriginalPackages.get(i))) != null) {
// We do have the package already installed under its
// original name... should we use it?
// 非系统目录返回失败,或者origPackage包当前已经安装的情况,会返回失败
if (!verifyPackageUpdateLPr(origPackage, pkg)) {
// New package is not compatible with original.
origPackage = null;
continue;
} else if (origPackage.sharedUser != null) {
// Make sure uid is compatible between packages.
// sharedUserId项 和 之前的不匹配,
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;
}
// TODO: Add case when shared user id is added [b/28144775]
} else {
if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
+ pkg.packageName + " to old name " + origPackage.name);
}
break;
}
}

当安装包安装完成后,包名发生变更,在重启手机重新扫描该包时,将新包名更换为旧包名,沿用旧包名;但当pkg.mOriginalPackages中匹配不到旧包名时,保留新包名,并保留原始包信息,但下一章节中会对包名和原始包信息处理,最终更名的包都会沿用初始安装时的包名。

1.1.1.4.4.7. 获取/创建包信息PackageSetting

调用mSettings.getPackageLPw方法获取已安装的包信息/创建新的包信息,但是并不添加到mSettings.mPackages中。

首先判断mSettings.mPackages是否存在该包信息,即是否已经安装过安装包,从而决定是创建新的包信息还是返回原有包信息。

如果存在包信息,说明包已经安装过,且是需要升级/更名的包,打印一些相关log信息,以及验证共享用户信息是否一致,代码如下:

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

PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi,
int pkgFlags, int pkgPrivateFlags, UserHandle user, boolean add) {
final String name = pkg.packageName;
final String parentPackageName = (pkg.parentPackage != null)
? pkg.parentPackage.packageName : null;
// 处理包的子包,最终把 parentPackage childPackage的name取出来放到相应数据中
List<String> childPackageNames = null;
if (pkg.childPackages != null) {
// 遍历 childPackages
final int childCount = pkg.childPackages.size();
childPackageNames = new ArrayList<>(childCount);
for (int i = 0; i < childCount; i++) {
String childPackageName = pkg.childPackages.get(i).packageName;
childPackageNames.add(childPackageName);
}
}

PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi,
pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user, add, true /* allowInstall */,
// 传入上面得到的parentPackageName childPackageNames
parentPackageName, childPackageNames);
return p;
}

private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
String legacyNativeLibraryPathString, String primaryCpuAbiString,
String secondaryCpuAbiString, int vc, int pkgFlags, int pkgPrivateFlags,
UserHandle installUser, boolean add, boolean allowInstall, String parentPackage,
List<String> childPackageNames) {
// mPackages 中是否能查到该对象
PackageSetting p = mPackages.get(name);
UserManagerService userManager = UserManagerService.getInstance();
if (p != null) {
// 能查到,则更新其字段
...
if (!p.codePath.equals(codePath)) {
if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
// 原来的是system app情况下, 此时解析的是data app, codepath并没有变更,沿用旧的值
Slog.w(PackageManagerService.TAG, "Trying to update system app code path from "
+ p.codePathString + " to " + codePath.toString());
} else {
// 此处为System app的情况, 设置所有用户都默认安装该应用
if ((pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0 &&
getDisabledSystemPkgLPr(name) == null) {
List<UserInfo> allUserInfos = getAllUsers();
if (allUserInfos != null) {
for (UserInfo userInfo : allUserInfos) {
p.setInstalled(true, userInfo.id);
}
}
}
}
// sharedUser不相等时, 直接清空PackageSetting对象,即原来的作废
if (p.sharedUser != sharedUser) {
p = null;
} else {
// 此处对应的是新扫描的apk如果是特权apk, 则特权继承
p.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
p.pkgPrivateFlags |= pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
}
}
// 构造新的PackageSetting对象
if (p == null) {
// 如果 origPackage 不为空时, 很多属性会从 origPackage 拿过来.
if (origPackage != null) {
// We are consuming the data from an existing package.
// 如果是新的PackageSetting对象,则沿用旧的包名. 当前的包名 name 存放到 realName 字段
p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
null /* cpuAbiOverrideString */, vc, pkgFlags, pkgPrivateFlags,
parentPackage, childPackageNames);

....
p.origPackage = origPackage;
p.getPermissionsState().copyFrom(origPackage.getPermissionsState());
mRenamedPackages.put(name, origPackage.name);
name = origPackage.name;
// Update new package state.
p.setTimeStamp(codePath.lastModified());
} else {
// 如果 origPackage 为空时
p = new PackageSetting(name, realName, codePath, resourcePath,
legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
null /* cpuAbiOverrideString */, vc, pkgFlags, pkgPrivateFlags,
parentPackage, childPackageNames);
p.setTimeStamp(codePath.lastModified());
p.sharedUser = sharedUser;
// If this is not a system app, it starts out stopped.
// 如果是非系统应用,置为stopped状态,并写入pakckage-restrictions.xml
if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
if (DEBUG_STOPPED) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
Slog.i(PackageManagerService.TAG, "Stopping package " + name, e);
}
List<UserInfo> users = getAllUsers();
final int installUserId = installUser != null ? installUser.getIdentifier() : 0;
if (users != null && allowInstall) {
for (UserInfo user : users) {
final boolean installed = installUser == null
|| (installUserId == UserHandle.USER_ALL
&& !isAdbInstallDisallowed(userManager, user.id))
|| installUserId == user.id;
p.setUserState(user.id, 0, COMPONENT_ENABLED_STATE_DEFAULT,
installed,
true, // stopped, 非系统应用默认禁用
true, // notLaunched
false, // hidden
false, // suspended
null, null, null,
false, // blockUninstall
INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0);
// 此处会更新pakckage-restrictions.xml文件
writePackageRestrictionsLPr(user.id);
}
}
}
if (sharedUser != null) {
// shareUser 不为空, app对应的appid是shareUser的
p.appId = sharedUser.userId;
} else {
// Clone the setting here for disabled system packages
// 当前包在禁用的系统包中的时候
PackageSetting dis = mDisabledSysPackages.get(name);
if (dis != null) {
// 签名继承在mDisabledSysPackages找到的
if (dis.signatures.mSignatures != null) {
p.signatures.mSignatures = dis.signatures.mSignatures.clone();
}
p.appId = dis.appId;
// Clone permissions
p.getPermissionsState().copyFrom(dis.getPermissionsState());
// Clone component info
List<UserInfo> users = getAllUsers();
if (users != null) {
for (UserInfo user : users) {
int userId = user.id;
p.setDisabledComponentsCopy(
dis.getDisabledComponents(userId), userId);
p.setEnabledComponentsCopy(
dis.getEnabledComponents(userId), userId);
}
}
// Add new setting to list of user ids
// 将p.appId添加到mSettngs.mUserIds或者mSettings.otherUserIds中
addUserIdLPw(p.appId, p, name);
} else {
// Assign new user id
// 获取应用id或者分配新的的id,添加到mSettngs.mUserIds或者mSettings.otherUserIds中
p.appId = newUserIdLPw(p);
}
}
}
if (p.appId < 0) {
return null;
}
if (add) {
// Finish adding new package by adding it and updating shared
// user preferences
addPackageSettingLPw(p, name, sharedUser);
}
// packageSetting不为新构造的情况下, 即packageSetting不为新构造的情况下, 当包信息存在时:不需要创建新的包信息,只需要获取包信息的安装状态,并根据安装状态决定是否更新pakckage-restrictions.xml文件。
} else {
if (installUser != null && allowInstall) {
List<UserInfo> users = getAllUsers();
if (users != null) {
for (UserInfo user : users) {
// 为所有用户安装,且没有禁用adb安装情况下|| 或指定为某个用户安装情况下, 对这些用户安装该apk, 并更新Pakcages.xml文件
if ((installUser.getIdentifier() == UserHandle.USER_ALL
&& !isAdbInstallDisallowed(userManager, user.id))
|| installUser.getIdentifier() == user.id) {
boolean installed = p.getInstalled(user.id);
if (!installed) {
p.setInstalled(true, user.id);
writePackageRestrictionsLPr(user.id);
}
}
}
}
}
}
return p;
}

最终返回创建/的包信息,如果包信息为null,说明无法创建该应用信息,直接返回,null,跳过后续步骤。

1.1.1.4.4.8. 更名包的后续处理

创建的包信息包含原始包信息时,将包名更换为原始包信息的包名,并将原始包信息置为null。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (pkgSetting.origPackage != null) {

// 将包名更换为原始包信息的包名
pkg.setPackageName(origPackage.name);

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

// No longer need to retain this.
// 并将原始包信息置为null
pkgSetting.origPackage = null;
}

对该包进行SELinux相关的操作。

1
2
3
if (mFoundPolicyFile) {
SELinuxMMAC.assignSeinfoValue(pkg);
}

将申请的包信息的应用pkgSetting.appId存入到pkg.applicationInfo.uid中,包信息pkgSetting存入到pkg.mExtras中。

1
2
pkg.applicationInfo.uid = pkgSetting.appId;
pkg.mExtras = pkgSetting;
1.1.1.4.4.9. 为非系统应用更新共享库信息

只有非系统级应用在扫描安装过程才会由于更新共享库导致安装失败,因此只针对非系统级应用在扫描过程中更新其共享库信息,而系统级应用在扫描完成后统一更新所有的共享库信息。

调用updateSharedLibrariesLPw方法更新共享库信息,若失败,直接返回null。

该方法主要是针对在AndroidManifest.xml文件中解析到的uses-library标签信息,信息存入了pkg.usesLibraries和pkg.usesOptionalLibraries。若二者都为null,说明没有用到库信息,直接返回true,解析过程继续;

当pkg.usesLibraries不为null时,检查PackageManagerService.mSharedLibraries中是否存在该库信息:如果存在则将共享库对应的路径信息存入PackageManagerService.mTmpSharedLibraries中;否则说明APK声明了一个不存在的共享库,那么更新失败,返回false。

当pkg.usesOptionalLibraries不为null时:检查PackageManagerService.mSharedLibraries中是否存在该库信息:如果存在则将共享库对应的路径信息存入PackageManagerService.mTmpSharedLibraries中;否则输出警告信息。

最后,将共享库路径信息更新到pkg.usesLibrariesFiles中。

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

private void updateSharedLibrariesLPw(PackageParser.Package pkg,
PackageParser.Package changingLib) throws PackageManagerException {
if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
final ArraySet<String> usesLibraryFiles = new ArraySet<>();
int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
for (int i=0; i<N; i++) {
// 从 mSharedLibraries 找对应的lib项
final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesLibraries.get(i));
if (file == null) {
//没有找到,报异常
throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
"Package " + pkg.packageName + " requires unavailable shared library "
+ pkg.usesLibraries.get(i) + "; failing!");
}
// 此处changingLib为null,将file关联的codepath添加到usesLibraryFiles中
addSharedLibraryLPw(usesLibraryFiles, file, changingLib);
}
N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
for (int i=0; i<N; i++) {
final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
if (file == null) {
Slog.w(TAG, "Package " + pkg.packageName
+ " desires unavailable shared library "
+ pkg.usesOptionalLibraries.get(i) + "; ignoring!");
} else {
addSharedLibraryLPw(usesLibraryFiles, file, changingLib);
}
}
// 最终更新到 package的usesLibraryFiles数组中
N = usesLibraryFiles.size();
if (N > 0) {
pkg.usesLibraryFiles = usesLibraryFiles.toArray(new String[N]);
} else {
pkg.usesLibraryFiles = null;
}
}
}
private void addSharedLibraryLPw(ArraySet<String> usesLibraryFiles, SharedLibraryEntry file,
PackageParser.Package changingLib) {
if (file.path != null) {
usesLibraryFiles.add(file.path);
return;
}
// file.path为空时,继续往下走
PackageParser.Package p = mPackages.get(file.apk);
if (changingLib != null && changingLib.packageName.equals(file.apk)) {
// 没找到对应的package 或者 package和changingLib为同一包名时, 替换为ChangingLib的codepath
if (p == null || p.packageName.equals(changingLib.packageName)) {
p = changingLib;
}
}
// 将package的 codepath添加到usesLibraryFiles中
if (p != null) {
usesLibraryFiles.addAll(p.getAllCodePaths());
}
}
1.1.1.4.4.10. 调用verifySignaturesLP验证签名

要验证的签名信息是在验证证书时获取到的,验证通过继续后续步骤,主要是验证上一次安装的签名信息和本次扫描的签名信息是否一致,上一次共享用户信息的签名信息是否和本次扫描的签名信息一致

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
// 检查其upgradeKeySets是否有效  pkgSetting 作为olgPkg
if (shouldCheckUpgradeKeySetLP(pkgSetting, scanFlags)) {
// 检查PackageSettting和pkg中的签名是否一致
if (checkUpgradeKeySetLP(pkgSetting, pkg)) {
// We just determined the app is signed correctly, so bring
// over the latest parsed certs.
pkgSetting.signatures.mSignatures = pkg.mSignatures;
} else {
// 不一致且为data app的情况. 抛出异常
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 {
// 如果不一致,但pkg是system app, 直接替换掉旧签名
pkgSetting.signatures.mSignatures = pkg.mSignatures;
String msg = "System package " + pkg.packageName
+ " signature changed; retaining data.";
reportSettingsProblem(Log.WARN, msg);
}
}
} else {
// 包签名无效的情况, 验证签名
try {
verifySignaturesLP(pkgSetting, pkg);
// We just determined the app is signed correctly, so bring
// over the latest parsed certs.
// 验证通过,则替换到pkgSetting的签名为 pkg的签名
pkgSetting.signatures.mSignatures = pkg.mSignatures;
} catch (PackageManagerException e) {
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
// data app直接往上抛异常
throw e;
}
// The signature has changed, but this package is in the system
// image... let's recover!
// 没有验证通过时, 如果为system app 仍然替换
pkgSetting.signatures.mSignatures = pkg.mSignatures;
// However... if this package is part of a shared user, but it
// doesn't match the signature of the shared user, let's fail.
// What this means is that you can't change the signatures
// associated with an overall shared user, which doesn't seem all
// that unreasonable.
if (pkgSetting.sharedUser != null) {
// 如果其shareUserId不为空时, 如果shareuser 包对应的签名和当前pkg的签名不一致,抛出异常
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);
}
}
}

当验证不通过时:对于扫描的是非系统目录,直接返回null,不再继续后续步骤;对于系统目录,将包的签名信息更新到包信息的签名信息中,然后验证包信息的共享用户信息的签名信息和包的签名信息是否一致,不一致直接返回null

1.1.1.4.4.11. 检查新包和已安装包的ContentProvider是否冲突

对于首次安装的包,即scanMode&SCAN_NEW_INSTALL!=0,才检查该包的providers是否与PackageManagerService.mProvidersByAuthority冲突,当冲突时(即pkg.providers存储的某个成员存在于PackageManagerService.mProvidersByAuthority)返回null,跳过后续步骤,否则继续。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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);
}
}
}
}
}
1.1.1.4.4.12. 为系统级包抽取权限信息

只有系统级包才能抽取其它系统级包定义的权限,将该权限所属的包变为所要抽取的系统包名,被抽取的包名是通过pkg.mAdoptPermissions指定的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if ((scanFlags & SCAN_CHECK_ONLY) == 0 && pkg.mAdoptPermissions != null) {
// This package wants to adopt ownership of permissions from
// another package.
for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
// 从 mAdoptPermissions 中取出原包名
final String origName = pkg.mAdoptPermissions.get(i);
final PackageSetting orig = mSettings.peekPackageLPr(origName);
if (orig != null) {
// orig package必须在system 中, 且 在mPackages中查询不到,即该 orig package还没有安装,只是经过扫描
if (verifyPackageUpdateLPr(orig, pkg)) {
Slog.i(TAG, "Adopting permissions from " + origName + " to "
+ pkg.packageName);
// Transfer ownership of permissions to the new package.
// 从orig package抽取 权限信息, 将其source package替换为现在的包名
mSettings.transferPermissionsLPw(origName, pkg.packageName);
}
}
}
}
1.1.1.4.4.13. 创建数据目录

首先获取当前扫描的时间戳,便于更新第一次安装/升级时间。

对于framework-res.apk,将/data/system路径存入pkg.applicationInfo.dataDir中。

当前数据目录所有者ID与pkg,applicationInfo.uid匹配时,直接将数据目录存入pkg.applicationInfo.dataDir中;

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
// 此处 mPlatformPackage 指的是 framework-res.apk
if (pkg != mPlatformPackage ) {
// Get all of our default paths setup 机主用户
pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM);
}

public void initForUser(int userId) {
uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
// android开头的包名,比如android.ext.services
if ("android".equals(packageName)) {
// 路径设置为 /data/system
dataDir = Environment.getDataSystemDirectory().getAbsolutePath();
return;
}
// DE区 /data/user_de/0
deviceEncryptedDataDir = deviceProtectedDataDir = Environment
.getDataUserDePackageDirectory(volumeUuid, userId, packageName)
.getAbsolutePath();
// CE区 /data/user/0 | /data/data
credentialEncryptedDataDir = credentialProtectedDataDir = Environment
.getDataUserCePackageDirectory(volumeUuid, userId, packageName)
.getAbsolutePath();
// 设置了 defaultToDeviceProtectedStorage 后,默认的数据目录在DE区
if ((privateFlags & PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) != 0
&& PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
dataDir = deviceProtectedDataDir;
} else {
// 否则在CE区
dataDir = credentialProtectedDataDir;
}
}
1.1.1.4.4.14. 处理本地库目录

当存储了本地库路径信息时,根据包的不同类型对本地库进行处理,决定是否从apk中解压出库文件到相应的本地库目录中extractLibs=true:

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
// cpuAbiOverride 来源于 安装时 指定的参数
final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
if (pkgSetting != null && pkgSetting.hasMultiArchLibString != null)
pkg.applicationInfo.hasMultiArchLib = pkgSetting.hasMultiArchLibString;

if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
// 不是新安装的包名, 抽取native库到对应的库目录中
derivePackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */);

// Some system apps still use directory structure for native libraries
// in which case we might end up not detecting abi solely based on apk
// structure. Try to detect abi based on directory structure.

// 上面使用 derivePackageAbi 无效时, primaryCpuAbi 为null. 需要基于 目录结构 监测abi,并设定指令集
if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() &&
pkg.applicationInfo.primaryCpuAbi == null) {
// 根据目录是否存在来设定指令集
setBundledAppAbisAndRoots(pkg, pkgSetting);
// 更新 pkg.applicationinfo的 nativeLibraryRootDir nativeLibraryRootRequiresIsa nativeLibraryDir secondaryNativeLibraryDir
setNativeLibraryPaths(pkg);
}

} else {
// 新安装的包的情况
if ((scanFlags & SCAN_MOVE) != 0) {
// 为移动apk的场景时. 直接继承原来的abi
// We haven't run dex-opt for this move (since we've moved the compiled output too)
// but we already have this packages package info in the PackageSetting. We just
// use that and derive the native library path based on the new codepath.
pkg.applicationInfo.primaryCpuAbi = pkgSetting.primaryCpuAbiString;
pkg.applicationInfo.secondaryCpuAbi = pkgSetting.secondaryCpuAbiString;
}

// Set native library paths again. For moves, the path will be updated based on the
// ABIs we've determined above. For non-moves, the path will be updated based on the
// ABIs we determined during compilation, but the path will depend on the final
// package path (after the rename away from the stage path).
setNativeLibraryPaths(pkg);
}

// This is a special case for the "system" package, where the ABI is
// dictated by the zygote configuration (and init.rc). We should keep track
// of this ABI so that we can deal with "normal" applications that run under
// the same UID correctly.
// framework-res.apk 初始化primaryCpuAbi
if (mPlatformPackage == pkg) {
pkg.applicationInfo.primaryCpuAbi = VMRuntime.getRuntime().is64Bit() ?
Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
}

private void derivePackageAbi(PackageParser.Package pkg, File scanFile,
String cpuAbiOverride, boolean extractLibs)
throws PackageManagerException {
// 设定本地库目录, 本地库目录下可能并没有东西
setNativeLibraryPaths(pkg);

// We would never need to extract libs for forward-locked and external packages,
// since the container service will do it for us. We shouldn't attempt to
// extract libs from system app when it was not updated.
if (pkg.isForwardLocked() || pkg.applicationInfo.isExternalAsec() ||
(isSystemApp(pkg) && !pkg.isUpdatedSystemApp())) {
extractLibs = false;
}

final String nativeLibraryRootStr = pkg.applicationInfo.nativeLibraryRootDir;
final boolean useIsaSpecificSubdirs = pkg.applicationInfo.nativeLibraryRootRequiresIsa;

NativeLibraryHelper.Handle handle = null;
try {
// 打开 apk 文件及splitapp文件
handle = NativeLibraryHelper.Handle.create(pkg);
final File nativeLibraryRoot = new File(nativeLibraryRootStr);

// Null out the abis so that they can be recalculated.
pkg.applicationInfo.primaryCpuAbi = null;
pkg.applicationInfo.secondaryCpuAbi = null;
// 包含多个指令集的情况
if (isMultiArch(pkg.applicationInfo)) {
// Warn if we've set an abiOverride for multi-lib packages..
// By definition, we need to copy both 32 and 64 bit libraries for
// such packages.
// install apk的参数
if (pkg.cpuAbiOverride != null
&& !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
}

int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
// data app 该值才为true 或者 system app 但不是update app的情况, 该标志的含义是从apk文件中解压出库文件写到对应的库目录中
if (extractLibs) {
// 创建 nativeLibraryRoot 目录, 将native 库的字节从apk 压缩文件中复制到相应库目录下
abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
useIsaSpecificSubdirs);
} else {
abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
}
}

if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
if (extractLibs) {
abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
useIsaSpecificSubdirs);
} else {
abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
}
}
if (abi64 >= 0) {
pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
}
// 同时有abi32 和abi64 的情况, 查询pkg的 use32bitAbi 确定其primaryCpuAbi
if (abi32 >= 0) {
final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
if (abi64 >= 0) {
// use32bitAbi , 则 primaryCpuAbi 为abi32 . secondaryCpuAbi为abi64
if (pkg.use32bitAbi) {
pkg.applicationInfo.secondaryCpuAbi = pkg.applicationInfo.primaryCpuAbi;
pkg.applicationInfo.primaryCpuAbi = abi;
} else {
// 否则 primaryCpuAbi 为abi64 . secondaryCpuAbi为abi32
pkg.applicationInfo.secondaryCpuAbi = abi;
}
} else {
// 只支持32. primaryCpuAbi为abi32
pkg.applicationInfo.primaryCpuAbi = abi;
}
}

} else {
// 单一指令集的情况
String[] abiList = (cpuAbiOverride != null) ?
new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;

// 编译优化相关. 暂不了解具体作用
// Renderscript compiler generates LLVM bitcode that is then shipped inside the application APK
boolean needsRenderScriptOverride = false;
if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
abiList = Build.SUPPORTED_32_BIT_ABIS;
needsRenderScriptOverride = true;
}

final int copyRet;
if (extractLibs) {
copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
} else {
copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
}

if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
"Error unpackaging native libs for app, errorCode=" + copyRet);
}

if (copyRet >= 0) {
// copyRet 中保存的是支持的abi集
pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
} else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) {
pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
} else if (needsRenderScriptOverride) {
pkg.applicationInfo.primaryCpuAbi = abiList[0];
}
}
} catch (IOException ioe) {
Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
} finally {
IoUtils.closeQuietly(handle);
}

if (pkg.applicationInfo.hasMultiArchLib == null&& pkg.applicationInfo.primaryCpuAbi != null && PRC_COMPATIBILITY) {
// 如果 hasMultiArchLib 为 null , primaryCpuAbi不为null ,则从apk中压缩文件中的lib相关目录判断是否是多指令集的
pkg.applicationInfo.hasMultiArchLib = String.valueOf(hasMultiArch(pkg.baseCodePath));
}

// Now that we've calculated the ABIs and determined if it's an internal app,
// we will go ahead and populate the nativeLibraryPath.
setNativeLibraryPaths(pkg);
}
1.1.1.4.4.15. 为shareUser统一调整指令集

处理原则如下

  • 当前包的指令集不为空, 当前包的requiredInstructionSet不为空, adjustedAbi 直接取当前包的 primaryCpuAbi, 更新shareUser所有包的 primaryCpuAbiString 为当前包的primaryCpuAbi, 删除primaryCpuAbi不一致的 shareUser 里对应包的dex文件
  • 当前包的指令集为空, 则赋值为 shareUser中第一个有指令集的包的架构集.同时更新shareUser所有包的 primaryCpuAbiString 为第一个包有架构集包的primaryCpuAbi, 删除primaryCpuAbi不一致的 shareUser 里对应包的dex文件
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
if ((scanFlags & SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
// We don't do this here during boot because we can do it all
// at once after scanning all existing packages.
//
// We also do this *before* we perform dexopt on this package, so that
// we can avoid redundant dexopts, and also to make sure we've got the
// code and package path correct.
// boot阶段不进行该操作, 为shareUser 调整abi
adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
pkg, true /* boot complete */);
}
// bootComplete 已经开机完成,true 表明不是在boot阶段
// scannedPackage 为当前扫描的 包,
// packagesForUser 同shareUser的包
private void adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
PackageParser.Package scannedPackage, boolean bootComplete) {

String requiredInstructionSet = null;
// 以当前包为基准, 找 primaryCpuAbi 值,为需要的架构集 保存到requiredInstructionSet
if (scannedPackage != null && scannedPackage.applicationInfo.primaryCpuAbi != null) {
requiredInstructionSet = VMRuntime.getInstructionSet(
scannedPackage.applicationInfo.primaryCpuAbi);
}

PackageSetting requirer = null;
for (PackageSetting ps : packagesForUser) {
// If packagesForUser contains scannedPackage, we skip it. This will happen
// when scannedPackage is an update of an existing package. Without this check,
// we will never be able to change the ABI of any package belonging to a shared
// user, even if it's compatible with other packages.
// shareUser 中的包名为当前包时略过
if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) {
if (ps.primaryCpuAbiString == null) {
continue;
}

final String instructionSet = VMRuntime.getInstructionSet(ps.primaryCpuAbiString);
if (requiredInstructionSet != null && !instructionSet.equals(requiredInstructionSet)) {
// We have a mismatch between instruction sets (say arm vs arm64) warn about
// this but there's not much we can do.
// 如果shareUser中其他包和当前包的需要的架构集不一致,打出log
String errorMessage = "Instruction set mismatch, "
+ ((requirer == null) ? "[caller]" : requirer)
+ " requires " + requiredInstructionSet + " whereas " + ps
+ " requires " + instructionSet;
Slog.w(TAG, errorMessage);
}
// 如果当前包需要的架构集为空,则赋值为 shareUser中其他包的需要的架构集
if (requiredInstructionSet == null) {
requiredInstructionSet = instructionSet;
requirer = ps;
}
}
}

if (requiredInstructionSet != null) {
String adjustedAbi;
if (requirer != null) {
// requirer != null implies that either scannedPackage was null or that scannedPackage
// did not require an ABI, in which case we have to adjust scannedPackage to match
// the ABI of the set (which is the same as requirer's ABI)
// 此时只对应当前包所需架构集为空,但shareUser中其他包 架构集不为空的情况, 该中情况下,更新当前包的 primaryCpuAbi 为 shareUser中对应包的架构集
adjustedAbi = requirer.primaryCpuAbiString;
if (scannedPackage != null) {
scannedPackage.applicationInfo.primaryCpuAbi = adjustedAbi;
}
} else {
// requirer == null implies that we're updating all ABIs in the set to
// match scannedPackage.
// 当前包的requiredInstructionSet不为空, adjustedAbi 直接取当前包的 primaryCpuAbi
adjustedAbi = scannedPackage.applicationInfo.primaryCpuAbi;
}

for (PackageSetting ps : packagesForUser) {
if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) {
if (ps.primaryCpuAbiString != null) {
continue;
}
// 更新shareUser所有包的 primaryCpuAbiString 为当前包的primaryCpuAbi
ps.primaryCpuAbiString = adjustedAbi;
if (ps.pkg != null && ps.pkg.applicationInfo != null &&
!TextUtils.equals(adjustedAbi, ps.pkg.applicationInfo.primaryCpuAbi)) {
ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi;
Slog.i(TAG, "Adjusting ABI for " + ps.name + " to " + adjustedAbi
+ " (requirer="
+ (requirer == null ? "null" : requirer.pkg.packageName)
+ ", scannedPackage="
+ (scannedPackage != null ? scannedPackage.packageName : "null")
+ ")");
try {
// 删除primaryCpuAbi不一致的 shareUser 里对应包的dex文件
mInstaller.rmdex(ps.codePathString,
getDexCodeInstructionSet(getPreferredInstructionSet()));
} catch (InstallerException ignored) {
}
}
}
}
}
}
1.1.1.4.4.16. 扫描模式未设置SCAN_NO_DEX标志

当扫描模式未设置此标志时,调用performDexOptLI方法对该包强制进行dexopt。根据参数值,会进行dexopt优化,或者跳过/推后,如果优化失败,输出Log信息,跳过后续步骤。并且如果设置了失败删除数据目录标志,也会删除数据目录和data/app-lib目录。

1.1.1.4.4.17. 只有特权包或者更新的特权包才有权添加子包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Only privileged apps and updated privileged apps can add child packages.
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);
}
}
}
1.1.1.4.4.18. 系统级应用向共享库中添加库

应用为升级包, 查找该包是否在系统禁用包中

  • 如果该包在更新前在系统禁用包中, 则对当前的shareLib单项进行判断是否匹配旧包的lib项匹配才允许加到共享库中
  • 如果该包不在系统禁用包中, 则其对应的库不允许添加到共享库中

对于系统级应用,如果library标签中声明的库信息不存在于PackageManagerService.mSharedLibraries中且被允许添加的情况下,往mSharedLibraries添加该库信息.

为其他应用更新共享库信息

  • 判定当前是不是在启动扫描阶段,如果不在启动扫描阶段,为已安装且涉及到当前扫描到的该应用的库的其它应用更新共享库路径信息(即用最新的路径信息,最新的包);
  • 对于启动扫描阶段,在扫描完成后统一更新。

不是在启动扫描阶段,由于需要为已安装且涉及到当前扫描到该应用的库的其它应用更新共享库路径信息,所以需要将这些应用杀死.

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
// writer
synchronized (mPackages) {
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
// Only system apps can add new shared libraries.
if (pkg.libraryNames != null) {
for (int i=0; i<pkg.libraryNames.size(); i++) {
String name = pkg.libraryNames.get(i);
boolean allowed = false;
if (pkg.isUpdatedSystemApp()) {
// 如果是package更新的场景,查找该包是否在系统禁用包中.如果该包在更新前在系统禁用包中,
// 则对当前的shareLib单项进行判断是否匹配旧包的lib项.匹配才允许加到共享库中
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;
}
}
}
// 没在系统禁用包中,或者lib项不匹配,allowed为false
} else {
allowed = true;
}
if (allowed) {
if (!mSharedLibraries.containsKey(name)) {
mSharedLibraries.put(name, new SharedLibraryEntry(null, pkg.packageName));
} else if (!name.equals(pkg.packageName)) {
Slog.w(TAG, "Package " + pkg.packageName + " library "
+ name + " already exists; skipping");
}
} else {
Slog.w(TAG, "Package " + pkg.packageName + " declares lib "
+ name + " that is not declared on system image; skipping");
}
}
if ((scanFlags & SCAN_BOOTING) == 0) {
// If we are not booting, we need to update any applications
// that are clients of our shared library. If we are booting,
// this will all be done once the scan is complete.
clientLibPkgs = updateAllSharedLibrariesLPw(pkg);
}
}
}
}
// Also need to kill any apps that are dependent on the library.
if (clientLibPkgs != null) {
for (int i=0; i<clientLibPkgs.size(); i++) {
PackageParser.Package clientPkg = clientLibPkgs.get(i);
// 杀死这些关联到该共享库的应用
killApplication(clientPkg.applicationInfo.packageName,
clientPkg.applicationInfo.uid, "update lib");
}
}
1.1.1.4.4.19. 保存当前扫描的包和包信息

将当前包信息和包(保持信息一致性)分别存入mSettings.mPackages和PackageManagerService.mPackages中。

并从mSettings.mPackagesToBeCleaned(保存已卸载并且清除外部数据的包名)移除当前包信息,防止误删。

1
2
3
4
5
6
7
8
9
10
11
12
// Add the new setting to mSettings
mSettings.insertPackageSettingLPw(pkgSetting, pkg);
// Add the new setting to mPackages
mPackages.put(pkg.applicationInfo.packageName, pkg);
// Make sure we don't accidentally delete its data.
final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
while (iter.hasNext()) {
PackageCleanItem item = iter.next();
if (pkgName.equals(item.packageName)) {
iter.remove();
}
}
1.1.1.4.4.20. 更新第一次安装/升级时间以及密钥信息

根据传来的扫描时间或者在创建数据目录时获取到的时间戳,更新包信息第一次安装pkgSetting.firstInstallTime或者升级的时间pkgSetting.lastUpdataTime。

接下来,将AndroidManifest.xml解析到的密钥信息更新到mSettings.mKeySetManager结构中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Take care of first install / last update times.
if (currentTime != 0) {
if (pkgSetting.firstInstallTime == 0) {
pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
} else if ((scanFlags&SCAN_UPDATE_TIME) != 0) {
pkgSetting.lastUpdateTime = currentTime;
}
} else if (pkgSetting.firstInstallTime == 0) {
// We need *something*. Take time time stamp of the file.
pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
} else if ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
if (scanFileTime != pkgSetting.timeStamp) {
// A package on the system image has changed; consider this
// to be an update.
pkgSetting.lastUpdateTime = scanFileTime;
}

// Add the package's KeySets to the global KeySetManagerService
ksms.addScannedPackageLPw(pkg);
1.1.1.4.4.21. 遍历并保存各组件信息

遍历在AndroidManifest.xml中解析到的各组件信息,并保存到PackageManagerService相应成员中。

  • 遍历pkg.providers

遍历pkg.providers,将其中的各个Provider类型的元素添加到ProviderIntentResolver类型的PackageMamangerService.mProviders的成员变量ProviderIntentResolver.mProviders(HashMap<ComponentName,Provider类型>)中。并根据成员值authority,将元素添加到PackageManagerService.mProvidersByAuthority

  • 遍历pkg.services

遍历pkg.services,将其中的各个Service类型的元素添加到ServiceIntentResolver类型的PackageMamangerService.mServices的成员变量ServiceIntentResolver.mServices(HashMap<ComponentName, Service >类型)中。

  • 遍历pkg.receivers

遍历pkg. receivers,将其中的各个Activity类型的元素添加到ActivityIntentResolver类型的PackageMamangerService.mReceivers的成员变量ActivityIntentResolver.mActivitys(HashMap<ComponentName, Activity>类型)中。

  • 遍历pkg.activities

遍历pkg.activities,将其中的各个Activity类型的元素添加到ActivityIntentResolver类型的PackageMamangerService.mActivitys的成员变量ActivityIntentResolver.mActivitys(HashMap<ComponentName, Activity>类型)中。

  • 遍历pkg.permissionGroups

遍历pkg.permissionGroups,将其中的各个PermissionGroup类型的元素添加到PackageMamangerService.mPermissionGroups(HashMap<String, permissionGroup>类型)中。

  • 遍历pkg.permissions

遍历pkg.permissions,根据PackageMamangerService.mPermissionGroups,以及mSettings.mPermissions/mSettings.mPermissionTrees中是否包含该Permission类型元素p的权限名p.info.name,将BasePermission类型元素(根据p更新其中的成员)添加到mSettings.mPermissions/mSettings.mPermissionTrees中。

  • 遍历pkg.instrumentation

遍历pkg.instrumentation,根据pkg数据信息更新Instrumentation类型元素,并将该元素添加到PackageManagerService.mInstrumentation中(HashMap<ComponentName,Instrumentation>类型)

  • 遍历pkg.protectedBroadcasts

遍历pkg.protectedBroadcasts,将元素添加到PackageManagerService.mProtectedBroadcasts中。

各组件的组成结构

1.1.1.4.4.22. 处理overlay资源

这个是在解析parseBaseApkCommon函数解析manifest节点时得到的. TAG_OVERLAY(overlay)标签

1
pkg.mOverlayTarget = com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage

mOverLays中以 pkg.mOverlayTarget为key, 保存 本package的ArrayMap

其中Arraymap 中以本package的包名为key,存放了本包的package对象

如果能够在 mPackages 找到本pakcage的 mOverlayTarget包, 则要为 target 包 和 本包创建idmap
在package的 mOverlayTarget为空的情况下, 如果能够在mOverlays找到本包名为key的ArrayMap, 则说明本包存在关联的target包,同样为本包和target包创建idmap

idmap相关知识

1.1.1.4.4.23. 小结

上述过程结束后,scanPackageDirtyLI函数结束, 返回PackageParser.Package 对象,在这个过程中,将PackageParser.Package 的一些值保存到PackageManagerService的全局变量中,详见保存各组件信息

scanPackageDirtyLi函数结束后,上面的调用栈整个返回,进行下一步的操作