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.5.2 Activity信息的管理 - 图1

图 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匹配查询工作。