8 Hook匹配过程
1, activity
IpackageManagerHookHandle中Hook了resolveIntent和queryIntentActivities方法,也就是activity 的匹配过程只需要看这2个方法,
resolveIntent的beforeInvoke方法有关代码如下,
ResolveInfo info = PluginManager.getInstance().resolveIntent(intent, resolvedType, flags);
queryIntentActivities的afterInvoke方法有关代码如下,
List<ResolveInfo> infos = PluginManager.getInstance().queryIntentActivities(intent, resolvedType, flags);
2,Service
IpackageManagerHookHandle中虽然也Hook了resolveService和queryIntentServices方法, 但是启动的还是注册的代理Service,
然后在代理Service中匹配原来的service。
还是看一下,
resolveService的beforeInvoke方法有关代码如下,
ResolveInfo info = PluginManager.getInstance().resolveService(intent, resolvedType, flags);
queryIntentServices的afterInvoke方法有关代码如下,
List<ResolveInfo> infos = PluginManager.getInstance().queryIntentServices(intent, resolvedType, flags);
在前面论述的恢复Service过程中,是利用ServcesManager的方法。
首先在ServcesManager的onStart方法中,
Intent targetIntent = intent.getParcelableExtra(Env.EXTRA_TARGET_INTENT);
if (targetIntent != null) {
ServiceInfo targetInfo = PluginManager.getInstance().resolveServiceInfo(targetIntent, 0);
调用resolveServiceInfo的相关信息。
然后在handleCreateServiceOne方法中,
ResolveInfo resolveInfo = hostContext.getPackageManager().resolveService(stubIntent, 0);
和resolveService的beforeInvoke方法完全一样。
3, BroadcastReceiver
对于广播来说,主要将广播注册上去了,就和真正的广播没有什么区别。IpackageManagerHookHandle中Hook了queryIntentReceivers方法。
queryIntentReceivers的afterInvoke方法如下,
List<ResolveInfo> infos = PluginManager.getInstance().queryIntentReceivers(intent, resolvedType, flags);
4,ContentProvider
IpackageManagerHookHandle中Hook了resolveContentProvider方法。但是启动的还是注册的代理ContentProvider,
然后在代理ContentProvider中匹配原来的ContentProvider。
resolveContentProvider的afterInvoke方法如下,
ProviderInfo info = PluginManager.getInstance().resolveContentProvider(name, flags);
在AbstractContentProviderStub的query/insert/delete/update等方法中都会利用targetAuthority调用getContentProviderClient
获取真实的ContentProviderClient对象,
String targetAuthority = uri.getQueryParameter(Env.EXTRA_TARGET_AUTHORITY);
if (!TextUtils.isEmpty(targetAuthority) && !TextUtils.equals(targetAuthority, uri.getAuthority())) {
ContentProviderClient client = getContentProviderClient(targetAuthority);
getContentProviderClient方法主要逻辑如下,
targetInfo = PluginManager.getInstance().resolveContentProvider(targetAuthority, 0);
和resolveContentProvider的afterInvoke方法逻辑完全相同。
8.1 Activity 匹配
PluginManager的resolveIntent方法调用流程图如下,
PluginManager是一个单例模式,并且只是客户端,类似于android系统的API接口,真正实现方法是在服务端IpluginManagerImpl中,
IpluginManagerImpl的resolveIntent方法如下,
List<ResolveInfo> infos = IntentMatcher.resolveIntent(mContext, mPluginCache, intent, resolvedType, flags);
if (infos != null && infos.size() > 0) {
return IntentMatcher.findBest(infos);
}
首先调用IntentMatcher的resolveIntent方法查询匹配的intent,然后调用findBest方法返回最匹配的结果, findBest直接返回infos中的第一个元素。
主要看IntentMatcher的resolveIntent方法。resolveIntent主要逻辑如下,
1,对于有包名的intent,直接查找插件对应的包名的PluginPackageParser。
PluginPackageParser parser = pluginPackages.get(comp.getPackageName());
if (parser != null) {
queryIntentActivityForPackage(context, parser, intent, flags, list);
2,否则,对于每一个插件都得去匹配一下intent,展开地毯式搜索。
for (PluginPackageParser parser : pluginPackages.values()) {
queryIntentActivityForPackage(context, parser, intent, flags, list);
queryIntentServiceForPackage(context, parser, intent, flags, list);
queryIntentProviderForPackage(context, parser, intent, flags, list);
queryIntentReceiverForPackage(context, parser, intent, flags, list);
}
queryIntentActivityForPackage主要逻辑如下,
1,获取插件中的所有Activity
List<ActivityInfo> activityInfos = packageParser.getActivities();
2,获取每个Activity的所有IntentFilter,
if (activityInfos != null && activityInfos.size() >= 0) {
for (ActivityInfo activityInfo : activityInfos) {
ComponentName className = new ComponentName(activityInfo.packageName, activityInfo.name);
List<IntentFilter> intentFilters = packageParser.getActivityIntentFilter(className);
都是利用packageParser中的变量,这些变量在解析完成时赋值的。
3,对IntentFilter匹配
if (intentFilters != null && intentFilters.size() > 0) {
for (IntentFilter intentFilter : intentFilters) {
int match = intentFilter.match(context.getContentResolver(), intent, true, "");
if (match >= 0) {
ActivityInfo flagInfo = packageParser.getActivityInfo(new ComponentName(activityInfo.packageName, activityInfo.name), flags);
if ((flags & PackageManager.MATCH_DEFAULT_ONLY) != 0) {
if (intentFilter.hasCategory(Intent.CATEGORY_DEFAULT)) {
ResolveInfo resolveInfo = newResolveInfo(flagInfo, intentFilter);
resolveInfo.match = match;
resolveInfo.isDefault = true;
outList.add(resolveInfo);
} else {
//只是匹配默认。这里也算匹配不上。
}
} else {
ResolveInfo resolveInfo = newResolveInfo(flagInfo, intentFilter);
resolveInfo.match = match;
resolveInfo.isDefault = false;
outList.add(resolveInfo);
}
}
}