简单介绍一下Android里面的IntentFirewall

news/2024/5/17 16:55:04 标签: android, gitee

源码链接

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.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防火墙,可以通过配置来过滤恶意的组件启动请求,保护应用安全。

详细解读具体代码逻辑

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;
        @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文件中读取和创建。

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 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类的一些方法,用于实现自定义的过滤逻辑。

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


http://www.niftyadmin.cn/n/5391406.html

相关文章

R语言入门笔记2.6

描述统计 分类数据与顺序数据的图表展示 为了下面代码便于看出颜色参数所对应的值&#xff0c;在这里先集中介绍&#xff0c; col1是黑色&#xff0c;2是粉红&#xff0c;3是绿色&#xff0c;4是天蓝&#xff0c;5是浅蓝&#xff0c;6是紫红&#xff0c;7是黄色&#xff0c;…

Golang Redis:构建高效和可扩展的应用程序

利用Redis的闪电般的数据存储和Golang的无缝集成解锁协同效应 在当前的应用程序开发中&#xff0c;高效的数据存储和检索的必要性已经变得至关重要。Redis&#xff0c;作为一个闪电般快速的开源内存数据结构存储方案&#xff0c;为各种应用场景提供了可靠的解决方案。在这份完…

简单封装axios

目录 一、代码解读二、整体代码 一、代码解读 import axios from ‘axios’; 创建一个名为 instance 的 Axios 实例&#xff0c;配置默认的请求地址和超时时间 const instance axios.create({baseURL: http://localhost:8085,timeout: 5000, });请求拦截器&#xff0c;用于…

vue 项目打包图片没有打包进去问题解决

问题 vue 项目打包&#xff0c;项目中引用了的图片没有被打进包里&#xff0c;导致打包后的项目图片缺失。 解决方法 1、在导入图片的文件中通过 import 引入图片 这种方法只适合图片少的情况 <template><img :srctestImg/> </template><script>i…

C#,动态规划(DP)模拟退火(Simulated Annealing)算法与源代码

1 模拟退火 *问题:**给定一个成本函数f:r^n–>r*&#xff0c;找到一个 n 元组&#xff0c;该元组最小化 f 的值。请注意&#xff0c;最小化函数值在算法上等同于最大化(因为我们可以将成本函数重新定义为 1-f)。 很多有微积分/分析背景的人可能都熟悉单变量函数的简单优化。…

Redis如何修改key名称

点击上方蓝字关注我 近期出现过多次修改Redis中key名字的场景&#xff0c;本次简介一下如何修改Redis中key名称的方法。 1. 命令行方式修改在Redis中&#xff0c;可以使用rename命令来修改Key的名称。这个命令的基本语法如下&#xff1a; RENAME old_key new_key 在这里&#…

Docker 第十九章 : 阿里云个人镜像仓使用

Docker 第十九章 : 阿里云个人镜像仓使用 本章知识点: 如何创建镜像库,如何设置密码,如何登录与退出个人镜像仓,如何本地打镜像,如何将本地镜像推送到个人镜像库。 背景 在项目YapiDocker部署中,因读取mongo:latest 版本不一致,导致后续执行步骤的异常。遇到此场景…

1.手写IOC实现Bean创建过程

1.创建子模块 2.创建测试类 &#xff08;service dao&#xff09; 3.创建两个注解 Bean 创建对象 DI 属性注入 4.创建Bean容器接口ApplicationCOntext&#xff0c;定义方法 5.实现bean 容器接口&#xff0c;根据包规则扫描加载Bean&#xff0c;这是在实现Bean。对于Di来说…