四大组件的匹配过程

来源:互联网 发布:ubuntu系统声音主题包 编辑:程序博客网 时间:2024/05/29 16:11

6 四大组件的匹配过程

在AndroidManifest.xml中,除了这些静态注册的receiver,每个插件中的activity或者service也有可能声明intent filter。

四大组件注册完成之后,都会有一个查找匹配的过程。

前面论述的都是包含包名和类名的情况,在此论述一下intent的匹配过程。

6.1 activity

把要启动的activity替换成了stub activity,那这些intent filter是怎么匹配上的呢?要搞清楚这一点,首先要了解下这个匹配

是在哪里做的。实际上,将stub activity还原成目标activity之后,才进行intent的查找匹配。因为目标activity的intent等信息

并未注册到PMS中,所以一定要Hook PMS的resolveIntent方法逐个扫描插件中的目标activity的intent,找出匹配的那个activity,

完成最后的启动过程。

ActivityThread的handleLaunchActivity调用流程图如下,


handleLaunchActivity第二个参数已经是目标activity的intent。

调用performLaunchActivity方法找出匹配的activity并且构造该activity。

Activity a = performLaunchActivity(r, customIntent);

在ActivityThread的performLaunchActivity()方法里,如果没有显式指定类名,会先调用resolveActivity()去找出最匹配的component

ActivityThread的performLaunchActivity方法如下,

ComponentName component = r.intent.getComponent();  if (component == null) {       component = r.intent.resolveActivity(          mInitialApplication.getPackageManager());          r.intent.setComponent(component);  }  

r是ActivityThread的内部类ActivityClientRecord对象,并且r也有intent变量。

Intent的resolveActivity方法如下,

ResolveInfo info = pm.resolveActivity(this, PackageManager.MATCH_DEFAULT_ONLY);if (info != null) {     return new ComponentName(     info.activityInfo.applicationInfo.packageName,     info.activityInfo.name);}

pm其实是ApplicationPackageManager对象, ApplicationPackageManager的resolveActivity方法如下,

public ResolveInfo resolveActivity(Intent intent, int flags) {      return resolveActivityAsUser(intent, flags, mContext.getUserId());}

直接调用resolveActivityAsUser方法,该方法如下,

public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {        try {            return mPM.resolveIntent(                intent,                intent.resolveTypeIfNeeded(mContext.getContentResolver()),                flags,                userId);        } catch (RemoteException e) {            throw new RuntimeException("Package manager has died", e);        }    }

不用说,这里的mPM 就是PMS对象,又跨进程调用到PMS中了, resolveIntent方法如下,

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);    }

最后通过queryIntentActivities查找出匹配的ResolveInfo信息。

当然, IpackageManagerHookHandle中Hook了resolveIntent和queryIntentActivities方法。

6.2 service

无论是bindeservice还是startservice最后都会有匹配的过程,不同于Activity,匹配过程直接由systemserver进程发起,调用流程图如下,


其中, startservice调用的是startServiceLocked方法, bindeservice调用的是bindServiceLocked方法,这2个方法都会调用

retrieveServiceLocked,最后调用PMS的resolveService/queryIntentServices完成intent的匹配过程。

当然, IpackageManagerHookHandle中Hook了resolveService和queryIntentServices方法。

6.3 广播

广播的匹配过程自然在广播的发送过程中,也是在systemserver进程有AMS发起的。调用流程图如下,


这个调用结构相对简单, 最后调用PMS的queryIntentReceivers完成广播intent的匹配过程。

当然, IpackageManagerHookHandle中Hook了queryIntentReceivers方法。

6.4 ContentProvider

ContentProvider过程最简单了,直接有AMS发起,调用流程图如下,


当然, IpackageManagerHookHandle中Hook了resolveContentProvider方法。