由前面深入PMS源码(一)—— PMS的启动过程和执行流程和深入PMS源码(二)—— APK的安装和卸载源码分析两篇文章知道,无论是Android系统启动后执行的PMS启动,还是使用PackageInstaller安装APK的过程,最终都会使用PackageParser扫描相应的apk文件,将扫描提取的信息保在Package对象中,扫描完成后会回调PMS中方法将扫描获取的四大组件信息转换保存在PMS属性中,主要使用ActivityIntentResolver、ServiceIntentResolver、ProviderIntentResolver保存信息,这里会有两个问题:
下面带着这两个问题,从源码的角度探讨下PMS中的intent-filter的匹配架构,接着PMS的启动过程中分析,对四大组件处理代码如下,这里已对Activity的处理为例分析
N = pkg.activities.size();
3503 r = null;
3504 for (i=0; i<N; i++) {
3505 PackageParser.Activity a = pkg.activities.get(i);
3506 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3507 a.info.processName, pkg.applicationInfo.uid);
3508 mActivities.addActivity(a, "activity"); //调用ActivityIntentResolver.addActivity()
}
// ActivityIntentResolver.addActivity()
public final void addActivity(PackageParser.Activity a, String type) {
mActivities.put(a.getComponentName(), a); // 1、获取内部的Component对象,在Activity会自动创建Component对象
final int NI = a.intents.size();
for (int j=0; j<NI; j++) {
PackageParser.ActivityIntentInfo intent = a.intents.get(j); // 获取Activity中设置的intent
addFilter(intent); // 添加Intent过滤
}
}
从解析得到的Package对象中获取每个创建的Activity对象,然后调用ActivityIntentResolver.addActivity()方法将Activity对象保存在ActivityIntentResolver.mActivities集合中,在程序的最后几行代码中会遍历a.intents的集合,取出每个ActivityIntentInfo信息调用addFilter()添加Intent过滤信息,这里的ActivityIntentInfo是在PackageParser解析标签中创建的对象并添加到a.intents的集合中,也就是说每个Activity标签下定义的标签都对应一个ActivityIntentInfo对象,且所有的对象都保存在a.intents的集合中,在介绍addFilter()方法前先介绍下IntentResolver类;
public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
private final ArraySet<F> mFilters = new ArraySet<F>(); //保存所有的intent对应的匹配对象
private final ArrayMap<String, F[]> mTypeToFilter = new ArrayMap<String, F[]>(); //保存Type 匹配的Intent集合
private final ArrayMap<String, F[]> mBaseTypeToFilter = new ArrayMap<String, F[]>();
private final ArrayMap<String, F[]> mWildTypeToFilter = new ArrayMap<String, F[]>();// 保存所有带“*”通配符类型
private final ArrayMap<String, F[]> mSchemeToFilter = new ArrayMap<String, F[]>(); //已注册所有Uri方案
private final ArrayMap<String, F[]> mActionToFilter = new ArrayMap<String, F[]>();//保存所有指定Action 的Intent集合
private final ArrayMap<String, F[]> mTypedActionToFilter = new ArrayMap<String, F[]>(); // 匹配已注册且指定Mime Type类型Intent
}
上面的IntentResolver是一个范型,内部储存者IntentFilter的子类,而ActivityIntentInfo继承IntentInfo,IntentInfo又继承于IntentFilter类,所以此处直接保存的就是ActivityIntentInfo对象,在IntentFilter中保存着设置的多个属性
private int mPriority; // 优先级
private int mOrder; // 层级
private final ArrayList<String> mActions; // 设置的actions集合
private ArrayList<String> mCategories = null; // 设置categories集合
private ArrayList<String> mDataSchemes = null; // 数据集合
private ArrayList<PatternMatcher> mDataSchemeSpecificParts = null;
private ArrayList<AuthorityEntry> mDataAuthorities = null; // 匹配权限
private ArrayList<PatternMatcher> mDataPaths = null; // 匹配数据path
private ArrayList<String> mDataTypes = null; // 数据类型
添加PMS扫描获得的可匹配的IntentFilter对象,在PMS解析时将每个Activity中设置的标签中信息保存在一个IntentFilter对象中,在IntentFilter中保存着标签下所有的action、type、scheme、categories的集合,在addFilter()时将这些集合中数据取出作为Key,将包含相同Key的Intent-Filter保存在数组中,然后以Key为键将这些集合存储在Intent-Resolve的ArrayMap中;
public void addFilter(F f) {
mFilters.add(f); // 在总的Filter中保存数据
int numS = register_intent_filter(f, f.schemesIterator(),
mSchemeToFilter, " Scheme: “); // 判断数据uri,保存在mSchemeToFilter集合中
int numT = register_mime_types(f, " Type: “); //判断baseType 和 mWildType 类型
if (numS == 0 && numT == 0) {
register_intent_filter(f, f.actionsIterator(),
mActionToFilter, " Action: “); // 判断匹配action对应的
}
if (numT != 0) {
register_intent_filter(f, f.actionsIterator(),
mTypedActionToFilter, " TypedAction: “); // 添加mTypedActionToFilter集合
}
}
在addFilter()中首先将传入的intent-filter对象保存在mFilters中,也就是说mFilters中保存着所有的匹配对象,然后依次调用register_intent_filter()、register_mime_types()、register_intent_filter()、register_intent_filter()方法分别解析IntentFilter对象中的属性信息,并保存在相应的HashMap中,这里以register_intent_filter()为例,register_intent_filter中传入的是f.actionsIterator()对象,即获取是actions集合的迭代器
private final int register_intent_filter(F filter, Iterator<String> i, ArrayMap<String, F[]> dest, String prefix) {
int num = 0;
while (i.hasNext()) { // 遍历Iterator
String name = i.next(); // 取出数据集合DataSchemes下一个数据
num++;
addFilter(dest, name, filter); // 添加到对应的Filter集合中,此处为mSchemeToFilter集合数据
}
return num;
}
在register_intent_filter中使用迭代器遍历每个action,然后取出每个action标签下设置的name属性,调用addFilter()方法执行保存,在addFilter()中传入要保存的相应的ArrayMap对象,如action对应的就是mActionToFilter
private final void addFilter(ArrayMap<String, F[]> map, String name, F filter) {
F[] array = map.get(name); // 根据name的名称去除保存数据的数组
if (array == null) {
array = newArray(2); // 创建数组
map.put(name, array); // 保存数据
array[0] = filter; // 保存filter
} else {
final int N = array.length;
int i = N;
while (i > 0 && array[i-1] == null) { // 遍历寻找为null的位置
i--;
}
if (i < N) {
array[i] = filter;
} else {
F[] newa = newArray((N*3)/2); // 原数组长度不够,扩展原数组长度
System.arraycopy(array, 0, newa, 0, N);
newa[N] = filter;
map.put(name, newa);
}
}
}
addFilter()的执行逻辑很简单:
到此程序中注册的四大组件和相应的信息都会保存在IntentResolver类中,在使用时只需要根据设置的条件去查找匹配的对象即可;
查询匹配方式:IntentResolver查询时分别从请求的Intent中取出数据(如:action、mime、scheme),然后分别以每个数据变量为Key,取出每个相应的ArrayMao中保存的对应的IntentFilter数组,最后求去这些数组的交集并去重,达到精准匹配的目的,最后返回匹配的所有ResolveInfo集合;
一般在查找是否能匹配意图时,会调用packageManager.queryIntentActivities(intent,flag)查找匹配的IntentResolve,这里的packageManager对象实际调用ApplicationPackageManager对象,程序进入ApplicationPackageManager中,在ApplicationPackageManager.queryIntentActivities()中直接调用了queryIntentActivitiesAsUser()
@Override
@SuppressWarnings("unchecked")
public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
int flags, int userId) {
try {
ParceledListSlice<ResolveInfo> parceledList =
mPM.queryIntentActivities(intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags, userId);2、
return parceledList.getList();
}
}
在queryIntentActivitiesAsUser()中调用PMS中方法查询匹配Intent,PMS.queryIntentActivities()中间接调用queryIntentActivitiesInternal()方法
if (!sUserManager.exists(userId)) return Collections.emptyList(); // 判断userId
final String instantAppPkgName = getInstantAppPackageName(filterCallingUid); // 获取userId对应的进程包名
final String pkgName = intent.getPackage(); // 获取Intent中携带的包名
ComponentName comp = intent.getComponent(); // 获取Component对象
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
final ActivityInfo ai = getActivityInfo(comp, flags, userId); // 首先从PMs中保存的mActivites集合中获取ActivityInfo信息
result = filterIfNotSystemUser(mActivities.queryIntent( // 从mActivities中查询匹配的List
intent, resolvedType, flags, userId), userId);
在queryIntentActivitiesInternal()方法中:
public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
int userId) {
String scheme = intent.getScheme(); // 获取scheme
ArrayList<R> finalList = new ArrayList<R>();
F[] firstTypeCut = null; //保存匹配的结果
F[] secondTypeCut = null;
F[] thirdTypeCut = null;
F[] schemeCut = null;
if (scheme != null) {
schemeCut = mSchemeToFilter.get(scheme); // 1、先根据scheme匹配,获取匹配的数组
}
final String baseType = resolvedType.substring(0, slashpos);
if (!baseType.equals("*")) {
if (resolvedType.length() != slashpos+2
|| resolvedType.charAt(slashpos+1) != '*') {
firstTypeCut = mTypeToFilter.get(resolvedType); // 根据type匹配
secondTypeCut = mWildTypeToFilter.get(baseType);
} else {
firstTypeCut = mBaseTypeToFilter.get(baseType);
secondTypeCut = mWildTypeToFilter.get(baseType);
}
thirdTypeCut = mWildTypeToFilter.get("*");
} else if (intent.getAction() != null) {
firstTypeCut = mTypedActionToFilter.get(intent.getAction());
}
}
if (resolvedType == null && scheme == null && intent.getAction() != null) {
firstTypeCut = mActionToFilter.get(intent.getAction()); // 2、根据action匹配
}
if (firstTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, firstTypeCut, finalList, userId); // 不断进行匹配
}
if (secondTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, secondTypeCut, finalList, userId);
}
if (thirdTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, thirdTypeCut, finalList, userId);
}
if (schemeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, schemeCut, finalList, userId);
}
sortResults(finalList); // 将数组中元素按照优先级排序
return finalList; // 返回最终匹配的结果集合
在queryIntent()中首先从Intent中取出所有属性信息,如action、scheme等,然后创建四个数组对象,这四个数组主要保存根据Intent中设置的属性查找出对应的数组,之后从每个ArrayMap中匹配返回相应的数组,然后根据四个数数组是否存在数据从而多此执行buildResolveList()方法,buildResolveList主要是获取四个数组中保存的IntentFilter对象转换为输出的对象,然后执行sortResults()其中的重复对象此时即可返回最终匹配结果;
private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
boolean debug, boolean defaultOnly, String resolvedType, String scheme,
F[] src, List<R> dest, int userId) {
final int N = src != null ? src.length : 0;
F filter;
for (i=0; i<N && (filter=src[i]) != null; i++) {
match = filter.match(action, resolvedType, scheme, data, categories, TAG);
if (match >= 0) {
if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
final R oneResult = newResult(filter, match, userId); // 将filter转换为 ResolveInfo
if (oneResult != null) {
dest.add(oneResult); // 保存到dest集合中
}
}
}
}
}
在上述的匹配过程之后即可获取到所有的可处理请求的Activity对象,然后将其中的信息设置在Intent之后再执行请求,此时就是像动态启动Activity一样直接启动目标活动;
Intent intent = new Intent(intentToResolve);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClassName(ris.get(0).activityInfo.packageName,
ris.get(0).activityInfo.name);
return intent;
到此PMS中关于保存IntentFilter和静态启动过程中的匹配过程介绍完毕了,通过上面的学习相信对PMS如何处理apk文件和系统如何识别要启动的程序或活动有了更深的理解,本篇也是PMS系列的最后一篇,希望整个系列的分析对大家学习有所帮助;