简单介绍一下Android里面的IntentFirewall

源码链接

https://android.googlesource.com/platform/frameworks/base/+/633dc9b/services/java/com/android/server/firewall/IntentFirewall.java
源码如下:

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源代码,概括了其主要逻辑如下:

  1. 定义相关常量和变量,包括规则文件路径、解析器等

  2. 构造函数中初始化解析器,并读取规则文件

  3. checkStartActivity()方法检查启动Activity的Intent是否被阻止

  4. readRules()方法读取并解析规则文件

  5. parseFilter()解析过滤器标签

  6. Rule类封装单条规则信息

  7. FirewallIntentFilter类扩展IntentFilter表示规则Intent过滤器

  8. FirewallIntentResolver类自定义的解析器实现

  9. 定义AMSInterface接口与AMS服务交互

  10. checkComponentPermission()根据权限检查组件访问

  11. 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的接口,然后根据返回值判断是否允许访问或匹配。

相关推荐
网络研究院2 小时前
Android 安卓内存安全漏洞数量大幅下降的原因
android·安全·编程·安卓·内存·漏洞·技术
凉亭下2 小时前
android navigation 用法详细使用
android
小比卡丘5 小时前
C语言进阶版第17课—自定义类型:联合和枚举
android·java·c语言
前行的小黑炭6 小时前
一篇搞定Android 实现扫码支付:如何对接海外的第三方支付;项目中的真实经验分享;如何高效对接,高效开发
android
落落落sss7 小时前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
代码敲上天.8 小时前
数据库语句优化
android·数据库·adb
GEEKVIP10 小时前
手机使用技巧:8 个 Android 锁屏移除工具 [解锁 Android]
android·macos·ios·智能手机·电脑·手机·iphone
model200512 小时前
android + tflite 分类APP开发-2
android·分类·tflite
彭于晏68912 小时前
Android广播
android·java·开发语言
与衫13 小时前
掌握嵌套子查询:复杂 SQL 中 * 列的准确表列关系
android·javascript·sql