Skytoby

PKMS相关类分析

PKMS相关类分析

1.Settings类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Settins文件 data/system/packages.xml
private final File mSettingsFilename;

//这个文件不一定存在,是备份文件,如果存在则说明更新packages.xml出错
//data/system/packages_backup.xml
private final File mBackupSettingsFilename;

//data/system/packages.list
private final File mPackageListFilename;

// key是包名,PackageSetting主要包含app的基本信息,如安装位置,lib位置等
/** Map from package name to settings */
final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();

/*key是类似“android.ui.system”这样的字段,在Android中每个应用都有一个UID,两个相同的UID的应用可以运行在/一个进程中,为了让两个应用运行在一个进程中,需要在manifest中设置sharedUserId这个属性,这个属性是字符串,但是在linux系统中uid是一个整型,因此就有了SharedUserSetting类型,这个类型除了name还有uid(对应linux中的uid),还有一个列表字段,用于记录系统中相同shardUserId的应用。*/
final ArrayMap<String, SharedUserSetting> mSharedUsers =
new ArrayMap<String, SharedUserSetting>();

/*主要保存的是/system/etc/permissions/platform.xml中的permission标签内容,因为Android系统是基于linux的系统,有用户组的概念,platform定义了一些权限,并且定制了哪些用户组具有哪些权限,一旦应用属于某个用户组,那么它就有这个用户组的所有权限*/
final PermissionSettings mPermissions;

1.1 Setting构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Settings(File dataDir, PermissionSettings permission, Object lock) {
mLock = lock;
mPermissions = permission;
//创建mRuntimePermissionsPersistence,是Setting内部类
mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);

//初始化文件路径
mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();
FileUtils.setPermissions(mSystemDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
mSettingsFilename = new File(mSystemDir, "packages.xml");
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
mPackageListFilename = new File(mSystemDir, "packages.list");
FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);

final File kernelDir = new File("/config/sdcardfs");
mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;

//下面两个文件路径不推荐使用
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}

Setting构造函数主要工作是创建系统文件夹,一些包管理的文件

packages.xml、packages-backup.xml是一组,用于描述系统所安装的Package信息,其中packages-backup.xml是packages.xml的备份

packages.list用于描述系统中存在的所有非系统自带的apk信息以及UID大于10000的apk。当APK有变化时,PKMS就会更新该文件。

1.2 addSharedUserLPw方法

该方法将shareUserId name和一个int类型的UID对应起来。UID的定义在Process.java中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
//获取SharedUserSetting对象
SharedUserSetting s = mSharedUsers.get(name);
if (s != null) {
if (s.userId == uid) {
return s;
}
PackageManagerService.reportSettingsProblem(Log.ERROR,
"Adding duplicate shared user, keeping first: " + name);
return null;
}
//没有在mSharedUsers找到则新建,并保存起来
s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
s.userId = uid;
if (addUserIdLPw(uid, s, name)) {
mSharedUsers.put(name, s);
return s;
}
return 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
43
44
45
46
47
48
/**
* Defines the root UID.
*/
public static final int ROOT_UID = 0;

/**
* Defines the UID/GID under which system code runs.
*/
public static final int SYSTEM_UID = 1000;

/**
* Defines the UID/GID under which the telephony code runs.
*/
public static final int PHONE_UID = 1001;

/**
* Defines the UID/GID for the user shell.
*/
public static final int SHELL_UID = 2000;

/**
* Defines the UID/GID for the log group.
* @hide
*/
@UnsupportedAppUsage
public static final int LOG_UID = 1007;

/**
* Defines the UID/GID for the WIFI supplicant process.
* @hide
*/
@UnsupportedAppUsage
public static final int WIFI_UID = 1010;
...

//第一个应用package的起始UID为10000
/**
* Defines the start of a range of UIDs (and GIDs), going from this
* number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
* to applications.
*/
public static final int FIRST_APPLICATION_UID = 10000;
//最后一个应用package的UID为19999
/**
* Last of application-specific UIDs starting at
* {@link #FIRST_APPLICATION_UID}.
*/
public static final int LAST_APPLICATION_UID = 19999;

Setting模块的AndroidManifest.xml里面,如下所示:

1
2
3
4
5
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.settings"
coreApp="true"
android:sharedUserId="android.uid.system">

在xml里面android:sharedUserId属性设置为”android.uid.system”。sharedUserId这个属性主要有两个作用:

1.两个或者多个声明了同一种sharedUserId的应用可以共享彼此的数据

2.通过声明特定sharedUserId,该应用所在进程将赋予指定的UID。如Setting声明了system的uid,则就可以共享system用户所对应的权限。

除了了xml了声明sharedUserId外,应用编译的时候还必须使用对应的证书进行签名。如Setting需要platform的签名。

1.3 PID、UID、GID的区别

PID是进程的身份识别,程序一旦运行,就会给应用分配唯一的PID。一个应用可能包含多个进程,每个进程有唯一的一个PID。进程终止后PID被系统回收,再次打开应用,会分配一个PID(新进程的PID一般比之前的号大)。

调用adb shell ps可以查看系统运行的进程。

UID是用户ID。UID在linux中就是用户ID,表明哪个用户运行了这个程序,主要用于权限的管理。而Android为单用户系统,这时候UID被赋予了新的使命,数据共享,为了实现数据共享,android为每个应用都分配了不同的uid,不像传统的linux,每个用户相同就为之分配相同的UID。

GID时用户组ID。对于普通的应用程序来说GID等于UID,由于每个应用程序的UID和GID不相同,所以不管是native还是java层都能够达到保护私有数据的作用。

adb shell cat /proc/PID号/status

SharedUserSetting类架构

PKMS的构造函数创建一个Settings的实例mSettings,mSettings有三个成员变量mSharedUsers,mUserIds,mOtherUserIds。addSharedUserLPw方法都涉及这三个成员变量。SharedUserSetting的成员变量packages是一个PackageSetting类型的ArraySet。PackageSetting继承自PackageSettingBase,PackageSetting保存着package的多种信息。

2.SystemConfig类

2.1 SystemConfig构造函数

主要读取下面路径的配置

/system/etc/、/system/etc/、/vendor/etc、/odm/etc、/oem/etc、/product/etc 目录下sysconfig和permissions

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
SystemConfig() {
// Read configuration from system
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);

// Read configuration from the old permissions dir
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);

// Vendors are only allowed to customze libs, features and privapp permissions
int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS;
if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
// For backward compatibility
vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
}
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);

// Allow ODM to customize system configs as much as Vendor, because /odm is another
// vendor partition other than /vendor.
int odmPermissionFlag = vendorPermissionFlag;
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);

String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
if (!skuProperty.isEmpty()) {
String skuDir = "sku_" + skuProperty;

readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions", skuDir),
odmPermissionFlag);
}

// Allow OEM to customize features and OEM permissions
int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS;
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);

// Allow Product to customize all system configs
readPermissions(Environment.buildPath(
Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
readPermissions(Environment.buildPath(
Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
}

SystemConfig构造函数中主要通过readPermissions函数将对应目录下的xml文件中定义的各个节点读取出来保存到SystemConfig成员变量中。在终端的/system/etc/permissions目录下可以看到很多xml配置文件,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
HWSTF:/system/etc/permissions $ ls -all
total 300
drwxr-xr-x 2 root root 4096 2018-08-08 00:01:00.000000000 +0800 .
drwxr-xr-x 26 root root 4096 2018-08-08 00:01:00.000000000 +0800 ..
-rw-r--r-- 1 root root 1515 2018-08-08 00:01:00.000000000 +0800 HiViewTunnel-core.xml
-rw-r--r-- 1 root root 830 2018-08-08 00:01:00.000000000 +0800 android.hardware.bluetooth_le.xml
-rw-r--r-- 1 root root 927 2018-08-08 00:01:00.000000000 +0800 android.hardware.faketouch.xml
-rw-r--r-- 1 root root 834 2018-08-08 00:01:00.000000000 +0800 android.hardware.fingerprint.xml
-rw-r--r-- 1 root root 942 2018-08-08 00:01:00.000000000 +0800 android.hardware.location.gps.xml
-rw-r--r-- 1 root root 949 2018-08-08 00:01:00.000000000 +0800 android.hardware.location.xml
-rw-r--r-- 1 root root 888 2018-08-08 00:01:00.000000000 +0800 android.hardware.nfc.hce.xml
-rw-r--r-- 1 root root 891 2018-08-08 00:01:00.000000000 +0800 android.hardware.nfc.hcef.xml
-rw-r--r-- 1 root root 921 2018-08-08 00:01:00.000000000 +0800 android.hardware.nfc.xml
-rw-r--r-- 1 root root 870 2018-08-08 00:01:00.000000000 +0800 android.hardware.opengles.aep.xml
-rw-r--r-- 1 root root 824 2018-08-08 00:01:00.000000000 +0800
...

这些配置文件都是编译时从framework指定位置拷贝过来的(framework/native/data/etc),下面是platform.xml里面的部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<permissions>

<permission name="android.permission.BLUETOOTH_ADMIN" >
<group gid="net_bt_admin" />
</permission>
<permission name="android.permission.READ_EXTERNAL_STORAGE" />
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
<library name="org.apache.http.legacy"
file="/system/framework/org.apache.http.legacy.boot.jar" />
<allow-in-power-save package="com.android.providers.downloads" />
<!-- These are the packages that shouldn't run as system user -->
<system-user-blacklisted-app package="com.android.wallpaper.livepicker" />
<allow-in-data-usage-save package="com.dti.att" />
<feature name="android.hardware.vulkan.level" version="0" />
...
</permissions>

readPermissions方法内部调用readPermissionsFromXml方法来解析xml里面的各个节点,其中xml涉及到的标签内容有permission、assign-permission、library、feature等,这些标签的内容解析出来保存到SystemConfig的对应数据结构的全局变量中,以便管理查询。

feature用来描述设备是否支持硬件特性; library用于指定系统库,当应用程序运行时,系统会为进城加载一些必须的库; assign-permission将system中描述的permission与uid关联; permission将permission和gid关联。

总结下SystemConfig初始化时解析xml文件节点以及对应的全局变量。

3. PackageParser

这个类作用是解析APK,在其类中注释如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* Parser for package files (APKs) on disk. This supports apps packaged either
* as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
* APKs in a single directory.
* <p>
* Apps packaged as multiple APKs always consist of a single "base" APK (with a
* {@code null} split name) and zero or more "split" APKs (with unique split
* names). Any subset of those split APKs are a valid install, as long as the
* following constraints are met:
* <ul>
* <li>All APKs must have the exact same package name, version code, and signing
* certificates.
* <li>All APKs must have unique split names.
* <li>All installations must contain a single base APK.
* </ul>
*
* @hide
*/

这个类主要用于解析apk安装包,它能解析单一apk文件,也能够解析multiple APKs(一个apk文件里面包含多个apk文件)。这些multiple APKs需要满足下面几个条件:

1.所有的apk必须具有完全相同的软件包包名,版本代码和签名证书

2.所有的apk必须具有唯一的拆分名称

3.所有安装必须含有一个单一的apk

解析步骤

1.将apk解析成package

2.将package转化为packageinfo

类结构

里面有很多内部类和方法,下面讲介绍里面的主要内部类以及部分解析的方法

3.1 内部类

3.1.1 NewPermissionInfo

记录新的权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/** @hide */
public static class NewPermissionInfo {
//权限名称
@UnsupportedAppUsage
public final String name;
@UnsupportedAppUsage
//权限的开始版本号
public final int sdkVersion;
//文件的版本号,一般为0
public final int fileVersion;

public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
this.name = name;
this.sdkVersion = sdkVersion;
this.fileVersion = fileVersion;
}
}

3.1.2 SplitPermissionInfo

主要记录一个权限拆分为颗粒度更小的权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/** @hide */
public static class SplitPermissionInfo {
//表示旧的权限
public final String rootPerm;
表示旧的权限拆分为颗粒度更小的权限
//public final String[] newPerms;
表示在那个版本上拆分
//public final int targetSdk;

public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
this.rootPerm = rootPerm;
this.newPerms = newPerms;
this.targetSdk = targetSdk;
}
}

3.1.3 ParsePackageItemArgs

主要为解析包单个item的参数

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
static class ParsePackageItemArgs {
//表示安装包的包对象package
final Package owner;
//表示错误信息
final String[] outError;
//表示安装包中名字对应的资源id
final int nameRes;
//表示安装包中label对应的资源id
final int labelRes;
//表示安装包中icon对应的资源id
final int iconRes;
//表示安装包中roundIcon对应的资源id
final int roundIconRes;
//表示安装包中logo对应的资源id
final int logoRes;
//表示安装包中banner对应的资源id
final int bannerRes;

String tag;
TypedArray sa;

ParsePackageItemArgs(Package _owner, String[] _outError,
int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
int _bannerRes) {
owner = _owner;
outError = _outError;
nameRes = _nameRes;
labelRes = _labelRes;
iconRes = _iconRes;
logoRes = _logoRes;
bannerRes = _bannerRes;
roundIconRes = _roundIconRes;
}
}

3.1.4 ParseComponentArgs

主要为解析包中单个组件的参数

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
/** @hide */
@VisibleForTesting
public static class ParseComponentArgs extends ParsePackageItemArgs {
//表示该组件对应的进程,如果设置独立进程则表示为独立进程的名字
final String[] sepProcesses;
//表示组件对应的进程的资源id
final int processRes;
//表示组件对应的进程的描述id
final int descriptionRes;
//表示组件是否可用
final int enabledRes;
//表示该组件的标志位
int flags;

public ParseComponentArgs(Package _owner, String[] _outError,
int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
int _bannerRes,
String[] _sepProcesses, int _processRes,
int _descriptionRes, int _enabledRes) {
super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
_bannerRes);
sepProcesses = _sepProcesses;
processRes = _processRes;
descriptionRes = _descriptionRes;
enabledRes = _enabledRes;
}
}

3.1.5 PackageLite

表示在解析过程中的一个轻量级的独立的安装包

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
/**
* Lightweight parsed details about a single package.
*/
public static class PackageLite {
//表示包名
@UnsupportedAppUsage
public final String packageName;
//表示版本号
public final int versionCode;
//表示主版本号
public final int versionCodeMajor;
@UnsupportedAppUsage
//表示安装位置的属性,可以有几个常量的选择,比如PackageInfo.INSTALL_LOACTION_AUTO
public final int installLocation;
//表示验证对象
public final VerifierInfo[] verifiers;

//如果有拆包,则表示拆包的名字数组
/** Names of any split APKs, ordered by parsed splitName */
public final String[] splitNames;

//拆包是否有feature
/** Names of any split APKs that are features. Ordered by splitName */
public final boolean[] isFeatureSplits;

//拆包的uses和config
/** Dependencies of any split APKs, ordered by parsed splitName */
public final String[] usesSplitNames;
public final String[] configForSplit;

//表示代码的路径,单个apk对应的是base apk路径,集群apk则是集群apk的目录
/**
* Path where this package was found on disk. For monolithic packages
* this is path to single base APK file; for cluster packages this is
* path to the cluster directory.
*/
public final String codePath;
//base apk的路径
/** Path of base APK */
public final String baseCodePath;
//拆分apk的路径
/** Paths of any split APKs, ordered by parsed splitName */
public final String[] splitCodePaths;
//base apk的调整版本号
/** Revision code of base APK */
public final int baseRevisionCode;
//拆分apk的调整版本号
/** Revision codes of any split APKs, ordered by parsed splitName */
public final int[] splitRevisionCodes;
//是不是核心app
public final boolean coreApp;
//是不是debug
public final boolean debuggable;
//是不是支持多平台,主要是指cpu平台
public final boolean multiArch;
//是不是用32位的so库
public final boolean use32bitAbi;
//是否需要提取so库
public final boolean extractNativeLibs;
//拆分包是否是独立
public final boolean isolatedSplits;

public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
String[] splitCodePaths, int[] splitRevisionCodes) {
this.packageName = baseApk.packageName;
this.versionCode = baseApk.versionCode;
this.versionCodeMajor = baseApk.versionCodeMajor;
this.installLocation = baseApk.installLocation;
this.verifiers = baseApk.verifiers;
this.splitNames = splitNames;
this.isFeatureSplits = isFeatureSplits;
this.usesSplitNames = usesSplitNames;
this.configForSplit = configForSplit;
this.codePath = codePath;
this.baseCodePath = baseApk.codePath;
this.splitCodePaths = splitCodePaths;
this.baseRevisionCode = baseApk.revisionCode;
this.splitRevisionCodes = splitRevisionCodes;
this.coreApp = baseApk.coreApp;
this.debuggable = baseApk.debuggable;
this.multiArch = baseApk.multiArch;
this.use32bitAbi = baseApk.use32bitAbi;
this.extractNativeLibs = baseApk.extractNativeLibs;
this.isolatedSplits = baseApk.isolatedSplits;
}

3.1.6 ApkLite

表示解析过程中的一个轻量级独立的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
/**
* Lightweight parsed details about a single APK file.
*/
public static class ApkLite {
//表示代码的路径
public final String codePath;
//表示包名
public final String packageName;
//表示拆分的包名
public final String splitName;
//表示拆包是否有Feature
public boolean isFeatureSplit;
//表示拆包的配置
public final String configForSplit;
//表示拆包名字的uses
public final String usesSplitName;
//表示版本号
public final int versionCode;
//表示主版本号
public final int versionCodeMajor;
//表示调整的版本号
public final int revisionCode;
//表示安装位置的属性,可以有几个常量的选择,比如PackageInfo.INSTALL_LOACTION_AUTO
public final int installLocation;
//表示验证对象
public final VerifierInfo[] verifiers;
//表示签名对象
public final SigningDetails signingDetails;
//是不是核心app
public final boolean coreApp;
//是不是debug
public final boolean debuggable;
//是不是支持多平台,主要是指cpu平台
public final boolean multiArch;
//是不是用32位的so库
public final boolean use32bitAbi;
//是否需要提取so库
public final boolean extractNativeLibs;
//拆分包是否是独立
public final boolean isolatedSplits;

public ApkLite(String codePath, String packageName, String splitName,
boolean isFeatureSplit,
String configForSplit, String usesSplitName, int versionCode, int versionCodeMajor,
int revisionCode, int installLocation, List<VerifierInfo> verifiers,
SigningDetails signingDetails, boolean coreApp,
boolean debuggable, boolean multiArch, boolean use32bitAbi,
boolean extractNativeLibs, boolean isolatedSplits) {
this.codePath = codePath;
this.packageName = packageName;
this.splitName = splitName;
this.isFeatureSplit = isFeatureSplit;
this.configForSplit = configForSplit;
this.usesSplitName = usesSplitName;
this.versionCode = versionCode;
this.versionCodeMajor = versionCodeMajor;
this.revisionCode = revisionCode;
this.installLocation = installLocation;
this.signingDetails = signingDetails;
this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
this.coreApp = coreApp;
this.debuggable = debuggable;
this.multiArch = multiArch;
this.use32bitAbi = use32bitAbi;
this.extractNativeLibs = extractNativeLibs;
this.isolatedSplits = isolatedSplits;
}

备注:PackageLite和ApkLite代表不同的含义,前者是包,后者是指apk,一个包中可能包含多个apk

3.1.7 SplitNameComparator

表示类比较器,在拆包中排序用到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* Used to sort a set of APKs based on their split names, always placing the
* base APK (with {@code null} split name) first.
*/
private static class SplitNameComparator implements Comparator<String> {
@Override
public int compare(String lhs, String rhs) {
if (lhs == null) {
return -1;
} else if (rhs == null) {
return 1;
} else {
return lhs.compareTo(rhs);
}
}
}

3.1.8 Package

表示从磁盘上的apk文件解析出来的完整包,一个包由一个基础的apk和多个拆分的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
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
  /**
* Representation of a full package parsed from APK files on disk. A package
* consists of a single base APK, and zero or more split APKs.
*/
public final static class Package implements Parcelable {
//表示包名
@UnsupportedAppUsage
public String packageName;
//表示manifest中声明的包名
// The package name declared in the manifest as the package can be
// renamed, for example static shared libs use synthetic package names.
public String manifestPackageName;
//表示拆包的包名
/** Names of any split APKs, ordered by parsed splitName */
public String[] splitNames;

// TODO: work towards making these paths invariant
//对应一个volume的uid
public String volumeUuid;

/**
* Path where this package was found on disk. For monolithic packages
* this is path to single base APK file; for cluster packages this is
* path to the cluster directory.
*/
//表示代码路径
public String codePath;

/** Path of base APK */
//表示base APK路径
public String baseCodePath;
//表示拆分APK路径
/** Paths of any split APKs, ordered by parsed splitName */
public String[] splitCodePaths;
//表示base APK调整版本号
/** Revision code of base APK */
public int baseRevisionCode;
//表示拆分APK调整版本号
/** Revision codes of any split APKs, ordered by parsed splitName */
public int[] splitRevisionCodes;

//表示拆分APK的标注数组
/** Flags of any split APKs; ordered by parsed splitName */
public int[] splitFlags;

/**
* Private flags of any split APKs; ordered by parsed splitName.
*
* {@hide}
*/
//表示拆分APK的私有标注数组
public int[] splitPrivateFlags;
//表示是否支持硬件加速
public boolean baseHardwareAccelerated;

//对应application对象,对应AndroidManifest里面的<Application>
// For now we only support one application per package.
@UnsupportedAppUsage
public ApplicationInfo applicationInfo = new ApplicationInfo();

//apk安装包中,对应AndroidManifest里面的<Permission>
@UnsupportedAppUsage
public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
//apk安装包中,对应AndroidManifest里面的<PermissionGroup>
@UnsupportedAppUsage
public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
//apk安装包中,对应AndroidManifest里面的<Activity>
//不是通常说的Activity,而是PackageParse的内部类Activity
@UnsupportedAppUsage
public final ArrayList<Activity> activities = new ArrayList<Activity>(0);

//apk安装包中,对应AndroidManifest里面的<Receiver>
//不是通常说的Activity,而是PackageParse的内部类Activity
@UnsupportedAppUsage
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);

//apk安装包中,对应AndroidManifest里面的<Provider>
//不是通常说的Provider,而是PackageParse的内部类Provider
@UnsupportedAppUsage
public final ArrayList<Provider> providers = new ArrayList<Provider>(0);

//apk安装包中,对应AndroidManifest里面的<Service>
//不是通常说的Service,而是PackageParse的内部类Service
@UnsupportedAppUsage
public final ArrayList<Service> services = new ArrayList<Service>(0);

//apk安装包中,对应AndroidManifest里面的<Instrumentation>
//不是通常说的Instrumentation,而是内部类Instrumentation
@UnsupportedAppUsage
public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
//apk安装包中请求的权限
@UnsupportedAppUsage
public final ArrayList<String> requestedPermissions = new ArrayList<String>();

//apk安装包中保内广播的action
@UnsupportedAppUsage
public ArrayList<String> protectedBroadcasts;
//父包
public Package parentPackage;
//子包
public ArrayList<Package> childPackages;
//共享库名称
public String staticSharedLibName = null;
//共享库版本
public long staticSharedLibVersion = 0;
//依赖库名称
public ArrayList<String> libraryNames = null;
@UnsupportedAppUsage
//使用库名称
public ArrayList<String> usesLibraries = null;
//使用静态库名称
public ArrayList<String> usesStaticLibraries = null;
//使用静态库版本
public long[] usesStaticLibrariesVersions = null;
public String[][] usesStaticLibrariesCertDigests = null;
//使用其它的库
@UnsupportedAppUsage
public ArrayList<String> usesOptionalLibraries = null;
//使用静态库文件
@UnsupportedAppUsage
public String[] usesLibraryFiles = null;
//使用共享库信息
public ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
//安装包中某个Activity信息的集合 在AndroidManifest里面对应<preferred>标签
public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
//安装包中 AndroidManifest中对应original-package的集合
public ArrayList<String> mOriginalPackages = null;
//真实包名,通常和mOriginalPackages一起使用
public String mRealPackage = null;
//APK安装包 AndroidManifest中对应adopt-permissions的集合
public ArrayList<String> mAdoptPermissions = null;
//独立的存储应用程序元数据,避免多个不需要的引用
// We store the application meta-data independently to avoid multiple unwanted references
@UnsupportedAppUsage
public Bundle mAppMetaData = null;
//版本号
// The version code declared for this package.
@UnsupportedAppUsage
public int mVersionCode;
//主版本号
// The major version code declared for this package.
public int mVersionCodeMajor;
//长版本号
// Return long containing mVersionCode and mVersionCodeMajor.
public long getLongVersionCode() {
return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
}
//版本名
// The version name declared for this package.
@UnsupportedAppUsage
public String mVersionName;
//共享用户Id
// The shared user id that this package wants to use.
@UnsupportedAppUsage
public String mSharedUserId;
//共享用户标签
// The shared user label that this package wants to use.
@UnsupportedAppUsage
public int mSharedUserLabel;
//签名
// Signatures that were read from the package.
@UnsupportedAppUsage
@NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
//dexopt的位置,以便pkms跟踪执行dexopt的位置
// For use by package manager service for quick lookup of
// preferred up order.
@UnsupportedAppUsage
public int mPreferredOrder = 0;
//最后一次使用package的时间
// 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.
@UnsupportedAppUsage
public Object mExtras;

//硬件配置信息,对应AndroidManifest里面的<users-configuration>标签
// Applications hardware preferences
@UnsupportedAppUsage
public ArrayList<ConfigurationInfo> configPreferences = null;
//特性组信息,对应AndroidManifest里面的<uses-feature>标签
// Applications requested features
@UnsupportedAppUsage
public ArrayList<FeatureInfo> reqFeatures = null;
//特性组信息,对应AndroidManifest里面的<feature-group>标签
// Applications requested feature groups
public ArrayList<FeatureGroupInfo> featureGroups = null;

//安装的属性
@UnsupportedAppUsage
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;

//对应AndroidManifest里面的<overlay>标签
public String mOverlayTarget;
//overlay类别
public String mOverlayCategory;
//overlay优先等级
public int mOverlayPriority;
//是否是静态overlay
public boolean mOverlayIsStatic;
//编译sdk版本
public int mCompileSdkVersion;
//编译sdk版本名称
public String mCompileSdkVersionCodename;

//下面用来给KeySetManagerService的数据
/**
* Data used to feed the KeySetManagerService
*/
@UnsupportedAppUsage
public ArraySet<String> mUpgradeKeySets; //升级
@UnsupportedAppUsage
public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping; //公钥

//有abi的话覆盖
/**
* The install time abi override for this package, if any.
*
* TODO: This seems like a horrible place to put the abiOverride because
* this isn't something the packageParser parsers. However, this fits in with
* the rest of the PackageManager where package scanning randomly pushes
* and prods fields out of {@code this.applicationInfo}.
*/
public String cpuAbiOverride;
//是否用32位的abi
/**
* The install time abi override to choose 32bit abi's when multiple abi's
* are present. This is only meaningfull for multiarch applications.
* The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
*/
public boolean use32bitAbi;
//限制升级hash
public byte[] restrictUpdateHash;
//是否对InstantApps可见
/** Set if the app or any of its components are visible to instant applications. */
public boolean visibleToInstantApps;
//是否是备份
/** Whether or not the package is a stub and must be replaced by the full version. */
public boolean isStub;

@UnsupportedAppUsage
public Package(String packageName) {
this.packageName = packageName;
this.manifestPackageName = packageName;
applicationInfo.packageName = packageName;
applicationInfo.uid = -1;
}
...
}

3.1.9 Component

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
  public static abstract class IntentInfo extends IntentFilter {
//是否有默认
@UnsupportedAppUsage
public boolean hasDefault;
//标签的资源id
@UnsupportedAppUsage
public int labelRes;
//本地化的标签
@UnsupportedAppUsage
public CharSequence nonLocalizedLabel;
//icon的资源id
@UnsupportedAppUsage
public int icon;
//logo的资源id
@UnsupportedAppUsage
public int logo;
//banner的资源id
@UnsupportedAppUsage
public int banner;
//preferred的资源id
public int preferred;
...
}

public static abstract class Component<II extends IntentInfo> {
//该组件所包含的IntentFilter
@UnsupportedAppUsage
public final ArrayList<II> intents;
//该组件的类名
@UnsupportedAppUsage
public final String className;
//该组件的元数据
@UnsupportedAppUsage
public Bundle metaData;
//该组件的类名
@UnsupportedAppUsage
//包含该组件的包名
public Package owner;
/** The order of this component in relation to its peers */
public int order;
//该组件名
ComponentName componentName;
//组件短名
String componentShortName;
...
}

3.1.10 Permission

继承于Component,对应AndroidManifest里面的标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public final static class Permission extends Component<IntentInfo> implements Parcelable {
//权限信息
@UnsupportedAppUsage
public final PermissionInfo info;
//是否权限树
@UnsupportedAppUsage
public boolean tree;
//对应的权限组
@UnsupportedAppUsage
public PermissionGroup group;

public Permission(Package _owner) {
super(_owner);
info = new PermissionInfo();
}
...
}

继承于Component,对应AndroidManifest里面的标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
@UnsupportedAppUsage
public final ActivityInfo info;
private boolean mHasMaxAspectRatio;

private boolean hasMaxAspectRatio() {
return mHasMaxAspectRatio;
}

public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
super(args, _info);
info = _info;
info.applicationInfo = args.owner.applicationInfo;
}

public void setPackageName(String packageName) {
super.setPackageName(packageName);
info.packageName = packageName;
}
...
}

一些其他的基本类似类在这里就不再详细的介绍,下面看下类里面的一些方法:

3.2 内部方法

里面的方法基本上是和解析相关的方法,这里以parseActivity为例说明,其他的解析大同小异。

3.2.1 parsePackage

这个类是解析package最开始的方法,其他的解析方法都是从这个入口进入的,这里分为两种解析,一种是single APK ,另一种是cluster APKs。

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
/**
* Parse the package at the given location. Automatically detects if the
* package is a monolithic style (single APK file) or cluster style
* (directory of APKs).
* <p>
* This performs sanity checking on cluster style packages, such as
* requiring identical package name and version codes, a single base APK,
* and unique split names.
* <p>
* Note that this <em>does not</em> perform signature verification; that
* must be done separately in {@link #collectCertificates(Package, int)}.
*
* If {@code useCaches} is true, the package parser might return a cached
* result from a previous parse of the same {@code packageFile} with the same
* {@code flags}. Note that this method does not check whether {@code packageFile}
* has changed since the last parse, it's up to callers to do so.
*
* @see #parsePackageLite(File, int)
*/
@UnsupportedAppUsage
public Package parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParserException {
Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
if (parsed != null) {
return parsed;
}

long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
//Cluster app
if (packageFile.isDirectory()) {
parsed = parseClusterPackage(packageFile, flags);
} else {
parsed = parseMonolithicPackage(packageFile, flags);
}

long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
cacheResult(packageFile, flags, parsed);
if (LOG_PARSE_TIMINGS) {
parseTime = cacheTime - parseTime;
cacheTime = SystemClock.uptimeMillis() - cacheTime;
if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
+ "ms, update_cache=" + cacheTime + " ms");
}
}
return parsed;
}

3.2.2 parseActivity

这个方法主要是解析AndroidManifest中activity标签的内容,并将其保存到PackageParser.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
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
private Activity parseActivity(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
boolean receiver, boolean hardwareAccelerated)
throws XmlPullParserException, IOException {
//获取资源数组
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
//初始化解析Activity参数
if (cachedArgs.mActivityArgs == null) {
cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
R.styleable.AndroidManifestActivity_name,
R.styleable.AndroidManifestActivity_label,
R.styleable.AndroidManifestActivity_icon,
R.styleable.AndroidManifestActivity_roundIcon,
R.styleable.AndroidManifestActivity_logo,
R.styleable.AndroidManifestActivity_banner,
mSeparateProcesses,
R.styleable.AndroidManifestActivity_process,
R.styleable.AndroidManifestActivity_description,
R.styleable.AndroidManifestActivity_enabled);
}
//判断是receiver还是activity
cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
cachedArgs.mActivityArgs.sa = sa;
cachedArgs.mActivityArgs.flags = flags;
//创建Activity类,是ParserPackage内部类
Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
if (outError[0] != null) {
sa.recycle();
return null;
}
//是否在AndroidManifest里面设置exported属性
boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
if (setExported) {
a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
}
//获取AndroidManifest里面对应的theme的值
a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
//获取AndroidManifest里面对应的uiOptions的值
a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
a.info.applicationInfo.uiOptions);
//获取AndroidManifest里面对应的parentActivityName的值
String parentName = sa.getNonConfigurationString(
R.styleable.AndroidManifestActivity_parentActivityName,
Configuration.NATIVE_CONFIG_VERSION);
//如果设置了
if (parentName != null) {
//构建parent的标签
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;
}
}
//获取权限permission
String str;
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;
}

//获取AndroidManifest里面对应的taskAffinity的值
str = sa.getNonConfigurationString(
R.styleable.AndroidManifestActivity_taskAffinity,
Configuration.NATIVE_CONFIG_VERSION);
a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
owner.applicationInfo.taskAffinity, str, outError);

//获取AndroidManifest里面对应的splitName的值
a.info.splitName =
sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);

//是否在AndroidManifest里面的Activity配置了multiprocesss属性
a.info.flags = 0;
if (sa.getBoolean(
R.styleable.AndroidManifestActivity_multiprocess, false)) {
a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
}
//是否在AndroidManifest里面的Activity配置了finishOnTaskLaunch属性
//用来标示用户再次启动任务时,是否应该关闭现有的Activity
if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
}
//是否在AndroidManifest里面的Activity配置了clearTaskOnLaunch属性
//用来标示当前应用从主屏幕重新启动时是否都从中移除根activity之外的其他activity
if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
}
//是否在AndroidManifest里面的Activity配置了noHistory属性
//用来标示当前用户离开activity时,是否从activity堆栈中移除
if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
}
//是否在AndroidManifest里面的Activity配置了alwaysRetainTaskState属性
//用来标示当是否保持activity所在的任务状态
if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
}
//是否在AndroidManifest里面的Activity配置了stateNotNeeded属性
//用来标示是否不保存activity状态的情况下将其终止并成功重启
if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
}
//是否在AndroidManifest里面的Activity配置了excludeFromRecents属性
//用来标示activity启动任务在最近使用的应用列表之外
if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
}
//是否在AndroidManifest里面的Activity配置了allowTaskReparenting属性
//用来标示这个应用是否在reset task时,关联对应的taskAffinity
if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
(owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
}
//是否在AndroidManifest里面的Activity配置了finishOnCloseSystemDialogs属性
//用来标示在关闭系统窗口时,是否销毁activity
if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
}
//是否在AndroidManifest里面的Activity配置了showForAllUsers属性
//用来指定该activity是否显示在解锁界面
if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
|| sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
}
//是否在AndroidManifest里面的Activity配置了immersive属性
//是否设置沉浸式显示
if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
}
//是否在AndroidManifest里面的Activity配置了systemUserOnly属性
//是否设置为系统组件
if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
}

//不是receiver标签
if (!receiver) {
if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
hardwareAccelerated)) {
a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
}
//设置对应的启动模式,对应的launchMode
a.info.launchMode = sa.getInt(
R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
//设置对应的启动模式,对应的documentLaunchMode
//一下也是获取一序列的属性,在此不再注解
a.info.documentLaunchMode = sa.getInt(
R.styleable.AndroidManifestActivity_documentLaunchMode,
ActivityInfo.DOCUMENT_LAUNCH_NONE);
a.info.maxRecents = sa.getInt(
R.styleable.AndroidManifestActivity_maxRecents,
ActivityManager.getDefaultAppRecentsLimitStatic());
a.info.configChanges = getActivityConfigChanges(
sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
a.info.softInputMode = sa.getInt(
R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);

a.info.persistableMode = sa.getInteger(
R.styleable.AndroidManifestActivity_persistableMode,
ActivityInfo.PERSIST_ROOT_ONLY);

if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
}

if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
}

if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
}

if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
}

a.info.screenOrientation = sa.getInt(
R.styleable.AndroidManifestActivity_screenOrientation,
SCREEN_ORIENTATION_UNSPECIFIED);

setActivityResizeMode(a.info, sa, owner);

if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
false)) {
a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
}

if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
}

if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
&& sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
== TypedValue.TYPE_FLOAT) {
a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
0 /*default*/));
}

a.info.lockTaskLaunchMode =
sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);

a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
R.styleable.AndroidManifestActivity_directBootAware,
false);

a.info.requestedVrComponent =
sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);

a.info.rotationAnimation =
sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);

a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
ActivityInfo.COLOR_MODE_DEFAULT);

if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
}

if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
}

} else {
//是receiver
a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
a.info.configChanges = 0;

if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
}

a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
R.styleable.AndroidManifestActivity_directBootAware,
false);
}

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

// can't make this final; we may set it later via meta-data
boolean visibleToEphemeral =
sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
if (visibleToEphemeral) {
a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
owner.visibleToInstantApps = true;
}

sa.recycle();

if (receiver && (owner.applicationInfo.privateFlags
&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
// A heavy-weight application can not have receives in its main process
// We can do direct compare because we intern all strings.
if (a.info.processName == owner.packageName) {
outError[0] = "Heavy-weight applications can not have receivers in main process";
}
}

if (outError[0] != null) {
return null;
}

int outerDepth = parser.getDepth();
int type;
//开始解析<activity>内部标签
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG
|| parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
//intent-filter标签
if (parser.getName().equals("intent-filter")) {
ActivityIntentInfo intent = new ActivityIntentInfo(a);
if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
intent, outError)) {
return null;
}
if (intent.countActions() == 0) {
Slog.w(TAG, "No actions in intent filter at "
+ mArchiveSourcePath + " "
+ parser.getPositionDescription());
} else {
a.order = Math.max(intent.getOrder(), a.order);
a.intents.add(intent);
}
// adjust activity flags when we implicitly expose it via a browsable filter
final int visibility = visibleToEphemeral
? IntentFilter.VISIBILITY_EXPLICIT
: !receiver && isImplicitlyExposedIntent(intent)
? IntentFilter.VISIBILITY_IMPLICIT
: IntentFilter.VISIBILITY_NONE;
intent.setVisibilityToInstantApp(visibility);
if (intent.isVisibleToInstantApp()) {
a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
}
if (intent.isImplicitlyVisibleToInstantApp()) {
a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
}
if (LOG_UNSAFE_BROADCASTS && receiver
&& (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
for (int i = 0; i < intent.countActions(); i++) {
final String action = intent.getAction(i);
if (action == null || !action.startsWith("android.")) continue;
if (!SAFE_BROADCASTS.contains(action)) {
Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
+ owner.packageName + " as requested at: "
+ parser.getPositionDescription());
}
}
}
} else if (!receiver && parser.getName().equals("preferred")) {
ActivityIntentInfo intent = new ActivityIntentInfo(a);
if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
intent, outError)) {
return null;
}
if (intent.countActions() == 0) {
Slog.w(TAG, "No actions in preferred at "
+ mArchiveSourcePath + " "
+ parser.getPositionDescription());
} else {
if (owner.preferredActivityFilters == null) {
owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
}
owner.preferredActivityFilters.add(intent);
}
// adjust activity flags when we implicitly expose it via a browsable filter
final int visibility = visibleToEphemeral
? IntentFilter.VISIBILITY_EXPLICIT
: !receiver && isImplicitlyExposedIntent(intent)
? IntentFilter.VISIBILITY_IMPLICIT
: IntentFilter.VISIBILITY_NONE;
intent.setVisibilityToInstantApp(visibility);
if (intent.isVisibleToInstantApp()) {
a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
}
if (intent.isImplicitlyVisibleToInstantApp()) {
a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
}
} else if (parser.getName().equals("meta-data")) {
if ((a.metaData = parseMetaData(res, parser, a.metaData,
outError)) == null) {
return null;
}
} else if (!receiver && parser.getName().equals("layout")) {
parseLayout(res, parser, a);
} else {
if (!RIGID_PARSER) {
Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
if (receiver) {
Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
+ " at " + mArchiveSourcePath + " "
+ parser.getPositionDescription());
} else {
Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
+ " at " + mArchiveSourcePath + " "
+ parser.getPositionDescription());
}
XmlUtils.skipCurrentTag(parser);
continue;
} else {
if (receiver) {
outError[0] = "Bad element under <receiver>: " + parser.getName();
} else {
outError[0] = "Bad element under <activity>: " + parser.getName();
}
return null;
}
}
}

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

return a;
}

3.3 PackageParser总结

上图画出了PackageParser解析Apk文件,得到的主要的数据结构,实际的内容远多于这些,我们仅保留了四大组件和权限相关的内容。

上面这些类,全部是定义于PackageParser中的内部类,这些内部类主要的作用就是保存AndroidManifest.xml解析出的对应信息。 以PackageParser.Activity为例,注意到该类持有ActivityInfo类,继承自 Component< ActivityIntentInfo>。其中,ActivityInfo用于保存Activity的信息;Component类是一个模板,对应元素类型是ActivityIntentInfo,顶层基类IntentFilter。四大组件中的其它成员,也有类似的继承结构。

这种设计的原因是:Package除了保存信息外,还需要支持Intent匹配查询。例如,当收到某个Intent后,由于ActivityIntentInfo继承自IntentFilter,因此它能判断自己是否满足Intent的要求。如果满足,则返回对应的ActivityInfo。

PackageParser整个扫描过程如下:

  • PackageParser首先解析出ApkLite,得到每个Apk文件的简化信息;

  • 利用所有的ApkLite以及Xml中其它信息,解析出PackageLite;

  • 利用PackageLite中的信息及XML中的其它信息,解析出Package信息;

​ Package中基本上涵盖了AndroidManifest中涉及的所有信息。

注意:在上述的解析过程中,PackageParser利用AssetManager存储了Package中资源文件的地址。

附录

源码路径

1
2
3
/frameworks/base/services/core/java/com/android/server/pm/Settings.java
/frameworks/base/core/java/com/android/server/SystemConfig.java
/frameworks/base/core/java/android/content/pm/PackageParser.java