1.Settings类
// 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构造函数
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中。
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;
}
/**
* 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里面,如下所示:
<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
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配置文件,如下:
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)
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,在其类中注释如下:
/**
* 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.
*
* 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:
*
* All APKs must have the exact same package name, version code, and signing
* certificates.
* All APKs must have unique split names.
* All installations must contain a single base APK.
*
*
* @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
记录新的权限
/** @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
主要记录一个权限拆分为颗粒度更小的权限
/** @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的参数
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
主要为解析包中单个组件的参数
/** @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
表示在解析过程中的一个轻量级的独立的安装包
/**
* 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
/**
* 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
表示类比较器,在拆包中排序用到
/**
* 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构成。
/**
* 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
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里面的
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里面的
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。
/**
* 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对象中。
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中资源文件的地址。
附录
源码路径
/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