简单介绍一下Android里面的IntentFirewall
源码链接
https://android.googlesource.com/platform/frameworks/base/+/633dc9b/services/java/com/android/server/firewall/IntentFirewall.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.xmlprivate 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 ~= .75factoryMap = 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 rulesif (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;@Overridepublic 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;}@Overrideprotected 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 FirewallIntentResolverextends IntentResolver<FirewallIntentFilter, Rule> {@Overrideprotected boolean allowFilterResult(FirewallIntentFilter filter, List<Rule> dest) {return !dest.contains(filter.rule);}@Overrideprotected boolean isPackageForFilter(String packageName, FirewallIntentFilter filter) {return true;}@Overrideprotected FirewallIntentFilter[] newArray(int size) {return new FirewallIntentFilter[size];}@Overrideprotected Rule newResult(FirewallIntentFilter filter, int match, int userId) {return filter.rule;}@Overrideprotected void sortResults(List<Rule> results) {// there's no need to sort the resultsreturn;}}/*** 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防火墙,可以通过配置来过滤恶意的组件启动请求,保护应用安全。
详细解读具体代码逻辑
private static final String TAG = "IntentFirewall";
这行代码定义了一个私有的静态的最终的字符串常量,名为TAG,值为"IntentFirewall",用于作为日志的标签。
private static final File RULES_FILE =new File(Environment.getSystemSecureDirectory(), "ifw/ifw.xml");
这行代码定义了一个私有的静态的最终的文件常量,名为RULES_FILE,值为一个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";
这块代码定义了四个私有的静态的最终的字符串常量,分别名为TAG_RULES,TAG_ACTIVITY,TAG_SERVICE,TAG_BROADCAST,值分别为为"rules",“activity”,“service”,“broadcast”,用于分别表示XML文件中的根元素的标签、活动类型的过滤规则的标签、服务类型的过滤规则的标签、广播类型的过滤规则的标签。这段代码是IntentFirewall类的一部分,用于定义一些常量和成员变量,它们分别用于表示日志的标签,规则文件的位置,XML文件中的元素的标签,过滤器工厂的映射,ActivityManagerService的接口,以及不同类型的过滤规则的解析器。
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的接口,以及不同类型的过滤规则的解析器。
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等。};
这行代码表示结束数组的初始化。
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循环。
public IntentFirewall(AMSInterface ams) {mAms = ams;readRules(getRulesFile());}
用于获取规则文件的对象,它返回一个文件类型的常量,表示规则文件的位置。它调用了Environment类的getSystemSecureDirectory方法,获取系统的安全目录,然后在该目录下创建一个名为"ifw/ifw.xml"的文件。
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对象来存储和管理过滤规则的条件和动作。
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文件中的元素创建一个过滤器对象,它使用了一个哈希映射来存储过滤器工厂的映射,然后根据元素的标签名来查找和创建过滤器,如果没有找到匹配的过滤器工厂,就抛出一个异常。
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;@Overridepublic 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;}@Overrideprotected 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文件中读取和创建。
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类,定义了一个过滤规则的变量,提供了一个构造方法,用于创建和初始化过滤器的对象。
private static class FirewallIntentResolverextends IntentResolver<FirewallIntentFilter, Rule> {@Overrideprotected boolean allowFilterResult(FirewallIntentFilter filter, List<Rule> dest) {return !dest.contains(filter.rule);}@Overrideprotected boolean isPackageForFilter(String packageName, FirewallIntentFilter filter) {return true;}@Overrideprotected FirewallIntentFilter[] newArray(int size) {return new FirewallIntentFilter[size];}@Overrideprotected Rule newResult(FirewallIntentFilter filter, int match, int userId) {return filter.rule;}@Overrideprotected void sortResults(List<Rule> results) {// there's no need to sort the resultsreturn;}}
这个类重写了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类的一些方法,用于实现自定义的过滤逻辑。
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的接口,它定义了一个方法,用于检查一个组件的权限,它接收一些参数,表示要检查的权限、进程、用户、组件等信息,它返回一个值,表示检查的结果。
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;}
这是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的接口,然后根据返回值判断是否允许访问或匹配。
相关文章:
简单介绍一下Android里面的IntentFirewall
源码链接 https://android.googlesource.com/platform/frameworks/base//633dc9b/services/java/com/android/server/firewall/IntentFirewall.java 源码如下: package com.android.server.firewall; import android.content.Intent; import android.content.Inte…...

Stable Diffusion 3 发布及其重大改进
1. 引言 就在 OpenAI 发布可以生成令人瞠目的视频的 Sora 和谷歌披露支持多达 150 万个Token上下文的 Gemini 1.5 的几天后,Stability AI 最近展示了 Stable Diffusion 3 的预览版。 闲话少说,我们快来看看吧! 2. 什么是Stable Diffusion…...
【后端】springboot项目
文章目录 1. 2.3.7.RELEASE版本搭建1.1 pom文件1.1.1 方式一1.1.2 方式二 1.2 启动类1.3 测试类 2. 引入Value乱码问题解决 【后端目录贴】 1. 2.3.7.RELEASE版本搭建 1.1 pom文件 1.1.1 方式一 <parent><groupId>org.springframework.boot</groupId><…...
React Native调用摄像头画面及拍照和保存图片到相册全流程
今天主要做了一个demo,功能很简单,就是调用手机摄像头画面,并且可以通过按钮控制拍照以及将图片保存到手机相册的功能,接下来我将从创建项目开始一步一步完成这个demo,各位只需要复制粘贴即可 创建React Native项目 npx react-native init yx_rnDemo --version 0.70.6 // 这里…...
Kubernetes基本部署概念
文章目录 命名空间(Namespaecs)查看命名空间查看带有命名空间对象下资源 文件存储持久卷(pv,Persistent Volumes)卷容量卷模式(volumeMode)访问模式(accessModes)回收策略…...
QT c++ 海康红外热像仪
//本文描述2通道海康通道红外热像仪预览和抓图 #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); userID-1; …...

OpenAI 的 GPTs 提示词泄露攻击与防护实战:防御卷(一)
前面的OpenAI DevDay活动上,GPTs技术的亮相引起了广泛关注。随着GPTs的创建权限开放给Plus用户,社区里迅速涌现了各种有趣的GPT应用,这些都是利用了Prompt提示词的灵活性。这不仅展示了技术的创新潜力,也让人们开始思考如何获取他…...

中科大计网学习记录笔记(十五):可靠数据传输的原理
前前言:看过本节的朋友应该都知道本节长度长的吓人,但其实内容含量和之前的差不多,老师在本节课举的例子和解释比较多,所以大家坚持看完是一定可以理解透彻的。本节课大部分是在提出问题和解决问题,先明确出现的问题是…...

五种多目标优化算法(MOGWO、MOJS、NSWOA、MOPSO、MOAHA)性能对比(提供MATLAB代码)
一、5种多目标优化算法简介 1.1MOGWO 1.2MOJS 1.3NSWOA 1.4MOPSO 1.5MOAHA 二、5种多目标优化算法性能对比 为了测试5种算法的性能将其求解9个多目标测试函数(zdt1、zdt2 、zdt3、 zdt4、 zdt6 、Schaffer、 Kursawe 、Viennet2、 Viennet3)࿰…...
力扣:93. 复原 IP 地址
回溯: 1.先定义一个接收的集合,之后再定义一个记录小数点的变量。之后编写回溯函数,终止条件为小数点的个数为3时,同时要判断最后一段的组合的值是否属于ip地址的范围。之后再用for循环来遍历ip地址的组合,先判断组合…...
利用序列化和反序列化实现深拷贝
利用序列化和反序列化可以实现对象的深拷贝,具体步骤如下: 将要深拷贝的对象序列化为字节流。从字节流中反序列化出一个新的对象,即完成了深拷贝。下面是一个示例代码: import java.io.*;class MyClass implements Serializable {private static final long serialVersion…...
【AHK】68键键盘键位布局优化/esc改退格键/回车键
本人习惯使用~作为退格键,但是由于keychron 68键的布局只能用esc平替~来修改,然后也将回车键通过alt和大小写锁定键一起触发 esc::bs ;次步骤与下面步骤相对应,如果是用send bs方式则下面的不生效^esc:: ;通过建立 保留esc功能 send {esc} re…...

计算机体系架构初步入门
🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:高性能(HPC)开发基础教程 🎀CSDN主页 发狂的小花 🌄人生秘诀:学习的本质就是极致重复! 目录 1 计算机五大…...
常见的序列化数据结构方法及其优缺点汇总
文章目录 1. JSON (JavaScript Object Notation)2. XML (eXtensible Markup Language)3. YAML (YAML Aint Markup Language)4. Protobuf (Protocol Buffers)5. MessagePack6. BSON (Binary JSON)7. Avro8. Thrift9. CBOR (Concise Binary Object Representation) 将常见的序列化…...

华清远见嵌入式学习——驱动开发——作业1
作业要求: 通过字符设备驱动分步注册过程实现LED驱动的编写,编写应用程序测试,发布到CSDN 作业答案: 运行效果: 驱动代码: #include <linux/init.h> #include <linux/module.h> #include &l…...

小苯的IDE括号问题(CD) -----牛客小白月赛87(双链表)
C题:C-小苯的IDE括号问题(easy)_牛客小白月赛87 (nowcoder.com) D题: D-小苯的IDE括号问题(hard)_牛客小白月赛87 (nowcoder.com) C题代码: #include<bits/stdc.h>using namespace std…...

Redis如何修改key名称
点击上方蓝字关注我 近期出现过多次修改Redis中key名字的场景,本次简介一下如何修改Redis中key名称的方法。 1. 命令行方式修改在Redis中,可以使用rename命令来修改Key的名称。这个命令的基本语法如下: RENAME old_key new_key 在这里&#…...
浅谈redis之SDS
SDS 什么是SDSSDS结构len的作用free的作用buf的作用简单示例 SDS机制重新分配内存分配内存机制小于1MB情况大于1MB情况为什么这样分配 惰性释放内存 什么是SDS SDS:全名 simple dynamic string,意为简单动态字符串,作为redis里的一种数据结构…...

数据结构知识点总结-线性表(1)-线性表的定义、基本操作、顺序表表示
线性表 定义 线性表是具有相同数据类型的N(N>0)个元素的有限序列,其中N为表长,当N0时线性表是一张空表。 线性表的逻辑特征:每个非空的线性表都有一个表头元素和表尾元素,中间的每个元素有且仅有一个直…...

Spring Boot 手写starter!!!
原因:为什么要手写starter??? 原因:简化功能。 实例:以分页为例:写一个starter。 1.首先定义一个PageX注解。 Target({ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Documented p…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...

AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...