Android 13 sysprop_library新增属性

前提

我们在androidP及之前的版本,平台侧及应用层开发习惯于通过调用(或者反射)SystemProperties系统API的方式进行系统属性的读写。Android R以后,平台侧代码采用了一种将系统属性封装成类方法的形式供开发者调用。

Android R以前读写属性

复制代码
1:mk文件或者system.prop文件新增属性
mk文件:
PRODUCT_PROPERTY_OVERRIDES += persist.vendor.usb.config=adb
*.prop文件
persist.vendor.usb.config=true
2:给属性配置上下文
persist.vendor.usb.config u:object_r:usb_prop:s0
3:通过SystemProperties进行读写
SystemProperties.set("persist.vendor.usb.config", "adb,mtp");
String value = SystemProperties.get("persist.vendor.usb.config");

Android R以后读写属性:

例如TelephonyManager.java为例,读写属性:gsm.sim.operator.iso-country

复制代码
1:设置sim卡国家码
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public void setSimCountryIsoForPhone(int phoneId, String iso) {
    if (SubscriptionManager.isValidPhoneId(phoneId)) {
        List<String> newList = updateTelephonyProperty(
                TelephonyProperties.icc_operator_iso_country(), phoneId, iso);
        TelephonyProperties.icc_operator_iso_country(newList);
    }
}
2:读取国家码
@UnsupportedAppUsage
public static String getSimCountryIsoForPhone(int phoneId) {
    return getTelephonyProperty(phoneId, TelephonyProperties.icc_operator_iso_country(), "");
}

以上的属性定义在TelephonyProperties

复制代码
//QSSI.13\frameworks\base\telephony\java\com\android\internal\telephony\TelephonyProperties.java
public interface TelephonyProperties
{
....
/** ISO country code equivalent for the SIM provider's country code*/
static String PROPERTY_ICC_OPERATOR_ISO_COUNTRY = "gsm.sim.operator.iso-country";
....
}

我们看到TelephonyProperties为接口,并且接口类中未定义实现icc_operator_iso_country(),只定义了属性PROPERTY_ICC_OPERATOR_ISO_COUNTRY,其实icc_operator_iso_country定义在如下文件

复制代码
//QSSI.13/system/libsysprop/srcs/android/sysprop/TelephonyProperties.sysprop
# ISO country code equivalent for the SIM provider's country code.
# Indexed by phone ID
prop {
    api_name: "icc_operator_iso_country"
    type: StringList
    scope: Internal
    access: ReadWrite
    prop_name: "gsm.sim.operator.iso-country"
}

/system/libsysprop/srcs/android/sysprop/,发现这里面有很多文件,文件后缀均为sysprop。

我们可以先看下bp文件

复制代码
sysprop_library {
    name: "PlatformProperties",
    srcs: ["**/*.sysprop"],
    property_owner: "Platform",
    api_packages: ["android.sysprop"],

    apex_available: [
        "//apex_available:platform",
        "com.android.art",
        "com.android.art.debug",
        "com.android.bluetooth",
        "com.android.tethering",
    ],
    cpp: {
        min_sdk_version: "S",
    },
    vendor_available: true,
}

可以看到该模块会被编译为jar包为:PlatformProperties.jar,该模块对应的jar包位置为:

复制代码
QSSI.13\out\soong\.intermediates\system\libsysprop\srcs\PlatformProperties\android_common\javac\PlatformProperties.jar

我们可以把该jar包放到AndroidStudio中引用看下,可以到TelephonyProperties.sysprop会被转换为TelephonyProperties.java

我们看下代码就可以看到原来也是调用SystemProperties

这个用法类似于aidl,说明编译脚本会将我们的sysprop文件转换为java文件,并生成对应的方法。此工作是在以下路径的脚本文件处理

复制代码
//QSSI.13/build/soong/sysprop/sysprop_library.go
...
func (g *syspropJavaGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
    var checkApiFileTimeStamp android.WritablePath

    ctx.VisitDirectDeps(func(dep android.Module) {
        if m, ok := dep.(*syspropLibrary); ok {
            checkApiFileTimeStamp = m.checkApiFileTimeStamp
        }
    })

    for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Srcs) {
        srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar")

        ctx.Build(pctx, android.BuildParams{
            Rule:        syspropJava,
            Description: "sysprop_java " + syspropFile.Rel(),
            Output:      srcJarFile,
            Input:       syspropFile,
            Implicit:    checkApiFileTimeStamp,
            Args: map[string]string{
                "scope": g.properties.Scope,
            },
        })

        g.genSrcjars = append(g.genSrcjars, srcJarFile)
    }
}
...

从上面的编译逻辑中可以窥知,编译过程中会输出srcJarFile类型的文件。例如TelephonyProperties.sysprop文件会被转换为TelephonyProperties.srcjar java文件

复制代码
out\soong.intermediates\system\libsysprop\srcs\PlatformProperties_java_gen\gen\sysprop\system\libsysprop\srcs\android\sysprop\TelephonyProperties.srcjar

至此我们知道编译脚本会对.sysprop文件 转换,我们只需要按照.sysprop文件格式定义对应的api即可

下面演示下如何新增一个prop

复制代码
1:在TelephonyProperties.sysprop 中定义属性
//QSSI.13/system/libsysprop/srcs/android/sysprop/TelephonyProperties.sysprop
# set default dns list
prop {
    api_name: "sim_default_dns"
    type: StringList
    scope: Public
    access: ReadWrite
    prop_name: "sim.default.dns"
}
scope为public 可被外部读写,scope: Internal 则只可被同包下的读写,并且public需要更新PlatformProperties-current.txt Internal 需要更新PlatformProperties-latest.txt文件
2:更新api接口
我们新增了属性,需要执行如下指令,更新api文件,具体的详见脚本文件:/build/soong/scripts/freeze-sysprop-api-files.sh
m PlatformProperties-dump-api && rm -rf system/libsysprop/srcs/api/PlatformProperties-current.txt && cp -f out/soong/.intermediates/system/libsysprop/srcs/PlatformProperties_sysprop_library/api-dump.txt system/libsysprop/srcs/api/PlatformProperties-current.txt
执行上述指令以后会更新如下文件
//QSSI.13/system/libsysprop/srcs/api/PlatformProperties-current.txt
prop {
    api_name: "sim_default_dns"
    type: StringList
    access: ReadWrite
    prop_name: "sim.default.dns"
  }
3:我们新增了属性为sim.default.dns,我们还需要增加selinux权限,即为此属性配置上下文,可直接使用之前系统定义好的上下文
//QSSI.13/system/sepolicy/private/property_contexts
sim.default.dns                u:object_r:telephony_status_prop:s0 exact string
//QSSI.13/system/sepolicy/prebuilts/api/33.0/private/property_contexts
sim.default.dns                u:object_r:telephony_status_prop:s0 exact string
4:在如下接口中新增属性
QSSI.13\frameworks\base\telephony\java\com\android\internal\telephony\TelephonyProperties.java
/**
 * PROPERTY_SIM_DEFAULT_DNS is to set the default DNS
 */
static String PROPERTY_SIM_DEFAULT_DNS = "sim.default.dns";
5:如上以后我们可以重新编译PlatformProperties
make PlatformProperties

然后把:out\soong.intermediates\system\libsysprop\srcs\PlatformProperties_java_gen\gen\sysprop\system\libsysprop\srcs\android\sysprop\TelephonyProperties.srcjar

路径下的jar包拖到AS中,可以看到系统为我们生成了对应的方法

然后我们就可以直接通过如下代码去读写了

复制代码
 /**
     * Set TelephonyProperties.default_dns for dns.
     *
     * @hide
     */
    public void setSimDnsServers(int phoneId, String dnsStr) {
        if (SubscriptionManager.isValidPhoneId(phoneId)) {
            List<String> newList = new ArrayList();
            if (!TextUtils.isEmpty(dnsStr)) {
                List<String> tList = updateTelephonyProperty(TelephonyProperties.sim_default_dns(), phoneId, dnsStr);
                newList.addAll(tList);
            }
            for (int i = 0; i < newList.size(); i++) {
                Log.e(TAG, "setSimDns...." + newList.get(i));
            }
            Log.e(TAG, "setSimDnsList...." + dnsStr + ":" + newList);
            TelephonyProperties.sim_default_dns(newList);
        }
    }

    /**
     * get TelephonyProperties.default_dns
     *
     * @hide
     */
    public String getSimDnsServers(int phoneId) {
        return getTelephonyProperty(phoneId, TelephonyProperties.sim_default_dns(), "");
    }
相关推荐
YuTaoShao2 分钟前
【LeetCode 热题 100】240. 搜索二维矩阵 II——排除法
java·算法·leetcode
考虑考虑1 小时前
JDK9中的dropWhile
java·后端·java ee
想躺平的咸鱼干1 小时前
Volatile解决指令重排和单例模式
java·开发语言·单例模式·线程·并发编程
hqxstudying1 小时前
java依赖注入方法
java·spring·log4j·ioc·依赖
·云扬·2 小时前
【Java源码阅读系列37】深度解读Java BufferedReader 源码
java·开发语言
Bug退退退1233 小时前
RabbitMQ 高级特性之重试机制
java·分布式·spring·rabbitmq
小皮侠3 小时前
nginx的使用
java·运维·服务器·前端·git·nginx·github
Zz_waiting.3 小时前
Javaweb - 10.4 ServletConfig 和 ServletContext
java·开发语言·前端·servlet·servletconfig·servletcontext·域对象
全栈凯哥3 小时前
02.SpringBoot常用Utils工具类详解
java·spring boot·后端
兮动人3 小时前
获取终端外网IP地址
java·网络·网络协议·tcp/ip·获取终端外网ip地址