源码链接
java
package com.android.server.firewall;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.os.ServiceManager;
import android.util.Slog;
import android.util.Xml;
import com.android.internal.util.XmlUtils;
import com.android.server.IntentResolver;
import com.android.server.pm.PackageManagerService;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class IntentFirewall {
private static final String TAG = "IntentFirewall";
// e.g. /data/system/ifw/ifw.xml or /data/secure/system/ifw/ifw.xml
private static final File RULES_FILE =
new File(Environment.getSystemSecureDirectory(), "ifw/ifw.xml");
private static final String TAG_RULES = "rules";
private static final String TAG_ACTIVITY = "activity";
private static final String TAG_SERVICE = "service";
private static final String TAG_BROADCAST = "broadcast";
private static final HashMap<String, FilterFactory> factoryMap;
private final AMSInterface mAms;
private final IntentResolver<FirewallIntentFilter, Rule> mActivityResolver =
new FirewallIntentResolver();
private final IntentResolver<FirewallIntentFilter, Rule> mServiceResolver =
new FirewallIntentResolver();
private final IntentResolver<FirewallIntentFilter, Rule> mBroadcastResolver =
new FirewallIntentResolver();
static {
FilterFactory[] factories = new FilterFactory[] {
AndFilter.FACTORY,
OrFilter.FACTORY,
NotFilter.FACTORY,
StringFilter.ACTION,
StringFilter.COMPONENT,
StringFilter.COMPONENT_NAME,
StringFilter.COMPONENT_PACKAGE,
StringFilter.DATA,
StringFilter.HOST,
StringFilter.MIME_TYPE,
StringFilter.PATH,
StringFilter.SENDER_PACKAGE,
StringFilter.SSP,
CategoryFilter.FACTORY,
SenderFilter.FACTORY,
SenderPermissionFilter.FACTORY,
PortFilter.FACTORY
};
// load factor ~= .75
factoryMap = new HashMap<String, FilterFactory>(factories.length * 4 / 3);
for (int i=0; i<factories.length; i++) {
FilterFactory factory = factories[i];
factoryMap.put(factory.getTagName(), factory);
}
}
public IntentFirewall(AMSInterface ams) {
mAms = ams;
readRules(getRulesFile());
}
public boolean checkStartActivity(Intent intent, ApplicationInfo callerApp,
String callerPackage, int callerUid, int callerPid, String resolvedType,
ActivityInfo resolvedActivity) {
List<Rule> matchingRules = mActivityResolver.queryIntent(intent, resolvedType, false, 0);
boolean log = false;
boolean block = false;
for (int i=0; i< matchingRules.size(); i++) {
Rule rule = matchingRules.get(i);
if (rule.matches(this, intent, callerApp, callerPackage, callerUid, callerPid,
resolvedType, resolvedActivity.applicationInfo)) {
block |= rule.getBlock();
log |= rule.getLog();
// if we've already determined that we should both block and log, there's no need
// to continue trying rules
if (block && log) {
break;
}
}
}
if (log) {
// TODO: log info about intent to event log
}
return !block;
}
public static File getRulesFile() {
return RULES_FILE;
}
private void readRules(File rulesFile) {
FileInputStream fis;
try {
fis = new FileInputStream(rulesFile);
} catch (FileNotFoundException ex) {
// Nope, no rules. Nothing else to do!
return;
}
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, null);
XmlUtils.beginDocument(parser, TAG_RULES);
int outerDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
IntentResolver<FirewallIntentFilter, Rule> resolver = null;
String tagName = parser.getName();
if (tagName.equals(TAG_ACTIVITY)) {
resolver = mActivityResolver;
} else if (tagName.equals(TAG_SERVICE)) {
resolver = mServiceResolver;
} else if (tagName.equals(TAG_BROADCAST)) {
resolver = mBroadcastResolver;
}
if (resolver != null) {
Rule rule = new Rule();
try {
rule.readFromXml(parser);
} catch (XmlPullParserException ex) {
Slog.e(TAG, "Error reading intent firewall rule", ex);
continue;
} catch (IOException ex) {
Slog.e(TAG, "Error reading intent firewall rule", ex);
continue;
}
for (int i=0; i<rule.getIntentFilterCount(); i++) {
resolver.addFilter(rule.getIntentFilter(i));
}
}
}
} catch (XmlPullParserException ex) {
Slog.e(TAG, "Error reading intent firewall rules", ex);
} catch (IOException ex) {
Slog.e(TAG, "Error reading intent firewall rules", ex);
} finally {
try {
fis.close();
} catch (IOException ex) {
Slog.e(TAG, "Error while closing " + rulesFile, ex);
}
}
}
static Filter parseFilter(XmlPullParser parser) throws IOException, XmlPullParserException {
String elementName = parser.getName();
FilterFactory factory = factoryMap.get(elementName);
if (factory == null) {
throw new XmlPullParserException("Unknown element in filter list: " + elementName);
}
return factory.newFilter(parser);
}
private static class Rule extends AndFilter {
private static final String TAG_INTENT_FILTER = "intent-filter";
private static final String ATTR_BLOCK = "block";
private static final String ATTR_LOG = "log";
private final ArrayList<FirewallIntentFilter> mIntentFilters =
new ArrayList<FirewallIntentFilter>(1);
private boolean block;
private boolean log;
@Override
public Rule readFromXml(XmlPullParser parser) throws IOException, XmlPullParserException {
block = Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_BLOCK));
log = Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_LOG));
super.readFromXml(parser);
return this;
}
@Override
protected void readChild(XmlPullParser parser) throws IOException, XmlPullParserException {
if (parser.getName().equals(TAG_INTENT_FILTER)) {
FirewallIntentFilter intentFilter = new FirewallIntentFilter(this);
intentFilter.readFromXml(parser);
mIntentFilters.add(intentFilter);
} else {
super.readChild(parser);
}
}
public int getIntentFilterCount() {
return mIntentFilters.size();
}
public FirewallIntentFilter getIntentFilter(int index) {
return mIntentFilters.get(index);
}
public boolean getBlock() {
return block;
}
public boolean getLog() {
return log;
}
}
private static class FirewallIntentFilter extends IntentFilter {
private final Rule rule;
public FirewallIntentFilter(Rule rule) {
this.rule = rule;
}
}
private static class FirewallIntentResolver
extends IntentResolver<FirewallIntentFilter, Rule> {
@Override
protected boolean allowFilterResult(FirewallIntentFilter filter, List<Rule> dest) {
return !dest.contains(filter.rule);
}
@Override
protected boolean isPackageForFilter(String packageName, FirewallIntentFilter filter) {
return true;
}
@Override
protected FirewallIntentFilter[] newArray(int size) {
return new FirewallIntentFilter[size];
}
@Override
protected Rule newResult(FirewallIntentFilter filter, int match, int userId) {
return filter.rule;
}
@Override
protected void sortResults(List<Rule> results) {
// there's no need to sort the results
return;
}
}
/**
* This interface contains the methods we need from ActivityManagerService. This allows AMS to
* export these methods to us without making them public, and also makes it easier to test this
* component.
*/
public interface AMSInterface {
int checkComponentPermission(String permission, int pid, int uid,
int owningUid, boolean exported);
}
/**
* Checks if the caller has access to a component
*
* @param permission If present, the caller must have this permission
* @param pid The pid of the caller
* @param uid The uid of the caller
* @param owningUid The uid of the application that owns the component
* @param exported Whether the component is exported
* @return True if the caller can access the described component
*/
boolean checkComponentPermission(String permission, int pid, int uid, int owningUid,
boolean exported) {
return mAms.checkComponentPermission(permission, pid, uid, owningUid, exported) ==
PackageManager.PERMISSION_GRANTED;
}
boolean signaturesMatch(int uid1, int uid2) {
PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
return pm.checkUidSignatures(uid1, uid2) == PackageManager.SIGNATURE_MATCH;
}
}
组件IntentFirewall的作用
IntentFirewall是Android框架中的一个组件,它可以根据XML文件中定义的规则来控制Intent的发送和接收。Intent是Android中用于组件间通信和启动的一种消息对象,它可以携带动作、数据、类别等信息。IntentFirewall可以根据Intent的属性和调用者的信息,决定是否允许或拒绝Intent的传递,从而增强系统的安全性和灵活性。
主要功能主要有以下几条:
(1)过滤任何类型的Intent,包括Activity,Service,Broadcast和ContentProvider。
(2)动态更新过滤规则,无需重启系统。
(3)支持多种过滤条件,包括动作、数据、类别、组件、权限、用户、进程等。
(4)支持多种过滤动作,包括阻止、记录、修改和转发Intent。
代码逻辑如下:
根据提供的Android IntentFirewall源代码,概括了其主要逻辑如下:
-
定义相关常量和变量,包括规则文件路径、解析器等
-
构造函数中初始化解析器,并读取规则文件
-
checkStartActivity()方法检查启动Activity的Intent是否被阻止
-
readRules()方法读取并解析规则文件
-
parseFilter()解析过滤器标签
-
Rule类封装单条规则信息
-
FirewallIntentFilter类扩展IntentFilter表示规则Intent过滤器
-
FirewallIntentResolver类自定义的解析器实现
-
定义AMSInterface接口与AMS服务交互
-
checkComponentPermission()根据权限检查组件访问
-
signaturesMatch()检查两个UID签名是否匹配
综上,该类主要实现了一个基于规则的Android Intent防火墙,可以通过配置来过滤恶意的组件启动请求,保护应用安全。
详细解读具体代码逻辑
java
private static final String TAG = "IntentFirewall";
这行代码定义了一个私有的静态的最终的字符串常量,名为TAG,值为"IntentFirewall",用于作为日志的标签。
java
private static final File RULES_FILE =
new File(Environment.getSystemSecureDirectory(), "ifw/ifw.xml");
这行代码定义了一个私有的静态的最终的文件常量,名为RULES_FILE,值为一个File对象,用于表示规则文件的位置,它调用了Environment类的getSystemSecureDirectory方法,获取系统的安全目录,然后在该目录下创建一个名为"ifw/ifw.xml"的文件。
java
private static final String TAG_RULES = "rules";
private static final String TAG_ACTIVITY = "activity";
private static final String TAG_SERVICE = "service";
private static final String TAG_BROADCAST = "broadcast";
这块代码定义了四个私有的静态的最终的字符串常量,分别名为TAG_RULES,TAG_ACTIVITY,TAG_SERVICE,TAG_BROADCAST,值分别为为"rules","activity","service","broadcast",用于分别表示XML文件中的根元素的标签、活动类型的过滤规则的标签、服务类型的过滤规则的标签、广播类型的过滤规则的标签。这段代码是IntentFirewall类的一部分,用于定义一些常量和成员变量,它们分别用于表示日志的标签,规则文件的位置,XML文件中的元素的标签,过滤器工厂的映射,ActivityManagerService的接口,以及不同类型的过滤规则的解析器。
java
private static final HashMap<String, FilterFactory> factoryMap;
private final AMSInterface mAms;
private final IntentResolver<FirewallIntentFilter, Rule> mActivityResolver =
new FirewallIntentResolver();
private final IntentResolver<FirewallIntentFilter, Rule> mServiceResolver =
new FirewallIntentResolver();
private final IntentResolver<FirewallIntentFilter, Rule> mBroadcastResolver =
new FirewallIntentResolver();
private static final HashMap<String, FilterFactory> factoryMap;
这行代码定义了一个私有的静态的最终的哈希映射常量,名为factoryMap,类型为HashMap<String, FilterFactory>,用于存储过滤器工厂的对象,键为过滤器的名称,值为过滤器工厂的实例。private final AMSInterface mAms;
这行代码定义了一个私有的最终的接口变量,名为mAms,类型为AMSInterface,用于表示ActivityManagerService的接口,用于管理和调度系统中的四大组件。private final IntentResolver<FirewallIntentFilter, Rule> mActivityResolver = new FirewallIntentResolver();
这行代码定义了一个私有的最终的IntentResolver变量,名为mActivityResolver,类型为IntentResolver<FirewallIntentFilter, Rule>,值为一个FirewallIntentResolver对象,用于存储和查询活动类型的过滤规则。private final IntentResolver<FirewallIntentFilter, Rule> mServiceResolver = new FirewallIntentResolver();
这行代码定义了一个私有的最终的IntentResolver变量,名为mServiceResolver,类型为IntentResolver<FirewallIntentFilter, Rule>,值为一个FirewallIntentResolver对象,用于存储和查询服务类型的过滤规则。private final IntentResolver<FirewallIntentFilter, Rule> mBroadcastResolver = new FirewallIntentResolver();
这行代码定义了一个私有的最终的IntentResolver变量,名为mBroadcastResolver,类型为IntentResolver<FirewallIntentFilter, Rule>,值为一个FirewallIntentResolver对象,用于存储和查询广播类型的过滤规则。
这代码是IntentFirewall类的一部分,用于定义一些成员变量,它们分别用于表示过滤器工厂的映射,ActivityManagerService的接口,以及不同类型的过滤规则的解析器。
java
static {
FilterFactory[] factories = new FilterFactory[] {
AndFilter.FACTORY,
OrFilter.FACTORY,
NotFilter.FACTORY,
StringFilter.ACTION,
StringFilter.COMPONENT,
StringFilter.COMPONENT_NAME,
StringFilter.COMPONENT_PACKAGE,
StringFilter.DATA,
StringFilter.HOST,
StringFilter.MIME_TYPE,
StringFilter.PATH,
StringFilter.SENDER_PACKAGE,
StringFilter.SSP,
CategoryFilter.FACTORY,
SenderFilter.FACTORY,
SenderPermissionFilter.FACTORY,
PortFilter.FACTORY
};
static {
这行代码表示开始一个静态代码块,用于在类加载时执行一些初始化操作,只执行一次。FilterFactory[] factories = new FilterFactory[] {
这行代码定义了一个FilterFactory类型的数组,名为factories,用于存储所有可用的过滤器工厂的对象,过滤器工厂是用于创建和管理过滤器的类,过滤器是用于定义过滤条件的接口。AndFilter.FACTORY,
这行代码表示将AndFilter类的FACTORY常量添加到factories数组中,这是一个AndFilterFactory类型的对象,用于创建和管理AndFilter类型的过滤器,AndFilter是用于实现逻辑与操作的过滤器,它可以包含多个子过滤器,只有当所有子过滤器都匹配时,才返回true。OrFilter.FACTORY,
这行代码表示将OrFilter类的FACTORY常量添加到factories数组中,这是一个OrFilterFactory类型的对象,用于创建和管理OrFilter类型的过滤器,OrFilter是用于实现逻辑或操作的过滤器,它可以包含多个子过滤器,只要有一个子过滤器匹配,就返回true。NotFilter.FACTORY,
这行代码表示将NotFilter类的FACTORY常量添加到factories数组中,这是一个NotFilterFactory类型的对象,用于创建和管理NotFilter类型的过滤器,NotFilter是用于实现逻辑非操作的过滤器,它可以包含一个子过滤器,返回子过滤器的相反结果。StringFilter.ACTION,
这行代码表示将StringFilter类的ACTION常量添加到factories数组中,这是一个StringFilter类型的对象,用于创建和管理StringFilter类型的过滤器,StringFilter是用于匹配字符串属性的过滤器,它可以指定一个或多个字符串值,以及一个匹配模式,比如完全匹配,前缀匹配,后缀匹配,正则匹配等。ACTION常量表示匹配Intent的动作属性,比如android.intent.action.VIEW等。StringFilter.COMPONENT,
这行代码表示将StringFilter类的COMPONENT常量添加到factories数组中,这是一个StringFilter类型的对象,用于匹配Intent的组件属性,比如com.example.app.MainActivity等。StringFilter.COMPONENT_NAME,
这行代码表示将StringFilter类的COMPONENT_NAME常量添加到factories数组中,这是一个StringFilter类型的对象,用于匹配Intent的组件的名称属性,比如MainActivity等。StringFilter.COMPONENT_PACKAGE,
这行代码表示将StringFilter类的COMPONENT_PACKAGE常量添加到factories数组中,这是一个StringFilter类型的对象,用于匹配Intent的组件的包名属性,比如com.example.app等。StringFilter.DATA,
这行代码表示将StringFilter类的DATA常量添加到factories数组中,这是一个StringFilter类型的对象,用于匹配Intent的数据属性,比如http://www.example.com等。StringFilter.HOST,
这行代码表示将StringFilter类的HOST常量添加到factories数组中,这是一个StringFilter类型的对象,用于匹配Intent的数据的主机属性,比如www.example.com等。StringFilter.MIME_TYPE,
这行代码表示将StringFilter类的MIME_TYPE常量添加到factories数组中,这是一个StringFilter类型的对象,用于匹配Intent的数据的MIME类型属性,比如image/jpeg等。StringFilter.PATH,
这行代码表示将StringFilter类的PATH常量添加到factories数组中,这是一个StringFilter类型的对象,用于匹配Intent的数据的路径属性,比如/index.html等。StringFilter.SENDER_PACKAGE,
这行代码表示将StringFilter类的SENDER_PACKAGE常量添加到factories数组中,这是一个StringFilter类型的对象,用于匹配Intent的发送者的包名属性,比如com.example.sender等。StringFilter.SSP,
这行代码表示将StringFilter类的SSP常量添加到factories数组中,这是一个StringFilter类型的对象,用于匹配Intent的数据的方案特定部分(Scheme Specific Part)属性,比如//www.example.com/index.html等。CategoryFilter.FACTORY,
这行代码表示将CategoryFilter类的FACTORY常量添加到factories数组中,这是一个CategoryFilterFactory类型的对象,用于创建和管理CategoryFilter类型的过滤器,CategoryFilter是用于匹配Intent的类别属性的过滤器,它可以指定一个或多个类别值,比如android.intent.category.BROWSABLE等。SenderFilter.FACTORY,
这行代码表示将SenderFilter类的FACTORY常量添加到factories数组中,这是一个SenderFilterFactory类型的对象,用于创建和管理SenderFilter类型的过滤器,SenderFilter是用于匹配Intent的发送者的过滤器,它可以指定一个或多个用户ID,进程ID,应用信息等。SenderPermissionFilter.FACTORY,
这行代码表示将SenderPermissionFilter类的FACTORY常量添加到factories数组中,这是一个SenderPermissionFilterFactory类型的对象,用于创建和管理SenderPermissionFilter类型的过滤器,SenderPermissionFilter是用于匹配Intent的发送者的权限的过滤器,它可以指定一个或多个权限名称,以及是否需要强制执行等。PortFilter.FACTORY
这行代码表示将PortFilter类的FACTORY常量添加到factories数组中,这是一个PortFilterFactory类型的对象,用于创建和管理PortFilter类型的过滤器,PortFilter是用于匹配Intent的数据的端口属性的过滤器,它可以指定一个或多个端口范围,比如80-8080等。};
这行代码表示结束数组的初始化。
java
factoryMap = new HashMap<String, FilterFactory>(factories.length * 4 / 3);
for (int i=0; i<factories.length; i++) {
FilterFactory factory = factories[i];
factoryMap.put(factory.getTagName(), factory);
}
factoryMap = new HashMap<String, FilterFactory>(factories.length * 4 / 3);
这行代码创建了一个HashMap对象,指定键和值的类型为String和FilterFactory,分别表示过滤器的名称和实例,然后将其赋值给factoryMap常量,用于存储过滤器工厂的映射。这里使用了一个参数的构造方法,指定HashMap的初始容量为factories数组的长度乘以4除以3,这样做的目的是为了减少HashMap的扩容次数,提高性能。for (int i=0; i<factories.length; i++) {
这行代码开始一个for循环,用于遍历factories数组中的每个元素,每个元素都是一个FilterFactory对象,用于创建和管理过滤器。FilterFactory factory = factories[i];
这行代码定义了一个FilterFactory类型的变量,名为factory,然后将factories数组中的第i个元素赋值给它,表示当前的过滤器工厂对象。factoryMap.put(factory.getTagName(), factory);
这行代码调用factoryMap对象的put方法,将factory对象的getTagName方法返回的字符串作为键,将factory对象本身作为值,添加到factoryMap中,表示将过滤器的名称和实例映射起来。}
这行代码表示结束for循环。
java
public IntentFirewall(AMSInterface ams) {
mAms = ams;
readRules(getRulesFile());
}
用于获取规则文件的对象,它返回一个文件类型的常量,表示规则文件的位置。它调用了Environment类的getSystemSecureDirectory方法,获取系统的安全目录,然后在该目录下创建一个名为"ifw/ifw.xml"的文件。
java
private void readRules(File rulesFile) {
FileInputStream fis;
try {
fis = new FileInputStream(rulesFile);
} catch (FileNotFoundException ex) {
// Nope, no rules. Nothing else to do!
return;
}
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, null);
XmlUtils.beginDocument(parser, TAG_RULES);
int outerDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
IntentResolver<FirewallIntentFilter, Rule> resolver = null;
String tagName = parser.getName();
if (tagName.equals(TAG_ACTIVITY)) {
resolver = mActivityResolver;
} else if (tagName.equals(TAG_SERVICE)) {
resolver = mServiceResolver;
} else if (tagName.equals(TAG_BROADCAST)) {
resolver = mBroadcastResolver;
}
if (resolver != null) {
Rule rule = new Rule();
try {
rule.readFromXml(parser);
} catch (XmlPullParserException ex) {
Slog.e(TAG, "Error reading intent firewall rule", ex);
continue;
} catch (IOException ex) {
Slog.e(TAG, "Error reading intent firewall rule", ex);
continue;
}
for (int i=0; i<rule.getIntentFilterCount(); i++) {
resolver.addFilter(rule.getIntentFilter(i));
}
}
}
} catch (XmlPullParserException ex) {
Slog.e(TAG, "Error reading intent firewall rules", ex);
} catch (IOException ex) {
Slog.e(TAG, "Error reading intent firewall rules", ex);
} finally {
try {
fis.close();
} catch (IOException ex) {
Slog.e(TAG, "Error while closing " + rulesFile, ex);
}
}
}
- 这个方法的参数是一个File类型的对象,表示存储过滤规则的XML文件。
- 这个方法首先定义了一个FileInputStream类型的变量,用于读取文件的内容,然后使用一个try-catch语句,尝试创建一个FileInputStream对象,如果发生FileNotFoundException异常,就表示没有找到规则文件,就直接返回。
- 然后使用另一个try-catch-finally语句,尝试解析文件的内容,如果发生XmlPullParserException或IOException异常,就表示读取过滤规则时出错,就打印一条错误信息,最后无论是否发生异常,都尝试关闭文件输入流,如果发生IOException异常,就表示关闭文件时出错,就打印一条错误信息。
- 在try语句中,创建一个XmlPullParser对象,用于解析XML文件的内容,然后设置输入源为文件输入流,使用默认的编码格式,然后开始解析XML文件,并检查根元素的标签是否为rules。
- 然后获取XML文件的初始深度,然后使用一个while循环,在当前深度范围内,查找下一个元素的开始标签,如果找到,就继续循环,否则,就跳出循环。
- 在循环中,根据当前元素的标签名,选择相应的IntentResolver对象,用于存储和查询不同类型的过滤规则,如果找到了匹配的IntentResolver对象,就创建一个Rule对象,用于存储当前元素的过滤规则,然后使用一个try-catch语句,尝试从当前元素的属性和子元素中读取过滤规则的条件和动作,如果发生异常,就打印一条错误信息,然后继续循环。
- 在try语句中,使用一个for循环,遍历Rule对象的所有IntentFilter对象,每个IntentFilter对象都是一个FirewallIntentFilter类型的实例,用于定义过滤规则的匹配条件,比如动作、类别、数据等,然后将每个IntentFilter对象添加到IntentResolver中,用于后续的过滤和查询。
这段代码是IntentFirewall类的一个私有方法,用于从文件中读取过滤规则,并将其添加到相应的IntentResolver中,它使用了XmlPullParser对象来解析XML文件的内容,然后使用Rule对象和IntentFilter对象来存储和管理过滤规则的条件和动作。
java
static Filter parseFilter(XmlPullParser parser) throws IOException, XmlPullParserException {
String elementName = parser.getName();
FilterFactory factory = factoryMap.get(elementName);
if (factory == null) {
throw new XmlPullParserException("Unknown element in filter list: " + elementName);
}
return factory.newFilter(parser);
}
- 这个方法的参数是一个XmlPullParser类型的对象,表示用于解析XML文件的解析器,它抛出了IOException和XmlPullParserException两种异常,表示可能发生的输入输出错误和解析错误。
- 这个方法的返回值是一个Filter类型的对象,表示根据XML文件中的元素创建的过滤器,过滤器是用于定义过滤条件的接口。
- 这个方法首先调用parser对象的getName方法,获取当前元素的标签名,然后将其赋值给一个字符串变量,名为elementName。
- 然后使用factoryMap对象的get方法,根据elementName作为键,从哈希映射中获取对应的值,这个值是一个FilterFactory类型的对象,表示用于创建和管理过滤器的工厂,然后将其赋值给一个FilterFactory类型的变量,名为factory。
- 如果factory变量为null,表示没有找到匹配的过滤器工厂,就抛出一个XmlPullParserException异常,表示在过滤器列表中存在未知的元素,异常的信息包含了elementName的值。
- 如果factory变量不为null,表示找到了匹配的过滤器工厂,就调用factory对象的newFilter方法,传入parser对象作为参数,从当前元素的属性和子元素中创建一个新的过滤器对象,然后将其返回。
这段代码是一个静态的方法,用于根据XML文件中的元素创建一个过滤器对象,它使用了一个哈希映射来存储过滤器工厂的映射,然后根据元素的标签名来查找和创建过滤器,如果没有找到匹配的过滤器工厂,就抛出一个异常。
java
private static class Rule extends AndFilter {
private static final String TAG_INTENT_FILTER = "intent-filter";
private static final String ATTR_BLOCK = "block";
private static final String ATTR_LOG = "log";
private final ArrayList<FirewallIntentFilter> mIntentFilters =
new ArrayList<FirewallIntentFilter>(1);
private boolean block;
private boolean log;
@Override
public Rule readFromXml(XmlPullParser parser) throws IOException, XmlPullParserException {
block = Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_BLOCK));
log = Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_LOG));
super.readFromXml(parser);
return this;
}
@Override
protected void readChild(XmlPullParser parser) throws IOException, XmlPullParserException {
if (parser.getName().equals(TAG_INTENT_FILTER)) {
FirewallIntentFilter intentFilter = new FirewallIntentFilter(this);
intentFilter.readFromXml(parser);
mIntentFilters.add(intentFilter);
} else {
super.readChild(parser);
}
}
public int getIntentFilterCount() {
return mIntentFilters.size();
}
public FirewallIntentFilter getIntentFilter(int index) {
return mIntentFilters.get(index);
}
public boolean getBlock() {
return block;
}
public boolean getLog() {
return log;
}
}
- 这段代码定义了一个私有的静态的内部类,名为Rule,继承了AndFilter类,用于表示一个过滤规则,包括过滤条件和过滤动作。
- 这个类定义了两个私有的静态的最终的字符串常量,分别是TAG_INTENT_FILTER和ATTR_BLOCK,值分别是"intent-filter"和"block",用于表示XML文件中的元素的标签和属性。
- 这个类定义了另外两个私有的静态的最终的字符串常量,分别是ATTR_LOG和ATTR_BLOCK,值分别是"log"和"block",用于表示XML文件中的元素的属性。
- 这个类定义了一个私有的最终的ArrayList变量,名为mIntentFilters,类型为ArrayList,值为一个新的ArrayList对象,用于存储过滤规则的所有IntentFilter对象,IntentFilter对象是用于定义过滤条件的对象,比如动作、类别、数据等。
- 这个类定义了两个私有的布尔变量,分别是block和log,用于表示过滤动作,block为true表示阻止Intent的传递,log为true表示记录Intent的信息。
- 这个类重写了AndFilter类的readFromXml方法,用于从XML文件中读取过滤规则的条件和动作,它接收一个XmlPullParser类型的参数,表示用于解析XML文件的解析器,它抛出了IOException和XmlPullParserException两种异常,表示可能发生的输入输出错误和解析错误。
- 这个方法首先调用parser对象的getAttributeValue方法,传入null和ATTR_BLOCK作为参数,获取当前元素的block属性的值,然后使用Boolean类的parseBoolean方法,将字符串值转换为布尔值,然后赋值给block变量。
- 然后调用parser对象的getAttributeValue方法,传入null和ATTR_LOG作为参数,获取当前元素的log属性的值,然后使用Boolean类的parseBoolean方法,将字符串值转换为布尔值,然后赋值给log变量。
- 然后调用父类的readFromXml方法,传入parser对象作为参数,从当前元素的子元素中读取过滤条件,比如AndFilter,OrFilter,NotFilter,StringFilter等,然后将它们添加到过滤条件的列表中。
- 最后,返回当前的Rule对象,表示读取完成。
- readChild:重写了AndFilter类的readChild方法,用于从XML文件中读取过滤规则的子元素,它接收一个XmlPullParser类型的参数,表示用于解析XML文件的解析器,它抛出了IOException和XmlPullParserException两种异常,表示可能发生的输入输出错误和解析错误。
这个方法首先判断当前元素的标签名是否等于TAG_INTENT_FILTER常量,这是一个字符串常量,值为"intent-filter",用于表示XML文件中的IntentFilter元素的标签,IntentFilter元素是用于定义过滤条件的元素,比如动作、类别、数据等。
如果当前元素的标签名等于TAG_INTENT_FILTER常量,就表示当前元素是一个IntentFilter元素,就创建一个FirewallIntentFilter类型的对象,名为intentFilter,传入当前的Rule对象作为参数,表示这个IntentFilter属于这个Rule,然后调用intentFilter对象的readFromXml方法,传入parser对象作为参数,从当前元素的属性和子元素中读取IntentFilter的内容,然后将intentFilter对象添加到mIntentFilters变量中,这是一个ArrayList类型的变量,用于存储当前Rule的所有IntentFilter对象。
如果当前元素的标签名不等于TAG_INTENT_FILTER常量,就表示当前元素是一个其他类型的过滤条件元素,比如AndFilter,OrFilter,NotFilter,StringFilter等,就调用父类的readChild方法,传入parser对象作为参数,从当前元素的属性和子元素中读取过滤条件的内容,然后将它们添加到过滤条件的列表中。总结:用于从XML文件中读取过滤规则的子元素,它根据当前元素的标签名,判断是一个IntentFilter元素还是一个其他类型的过滤条件元素,然后分别处理它们,将它们添加到当前Rule的过滤条件的列表中。
这段代码是一个私有的静态的内部类,是一个表示过滤规则的类,它继承了AndFilter类,定义了过滤条件和过滤动作,可以从XML文件中读取和创建。
java
private static class FirewallIntentFilter extends IntentFilter {
private final Rule rule;
public FirewallIntentFilter(Rule rule) {
this.rule = rule;
}
}
- 这段代码定义了一个私有的静态的内部类,名为FirewallIntentFilter,继承了IntentFilter类,用于表示一个过滤器,它可以匹配Intent的属性,比如动作、类别、数据等。
- 这个类定义了一个私有的最终的Rule类型的变量,名为rule,用于表示这个过滤器所属的过滤规则,过滤规则是用于定义过滤条件和过滤动作的类,比如阻止或记录Intent的传递。
- 这个类定义了一个公共的构造方法,接收一个Rule类型的参数,表示要创建的过滤器所属的过滤规则,然后将其赋值给rule变量,表示初始化过滤器的状态。
这段代码是一个私有的静态的内部类,用于表示一个过滤器,它继承了IntentFilter类,定义了一个过滤规则的变量,提供了一个构造方法,用于创建和初始化过滤器的对象。
java
private static class FirewallIntentResolver
extends IntentResolver<FirewallIntentFilter, Rule> {
@Override
protected boolean allowFilterResult(FirewallIntentFilter filter, List<Rule> dest) {
return !dest.contains(filter.rule);
}
@Override
protected boolean isPackageForFilter(String packageName, FirewallIntentFilter filter) {
return true;
}
@Override
protected FirewallIntentFilter[] newArray(int size) {
return new FirewallIntentFilter[size];
}
@Override
protected Rule newResult(FirewallIntentFilter filter, int match, int userId) {
return filter.rule;
}
@Override
protected void sortResults(List<Rule> results) {
// there's no need to sort the results
return;
}
}
这个类重写了IntentResolver类的以下方法:
allowFilterResult
:用于判断是否允许将过滤器的结果添加到目标列表中,它接收一个FirewallIntentFilter类型的参数,表示要添加的过滤器,和一个List类型的参数,表示目标列表,它返回一个布尔值,表示是否允许添加。这个方法的逻辑是,如果目标列表中已经包含了过滤器所属的规则,就返回false,表示不允许重复添加,否则,就返回true,表示允许添加。isPackageForFilter
:用于判断一个包名是否适用于一个过滤器,它接收一个字符串类型的参数,表示要判断的包名,和一个FirewallIntentFilter类型的参数,表示要判断的过滤器,它返回一个布尔值,表示是否适用。这个方法的逻辑是,直接返回true,表示任何包名都适用于任何过滤器,不需要进行过滤。newArray
:用于创建一个指定大小的FirewallIntentFilter类型的数组,它接收一个整数类型的参数,表示要创建的数组的大小,它返回一个FirewallIntentFilter类型的数组,表示创建的数组。这个方法的逻辑是,使用new关键字,创建一个FirewallIntentFilter类型的数组,传入size参数作为数组的长度,然后返回这个数组。newResult
:用于创建一个新的过滤规则的结果,它接收一个FirewallIntentFilter类型的参数,表示匹配的过滤器,一个整数类型的参数match,表示匹配的结果,和一个整数类型的参数userId,表示用户的ID,它返回一个Rule类型的对象,表示创建的结果。这个方法的逻辑是,直接返回过滤器所属的规则,表示这个规则是匹配的结果。sortResults
:用于对过滤规则的结果进行排序,它接收一个List类型的参数,表示要排序的结果列表,它没有返回值。这个方法的逻辑是,直接返回,表示不需要对结果进行排序。
这是IntentFirewall类的一个私有的静态的内部类,用于存储和查询不同类型的过滤规则,它重写了IntentResolver类的一些方法,用于实现自定义的过滤逻辑。
java
public interface AMSInterface {
int checkComponentPermission(String permission, int pid, int uid,
int owningUid, boolean exported);
}
这个接口定义了一个方法,名为checkComponentPermission,用于检查一个组件的权限,它接收以下参数:
- permission:一个字符串类型的参数,表示要检查的权限的名称,比如android.permission.INTERNET等。
- pid:一个整数类型的参数,表示要检查的进程的ID,比如1234等。
- uid:一个整数类型的参数,表示要检查的用户的ID,比如1000等。
- owningUid:一个整数类型的参数,表示拥有该组件的用户的ID,比如1001等。
- exported:一个布尔类型的参数,表示该组件是否是可导出的,即是否可以被其他应用访问,比如true或false等。
这个方法的返回值是一个整数类型的值,表示检查的结果,比如PackageManager.PERMISSION_GRANTED表示允许访问,PackageManager.PERMISSION_DENIED表示拒绝访问等。
这是是一个公共的接口,用于表示ActivityManagerService的接口,它定义了一个方法,用于检查一个组件的权限,它接收一些参数,表示要检查的权限、进程、用户、组件等信息,它返回一个值,表示检查的结果。
java
boolean checkComponentPermission(String permission, int pid, int uid, int owningUid,
boolean exported) {
return mAms.checkComponentPermission(permission, pid, uid, owningUid, exported) ==
PackageManager.PERMISSION_GRANTED;
}
java
boolean signaturesMatch(int uid1, int uid2) {
PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
return pm.checkUidSignatures(uid1, uid2) == PackageManager.SIGNATURE_MATCH;
}
这是ntentFirewall类的两个私有方法,用于检查组件的权限和签名,它们分别是:
checkComponentPermission
:用于检查一个组件的权限,它接收一个字符串类型的参数,表示要检查的权限的名称,和四个整数类型的参数,分别表示要检查的进程的ID,用户的ID,拥有该组件的用户的ID,以及该组件是否是可导出的,它返回一个布尔值,表示是否允许访问。这个方法的逻辑是,调用mAms对象的checkComponentPermission方法,传入相同的参数,然后判断返回值是否等于PackageManager.PERMISSION_GRANTED常量,这是一个整数常量,表示允许访问的结果,如果相等,就返回true,否则,就返回false。mAms对象是一个AMSInterface类型的变量,表示ActivityManagerService的接口,用于管理和调度系统中的四大组件。signaturesMatch
:用于检查两个用户的签名是否匹配,它接收两个整数类型的参数,分别表示要检查的两个用户的ID,它返回一个布尔值,表示是否匹配。这个方法的逻辑是,定义一个PackageManagerService类型的变量,名为pm,然后调用ServiceManager类的getService方法,传入一个字符串常量,表示要获取的服务的名称,这个常量是"package",表示要获取的是PackageManagerService,这是一个用于管理和安装应用的服务,然后将返回值强制转换为PackageManagerService类型,然后赋值给pm变量。然后调用pm对象的checkUidSignatures方法,传入两个用户的ID作为参数,然后判断返回值是否等于PackageManager.SIGNATURE_MATCH常量,这是一个整数常量,表示签名匹配的结果,如果相等,就返回true,否则,就返回false。
这两个方法用于检查组件的权限和签名的方法,它们分别调用ActivityManagerService和PackageManagerService的接口,然后根据返回值判断是否允许访问或匹配。