4.5.2 Activity信息的管理
前面在介绍PKMS扫描APK时提到,PKMS将解析得到的package私有的Activity信息加入到自己的数据结构mActivities中保存。下面先来看以下相关代码:
[—>PackgeManagerService.java:scanPackageLI]
……//此时APK文件已经解析完成
N=pkg.activities.size();//取出该APK中包含的Activities信息
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.addActivity(a,"activity");//①加到mActivities中保存
}
上面的代码中有两个比较重要的数据结构,如图4-13所示。
图 4-13 相关数据结构示意图
结合代码,由图4-13可知:
mActivities为ActivityIntentResolver类型,是PKMS的成员变量,用于保存系统中所有与Activity相关的信息。此数据结构内部有一个mActivities变量,它以Componet-Name为key,保存PackageParser.Activity对象。
从APK中解析得到的所有和Activity相关的信息(包括在XML中声明的IntentFilter标签)都由PackageParser.Activity来保存。
前面代码中调用addActivity函数完成了私有信息的公有化。addActivity函数的代码如下:
[—>PackageManagerService.java:ActivityIntentResolver.addActivity]
public final void addActivity(PackageParser.Activity a, String type){
final boolean systemApp=isSystemApp(a.info.applicationInfo);
//将Component和Activity保存到mActivities中
mActivities.put(a.getComponentName(),a);
final int NI=a.intents.size();
for(int j=0;j<NI;j++){
//ActivityIntentInfo存储的就是XML中声明的IntentFilter信息
PackageParser.ActivityIntentInfo intent=a.intents.get(j);
if(!systemApp&&intent.getPriority()>0&&"activity".equals(type)){
//非系统APK的priority必须为0。后续分析中将介绍priority的作用
intent.setPriority(0);
}
addFilter(intent);//接下来将分析这个函数
}
}
下面来分析addFilter函数,这里涉及较多的复杂的数据结构,代码如下:
[—>IntentResolver.java:IntentResolver.addFilter]
public void addFilter(F f){
……
mFilters.add(f);//mFilters保存所有IntentFilter信息
//除此之外,为了加快匹配工作的速度,还需要分类保存IntentFilter信息
//下边register_xxx函数的最后一个参数用于打印信息
int numS=register_intent_filter(f, f.schemesIterator(),
mSchemeToFilter,"Scheme:");
int numT=register_mime_types(f,"Type:");
if(numS==0&&numT==0){
register_intent_filter(f, f.actionsIterator(),
mActionToFilter,"Action:");
}
if(numT!=0){
register_intent_filter(f, f.actionsIterator(),
mTypedActionToFilter,"TypedAction:");
}
}
正如代码注释中所说,为了加快匹配工作的速度,这里使用了泛型编程并定义了较多的成员变量。下面总结一下这些变量的作用(注意,除mFilters为HashSet<F>类型外,其他成员变量的类型都是HashMap<String, ArrayList<F>>,其中F为模板参数)。
mSchemeToFilter:用于保存uri中与scheme相关的IntentFilter信息。
mActionToFilter:用于保存仅设置Action条件的IntentFilter信息。
mTypedActionToFilter:用于保存既设置了Action又设置了Data的MIME类型的IntentFilter信息。
mFilters:用于保存所有IntentFilter信息。
mWildTypeToFilter:用于保存设置了Data类型类似“image/*”的IntentFilter,但是设置MIME类型类似“Image/jpeg”的不算在此类。
mTypeToFilter:除了包含mWildTypeToFilter外,还包含那些指明了Data类型为确定参数的IntentFilter信息,例如“image/*”和“image/jpeg”等都包含在mTypeToFilter中。
mBaseTypeToFilter:包含MIME中Base类型的IntentFilter信息,但不包括Sub type为“*”的IntentFilter。
不妨举个例子来说明这些变量的用法。
假设,在XML中声明一个IntentFilter,代码如下:
<intent-filter android:label="test">
<action android:name="android.intent.action.VIEW"/>
data android:mimeType="audio/*"android:scheme="http"
</intent-filter>
那么:
在mTypedActionToFilter中能够以“android.intent.action.VIEW”为key找到该IntentFilter。
在mWildTypeToFilter和mTypeToFilter中能够以“audio”为key找到该IntentFilter。
在mSchemeToFilter中能够以“http”为key找到该IntentFilter。
下面来分析Intent匹配查询工作。