Android 11----SystemConfig.java解析

SystemConfig.java是PKMS里一个很重要的类,用来解析一些系统配置信息的,然后将解析的结果赋值给SystemConfig里的各个数据结构,供我们查询。首先看一下它的构造方法(在PKMS的构造方法里最终会通过调用SystemConfig的构造方法去解析配置文件):

frameworks/base/core/java/com/android/server/SystemConfig.java
    SystemConfig() {
        TimingsTraceLog log = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
        log.traceBegin("readAllPermissions");
        try {
            readAllPermissions();
        } finally {
            log.traceEnd();
        }
    }

调用readAllPermissions()方法读取系统配置。

    private void readAllPermissions() {
        // Read configuration from system
        readPermissions(Environment.buildPath(
                Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);//读取system/etc/sysconfig目录

        // Read configuration from the old permissions dir
        readPermissions(Environment.buildPath(
                Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);//读取system/etc/permissions目录

        // Vendors are only allowed to customize these
        int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
                | ALLOW_ASSOCIATIONS;
        if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
            // For backward compatibility
            vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
        }
        readPermissions(Environment.buildPath(
                Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);//读取vendor/etc/sysconfig目录
        readPermissions(Environment.buildPath(
                Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);//读取vendor/etc/permissions目录

        String vendorSkuProperty = SystemProperties.get(VENDOR_SKU_PROPERTY, "");//vendor/etc/vintf/manifest_SKU.xml里如果定义了SKU,那么SKU就是属性 ro.boot.product.vendor.sku的值,按照这个值去读取对应的目录
        if (!vendorSkuProperty.isEmpty()) {
            String vendorSkuDir = "sku_" + vendorSkuProperty;
            readPermissions(Environment.buildPath(
                    Environment.getVendorDirectory(), "etc", "sysconfig", vendorSkuDir),
                    vendorPermissionFlag);
            readPermissions(Environment.buildPath(
                    Environment.getVendorDirectory(), "etc", "permissions", vendorSkuDir),
                    vendorPermissionFlag);
        }

        // Allow ODM to customize system configs as much as Vendor, because /odm is another
        // vendor partition other than /vendor.
        int odmPermissionFlag = vendorPermissionFlag;
        readPermissions(Environment.buildPath(
                Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);//读取odm/etc/sysconfig目录
        readPermissions(Environment.buildPath(
                Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);//读取odm/etc/permissions目录

        String skuProperty = SystemProperties.get(SKU_PROPERTY, "");//odm/etc/vintf/manifest_SKU.xml里如果定义了SKU,那么SKU就是属性 ro.boot.product.hardware.sku 的值,按照这个值去读取对应的目录
        if (!skuProperty.isEmpty()) {
            String skuDir = "sku_" + skuProperty;

            readPermissions(Environment.buildPath(
                    Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
            readPermissions(Environment.buildPath(
                    Environment.getOdmDirectory(), "etc", "permissions", skuDir),
                    odmPermissionFlag);
        }

        // Allow OEM to customize these
        int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
        readPermissions(Environment.buildPath(
                Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);//读取oem/etc/sysconfig目录
        readPermissions(Environment.buildPath(
                Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);//读取oem/etc/permissions目录

        // Allow Product to customize all system configs
        readPermissions(Environment.buildPath(
                Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);//读取product/etc/sysconfig目录
        readPermissions(Environment.buildPath(
                Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);//读取product/etc/permissions目录

        // Allow /system_ext to customize all system configs
        readPermissions(Environment.buildPath(
                Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);//读取system_ext/etc/sysconfig目录
        readPermissions(Environment.buildPath(
                Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);//读取system_ext/etc/permissions目录

        // Skip loading configuration from apex if it is not a system process.
        if (!isSystemProcess()) {//必须在system进程里
            return;
        }
        // Read configuration of libs from apex module.
        // TODO: Use a solid way to filter apex module folders?
        for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) {
            if (f.isFile() || f.getPath().contains("@")) {//过滤文件和包含@的路径文件
                continue;
            }
            readPermissions(Environment.buildPath(f, "etc", "permissions"), ALLOW_LIBS);//读取apex/etc/permissions目录
        }
    }

可以看出readAllPermissions()方法主要是读取各个目录下etc/permissions和etc/sysconfig目录下的文件,permissionFlag参数表示xml文件内允许被解析的tag类型。

    public void readPermissions(File libraryDir, int permissionFlag) {
        // Read permissions from given directory.
        if (!libraryDir.exists() || !libraryDir.isDirectory()) {//目录不存在
            if (permissionFlag == ALLOW_ALL) {//所有类型都被允许解析
                Slog.w(TAG, "No directory " + libraryDir + ", skipping");
            }
            return;
        }
        if (!libraryDir.canRead()) {//目录不可读时,直接返回
            Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
            return;
        }

        // Iterate over the files in the directory and scan .xml files
        File platformFile = null;//表示platform.xml文件
        for (File f : libraryDir.listFiles()) {//遍历目录下的文件
            if (!f.isFile()) {//过滤不是文件的内容
                continue;
            }

            // We'll read platform.xml last
            if (f.getPath().endsWith("etc/permissions/platform.xml")) {//platform.xml最后读取,先跳过
                platformFile = f;
                continue;
            }

            if (!f.getPath().endsWith(".xml")) {//只解析.xml文件
                Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
                continue;
            }
            if (!f.canRead()) {//文件不允许读取,跳过。
                Slog.w(TAG, "Permissions library file " + f + " cannot be read");
                continue;
            }

            readPermissionsFromXml(f, permissionFlag);//开始解析xml文件
        }

        // Read platform permissions last so it will take precedence
        if (platformFile != null) {
            readPermissionsFromXml(platformFile, permissionFlag);//读取platform.xml文件
        }
    }

这个方法主要是对目录的权限进行检查,然后遍历目录下的文件,其核心方法还是调用readPermissionsFromXml()方法读取xml类型文件里面的各个节点,例如:premission、features、library等,然后将解析的结果分别放到SystemConfig对应的数据结构里。platform.xml文件放到最后读取。

private void readPermissionsFromXml(File permFile, int permissionFlag) {
        FileReader permReader = null;
        try {
            permReader = new FileReader(permFile);//根据路径创建FileReader实例,用于读取文件
        } catch (FileNotFoundException e) {
            Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
            return;
        }
        Slog.i(TAG, "Reading permissions from " + permFile);

        final boolean lowRam = ActivityManager.isLowRamDeviceStatic();//是否是低内存设备

        try {
            XmlPullParser parser = Xml.newPullParser();//用于解析xml类型文件
            parser.setInput(permReader);

            int type;
            while ((type=parser.next()) != parser.START_TAG
                       && type != parser.END_DOCUMENT) {//以文件的start和end为解析范围
                ;
            }

            if (type != parser.START_TAG) {
                throw new XmlPullParserException("No start tag found");
            }

            if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {//只解析permissions和config类型的内容
                throw new XmlPullParserException("Unexpected start tag in " + permFile
                        + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
            }

            final boolean allowAll = permissionFlag == ALLOW_ALL;//是否允许解析所有类型节点,下面会用到,下同。
            final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;//是否允许解析library类型节点
            final boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;//是否允许解析feature类型节点
            final boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;//是否允许解析permission类型节点
            ......
            while (true) {//开始解析
                XmlUtils.nextElement(parser);
                if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
                    break;
                }

                String name = parser.getName();//获取节点名称
                if (name == null) {
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }
                switch (name) {
                    case "group": {//解析xml文件中节点为group类型的内容,下同。
                        if (allowAll) {//是否允许解析所有类型节点
                            String gidStr = parser.getAttributeValue(null, "gid");
                            if (gidStr != null) {
                                int gid = android.os.Process.getGidForName(gidStr);
                                mGlobalGids = appendInt(mGlobalGids, gid);
                            } else {
                                Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
                                        + parser.getPositionDescription());
                            }
                        } else {
                            logNotAllowedInPartition(name, permFile, parser);
                        }
                        XmlUtils.skipCurrentTag(parser);
                    } break;
                    case "permission": {
                        if (allowPermissions) {
                            String perm = parser.getAttributeValue(null, "name");
                            if (perm == null) {
                                Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
                                        + parser.getPositionDescription());
                                XmlUtils.skipCurrentTag(parser);
                                break;
                            }
                            perm = perm.intern();
                            readPermission(parser, perm);
                        } else {
                            logNotAllowedInPartition(name, permFile, parser);
                            XmlUtils.skipCurrentTag(parser);
                        }
                    } break;
                    ......
                    default: {
                        Slog.w(TAG, "Tag " + name + " is unknown in "
                                + permFile + " at " + parser.getPositionDescription());
                        XmlUtils.skipCurrentTag(parser);
                    } break;
                }
            }
        } catch (XmlPullParserException e) {
            Slog.w(TAG, "Got exception parsing permissions.", e);
        } catch (IOException e) {
            Slog.w(TAG, "Got exception parsing permissions.", e);
        } finally {
            IoUtils.closeQuietly(permReader);
        }

        // Some devices can be field-converted to FBE, so offer to splice in
        // those features if not already defined by the static config
        if (StorageManager.isFileEncryptedNativeOnly()) {
            addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);//可以添加一些额外的feature
            addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
        }

        ......
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用以下命令启动这些 jar 包: ``` nohup java -jar codegen-service.jar > codegen-service.log & nohup java -jar data-market-service-integration.jar > data-market-service-integration.log & nohup java -jar data-market-service-mapping.jar > data-market-service-mapping.log & nohup java -jar data-market-service.jar > data-market-service.log & nohup java -jar data-masterdata-service.jar > data-masterdata-service.log & nohup java -jar data-metadata-service-console.jar > data-metadata-service-console.log & nohup java -jar data-metadata-service.jar > data-metadata-service.log & nohup java -jar data-quality-service.jar > data-quality-service.log & nohup java -jar data-standard-service.jar > data-standard-service.log & nohup java -jar data-visual-service.jar > data-visual-service.log & nohup java -jar datax-auth.jar > datax-auth.log & nohup java -jar datax-config.jar > datax-config.log & nohup java -jar datax-eureka.jar > datax-eureka.log & nohup java -jar datax-gateway.jar > datax-gateway.log & nohup java -jar datax-tool-monitor.jar > datax-tool-monitor.log & nohup java -jar email-service.jar > email-service.log & nohup java -jar file-service.jar > file-service.log & nohup java -jar quartz-service.jar > quartz-service.log & nohup java -jar system-service.jar > system-service.log & nohup java -jar workflow-service.jar > workflow-service.log & ``` 其中,`nohup` 命令可以使程序在后台运行,并将输出重定向到日志文件中。`&` 符号表示在后台运行该命令。请确保在执行此命令之前,已经安装了 Java 运行时环境,并且当前路径下存在相应的 jar 文件。如果 jar 文件不在当前路径下,可以使用绝对路径或相对路径指定文件的位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值