PMS解析已安装的apk信息
在Android中getSystemService流程一文中,我们知道系统在启动的时候
会加载系统Service,比如ActivityManagerService,PackageManagerService等, PMS启动以后,会扫描系统中所有已安装apk的目录,比如系统
应用”/system/app”,第三方应用”/data/app”,PMS会解析该包下的所有AndroidManifest.xml文件,将解析出的activity,service,broadcastreceiver
等信息保存到系统中。
其实在android系统开机以后加载PackageManagerService时候,从其构造方法就开始了。
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
.......
synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper());
// 获取/data目录
File dataDir = Environment.getDataDirectory();
// /data/data
mAppDataDir = new File(dataDir, "data");
// /data/app
mAppInstallDir = new File(dataDir, "app");
mAppLib32InstallDir = new File(dataDir, "app-lib");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
mUserAppDataDir = new File(dataDir, "user");
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
mRegionalizationAppInstallDir = new File(dataDir, "app-regional");
.....
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
// 加载framework资源
alreadyDexOpted.add(frameworkDir.getPath() + "/framework-res.apk");
// 加载核心库文件
alreadyDexOpted.add(frameworkDir.getPath() + "/core-libart.jar");
populateBlacklist();
.....
// 获取系统app的安装路径
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
// 扫描系统app的安装路径
scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_RUNTIME_SKIN, 0);
// Collect all vendor packages.
File vendorAppDir = new File("/vendor/app");
try {
vendorAppDir = vendorAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_RUNTIME_SKIN, 0);
// Collect all OEM packages.
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_RUNTIME_SKIN, 0);
File oemPrivAppDir = new File(Environment.getOemDirectory(), "priv-app");
if (oemPrivAppDir.exists()) {
scanDirLI(oemPrivAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_TRUSTED_RUNTIME_SKIN, 0);
}
// Collect all Regionalization packages form Carrier's res packages.
if (RegionalizationEnvironment.isSupported()) {
Log.d(TAG, "Load Regionalization vendor apks");
final List<File> RegionalizationDirs =
RegionalizationEnvironment.getAllPackageDirectories();
for (File f : RegionalizationDirs) {
File RegionalizationSystemDir = new File(f, "system");
// Collect packages in <Package>/system/priv-app
scanDirLI(new File(RegionalizationSystemDir, "priv-app"),
PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
// Collect packages in <Package>/system/app
scanDirLI(new File(RegionalizationSystemDir, "app"),
PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags, 0);
// Collect overlay in <Package>/system/vendor
scanDirLI(new File(RegionalizationSystemDir, "vendor/overlay"),
PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags | SCAN_TRUSTED_OVERLAY, 0);
}
}
if (!mOnlyCore) {
// 扫描第三方app的安装路径
scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
scanFlags | SCAN_REQUIRE_KNOWN, 0);
}
.....
} // synchronized (mPackages)
} // synchronized (mInstallLock)
Runtime.getRuntime().gc();
// Expose private service for system components to use.
LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());
LocalServices.addService(PackageManagerServiceExtend.class, new ServiceExtendImpl());
}
从上面的构造方法,可以看出,PMS需要加载系统已安装的各类apk,包括系统apk第三方apk等等,在此之前,还要加载Framework资源与核心库文件,
并且具体的扫描加载功能由scanDirLI方法实现,我们看看scanDirLI方法的内部实现:
private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
// 获取目录下的所有文件
final File[] files = dir.listFiles();
if (ArrayUtils.isEmpty(files)) {
Log.d(TAG, "No files in app dir " + dir);
return;
}
// 遍历所有文件
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
// 如果不是apk文件,则直接忽略
if (!isPackage) {
continue;
}
......
try {
// 解析apk
scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
scanFlags, currentTime, null);
} catch (PackageManagerException e) {
.....
}
}
}
scanDirLI方法比较简单:
1. 遍历当前目录下所有文件,如果没有文件,直接返回
2. 判断当前文件是否是apk文件,如果不是直接返回
3. 通过scanPackageLI解析当前apk文件
可以看到重点解析当前apk文件的工作,转移到了scanPackageLI方法,我们继续scanPackageLI:
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
// 创建一个包解析器
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
pp.setRuntimeSkinBlacklist(mRuntimeSkinManager.getBlacklistedPackages());
final PackageParser.Package pkg;
try {
// 解析apk包
pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParser.PackageParserException e) {
throw PackageManagerException.from(e);
}
....
// 解析apk中的activity,service等组件, 在(pkg, parseFlags, scanFlags
// | SCAN_UPDATE_SIGNATURE, currentTime, user)方法中会将当前解析出的activity,service等组件添加到PackageManagerService的集合里
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags
| SCAN_UPDATE_SIGNATURE, currentTime, user);
....
return scannedPkg;
}
在scanPackageLI方法中:
1.首先创建一个包解析器
2.通过parsePackage解析apk包,封装成PackageParser.Package类型
3.通过步骤二中的PackageParser.Package对象,解析apk中的activity,service等组件
解析单个apk
下面我们看下parsePackage方法,具体解析单个apk文件的流程:
public Package parsePackage(File packageFile, int flags) throws PackageParserException {
// 是否是文件夹类型
if (packageFile.isDirectory()) {
return parseClusterPackage(packageFile, flags);
} else {
// 解析单个apk文件
return parseMonolithicPackage(packageFile, flags);
}
}
在parsePackage中,会判断当前文件类型选择不同的解析,如果是一个文件夹,则匹配该文件夹下的所有apk文件,如果是一个文件,则调用
PackageParser#parseMonolithicPackage解析单个文件。
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
...
final AssetManager assets = new AssetManager();
try {
// 具体解析apk文件操作的封装
final Package pkg = parseBaseApk(apkFile, assets, flags);
pkg.codePath = apkFile.getAbsolutePath();
return pkg;
} finally {
IoUtils.closeQuietly(assets);
}
}
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
// 代码省略
final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
Resources res = null;
XmlResourceParser parser = null;
try {
// 根据AssetManager实例构建资源实例
res = new 构建(assets, mMetrics, null);
assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
// 获取AndroidManifest.xml的解析器
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final String[] outError = new String[1];
// 解析获取到的AndroidManifest.xml
final Package pkg = parseBaseApk(res, parser, flags, outError);
pkg.volumeUuid = volumeUuid;
pkg.applicationInfo.volumeUuid = volumeUuid;
pkg.baseCodePath = apkPath;
pkg.mSignatures = null;
return pkg;
}
// 省略catch代码块
}
在上述方法中主要调用了parseBaseApk(res, parser, flags, outError)解析AndroidManifest.xml文件
private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
String[] outError) throws XmlPullParserException, IOException {
AttributeSet attrs = parser;
// 1.构建Package对象
final Package pkg = new Package(pkgName);
boolean foundApp = false;
// 2.通过TypedArray获取AndroidManifest.xml文件中的属性值,并赋值给pkg对象
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifest);
pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
pkg.baseRevisionCode = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
pkg.mVersionName = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifest_versionName, 0);
if (pkg.mVersionName != null) {
pkg.mVersionName = pkg.mVersionName.intern();
}
String str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
if (str != null && str.length() > 0) {
String nameError = validateName(str, true, false);
if (nameError != null && !"android".equals(pkgName)) {
outError[0] = "<manifest> specifies bad sharedUserId name \""
+ str + "\": " + nameError;
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
return null;
}
pkg.mSharedUserId = str.intern();
pkg.mSharedUserLabel = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
}
pkg.installLocation = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_installLocation,
PARSE_DEFAULT_INSTALL_LOCATION);
pkg.applicationInfo.installLocation = pkg.installLocation;
pkg.coreApp = attrs.getAttributeBooleanValue(null, "coreApp", false);
sa.recycle();
// 3.解析AndroidManifest.xml文件
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("application")) {
if (foundApp) {
// 4.解析application标签,activity,service,broadcastreceiver都在这个标签中
if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) {
return null;
}
} else if (tagName.equals("overlay")) {
....
} else if (tagName.equals("key-sets")) {
if (!parseKeySets(pkg, res, parser, attrs, outError)) {
return null;
}
} else if (tagName.equals("permission-group")) {
if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) {
return null;
}
} else if (tagName.equals("permission")) {
if (parsePermission(pkg, res, parser, attrs, outError) == null) {
return null;
}
} else if (tagName.equals("permission-tree")) {
if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
return null;
}
} else if (tagName.equals("uses-permission")) {
if (!parseUsesPermission(pkg, res, parser, attrs)) {
return null;
}
} else if (tagName.equals("uses-permission-sdk-m")
|| tagName.equals("uses-permission-sdk-23")) {
if (!parseUsesPermission(pkg, res, parser, attrs)) {
return null;
}
} else if (tagName.equals("uses-configuration")) {
....
} else if (tagName.equals("uses-feature")) {
....
} else if (tagName.equals("feature-group")) {
....
} else if (tagName.equals("uses-sdk")) {
....
} else if (tagName.equals("supports-screens")) {
....
} else if (tagName.equals("protected-broadcast")) {
....
} else if (tagName.equals("adopt-permissions")) {
....
}
}
....
return pkg;
}
在PackageParser#parseBaseApk(res, parser, flags, outError)方法主要做了下面的事情:
- 构建Package对象
- 通过TypedArray获取AndroidManifest.xml文件中的属性值,并赋值给pkg对象
- 解析AndroidManifest.xml文件
- 通过parseBaseApplication解析application标签,activity,service,broadcastreceiver都在这个标签中
接着分析parseBaseApplication方法:
private boolean parseBaseApplication(Package owner, Resources res,
XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
throws XmlPullParserException, IOException {
final ApplicationInfo ai = owner.applicationInfo;
final String pkgName = owner.applicationInfo.packageName;
// 根据TypedArray获取到在AndroidManifest.xml文件中配置的属性值.
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestApplication);
// 省略代码
ai.icon = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
ai.logo = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
ai.banner = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_banner, 0);
ai.theme = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
ai.descriptionRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
// 省略代码
sa.recycle();
// 2.解析AndroidManifest.xml中的四大组件,并且将解析结果,添加到Package中对应的集合里
final int innerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("activity")) {
Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
owner.baseHardwareAccelerated);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.activities.add(a);
} else if (tagName.equals("receiver")) {
Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.receivers.add(a);
} else if (tagName.equals("service")) {
Service s = parseService(owner, res, parser, attrs, flags, outError);
if (s == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.services.add(s);
} else if (tagName.equals("provider")) {
Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
if (p == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.providers.add(p);
} else if (tagName.equals("activity-alias")) {
Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.activities.add(a);
}
return true;
}
在parseBaseApplication主要做了下面操作:
1. 根据TypedArray获取到在AndroidManifest.xml文件中配置的属性值.
2. 解析AndroidManifest.xml中的四大组件,并且将解析结果,添加到Package中对应的集合里,这些集合是声明在PackageParser$Package中的
public final static class Package {
....
public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
public final ArrayList<Service> services = new ArrayList<Service>(0);
}
到此位置解析单个apk的工作都已经完成,并且将解析结果封装到Package对象中
将解析结果信息存储到PackageManagerService的集合里
回到上面的scanPackageLI(File scanFile, int parseFlags, int scanFlags,long currentTime, UserHandle user)方法,
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
// 创建一个包解析器
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
pp.setRuntimeSkinBlacklist(mRuntimeSkinManager.getBlacklistedPackages());
final PackageParser.Package pkg;
try {
// 解析apk包
pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParser.PackageParserException e) {
throw PackageManagerException.from(e);
}
....
// 解析apk中的activity,service等组件, 在(pkg, parseFlags, scanFlags
// | SCAN_UPDATE_SIGNATURE, currentTime, user)方法中会将当前解析出的activity,service等组件添加到PackageManagerService的集合里
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags
| SCAN_UPDATE_SIGNATURE, currentTime, user);
....
return scannedPkg;
}
在该方法,最后调用了scanPackageLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user)方法:
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
.....
N = pkg.services.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Service s = pkg.services.get(i);
s.info.processName = fixProcessName(pkg.applicationInfo.processName,
s.info.processName, pkg.applicationInfo.uid);
// 添加到对应的mServices集合中
mServices.addService(s);
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(s.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
}
N = pkg.receivers.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.receivers.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
// 添加到对应的mReceivers集合中
mReceivers.addActivity(a, "receiver");
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
}
N = pkg.activities.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.activities.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
// 添加到对应的mActivities集合中
mActivities.addActivity(a, "activity");
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
....
}
将之前保存在PackageParser.Package中的apk信息重新放到PackageManagerService中
final ActivityIntentResolver mActivities =
new ActivityIntentResolver();
// All available receivers, for your resolving pleasure.
final ActivityIntentResolver mReceivers =
new ActivityIntentResolver();
// All available services, for your resolving pleasure.
final ServiceIntentResolver mServices = new ServiceIntentResolver();
// All available providers, for your resolving pleasure.
final ProviderIntentResolver mProviders = new ProviderIntentResolver();
到现在为止所有apk信息的构建就完成了。
intent信息的匹配
这里我们用”startActivity”来说明,在activity启动流程一文中,我们详细的讨论过activity的启动流程
ActivityStackSupervisor#startActivityMayWait方法
final int startActivityMayWait(参数省略.....) {
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveIntent(
intent, null,
PackageManager.MATCH_DEFAULT_ONLY
| ActivityManagerService.STOCK_PM_FLAGS, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
aInfo = mService.getActivityInfoForUser(aInfo, userId);
} catch (RemoteException e) {
aInfo = null;
}
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
componentSpecified, null, container, inTask);
return res;
}
可以看到通过PMS中的resolveIntent方法来查找匹配当前intent的activity
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "resolve intent");
List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
return chooseBestActivity(intent, resolvedType, flags, query, userId);
}
@Override
public List<ResolveInfo> queryIntentActivities(Intent intent,
String resolvedType, int flags, int userId) {
// 获取ComponentName对象,如果该对象不为null,则表明intent指明了ComponentName
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
intent = intent.getSelector();
comp = intent.getComponent();
}
}
if (comp != null) {
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
// 根据comp获取精确的ActivityInfo
final ActivityInfo ai = getActivityInfo(comp, flags, userId);
if (ai != null) {
final ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
list.add(ri);
}
if (homeIntentRestrictedByDPM) {
return getCurrentDefaultHome(list, userId);
}
return list;
}
// reader
synchronized (mPackages) {
final String pkgName = intent.getPackage();
if (pkgName == null) {
// Check for results in the current profile.
List<ResolveInfo> result = mActivities.queryIntent(
intent, resolvedType, flags, userId);
....
return result;
}
// 通过包名获取Package对象
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
// 通过Package对象获取ActivityInfo
List<ResolveInfo> result = mActivities.queryIntentForPackage(
intent, resolvedType, flags, pkg.activities, userId);
if (homeIntentRestrictedByDPM) {
return getCurrentDefaultHome(result, userId);
}
return filterIfNotPrimaryUser(result, userId);
}
return new ArrayList<ResolveInfo>();
}
}
上面方法中,当intent指明了Componet,那么直接通过ComponentName就可以找到一个ActivityInfo列表,并且该列表只有一个,如果没有指定,那么先查看Intent是否制定了需要跳转到对应的包,如果有包名,则通过包名获取对应的ActivityInfo.
到此为止,apk信息的构建以及intent的匹配就完成了。