美文网首页
Android属性系统简介及使用

Android属性系统简介及使用

作者: lenozhao | 来源:发表于2018-03-01 16:59 被阅读0次

    属性系统介绍

    Android 里有很多属性(property),每个属性都有一个名称和值,他们都是字符串格式。这些属性定义了 Android 系统的一些公共系统属性。借用大神的一句话,系统属性就是 真·全局变量

    属性变更的请求时init事件循环处理的另一个事件,在Android平台中,为了让运行中的所有进程共享系统运行时所需要的各种设置值,系统开辟了属性存储区域,并提供了访问该区域的API。属性由键(key)与值(value)构成,其表现形式为“键=值”。

    在Android平台中,在访问属性值时,添加了访问权限控制,增强了访问的安全性。系统中所有运行中的进程都可以访问属性值,但仅有init进程才能修改属性值。其他进程修改属性值时,必须向init进程提出请求,最终由init进程负责修改属性值。在此过程中,init进程会先检查各属性的访问权限,而后再修改属性值。

    当属性值更改后,若定义在init.rc文件中的某个特定条件得到满足,则与此条件相匹配的动作就会发生,每个动作都有一个触发器,决定动作的执行时间,记录在“on property”关键字后的命令即被执行。

    属性系统有什么强大的地方

    个人看来属性系统有一下四个优点,当然缺点也很明显,只能支持三种基本类型:string、int、boolean

    • 全局:只要拥有对应的权限,就可以同步获取和修改
    • 通用:在Java层,native层,shell层都可以获取和修改
    • 初始化早:属性服务实在 init 进程中启动的,
    • 使用简单:主要就两个方法 set 和 get

    如何使用系统属性

    native

    当编写本地应用程序时,可以使用 property_get 和 property_set 这两个API来读取/设置属性。要使用它们,我们需要 include cutils/properties.h,并链接 libcutils 库。

    例如:

    frameworks/base/cmds/bootanimation/BootAnimation.cpp

    ...
    #include <cutils/properties.h>
    ...
    status_t BootAnimation::readyToRun() {
    ...
        // If the device has encryption turned on or is in process
        // of being encrypted we show the encrypted boot animation.
        char decrypt[PROPERTY_VALUE_MAX];
        property_get("vold.decrypt", decrypt, "");
    ...
    

    frameworks/base/cmds/bootanimation/Android.mk

    LOCAL_SHARED_LIBRARIES := \
        libcutils \
    

    具体接口如下:

    int property_get(const char *key, char *value, const char *default_value);
    int8_t property_get_bool(const char *key, int8_t default_value);
    int64_t property_get_int64(const char *key, int64_t default_value);
    int32_t property_get_int32(const char *key, int32_t default_value);
    int property_set(const char *key, const char *value);
    int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie);    
    

    以上就是 properties.h 中申明的所有方法,其中 property_set 返回 0 表示执行成功,返回值 <0 表示失败。

    Java

    java 层调用 /frameworks/base/core/java/android/os/SystemProperties.java 中的 set 和 get 方法即可设置和获取系统属性

    例如:

    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    ...
    import android.os.SystemProperties;
    ...
        final void finishBooting() {
        ...
            // Tell anyone interested that we are done booting!
            SystemProperties.set("sys.boot_completed", "1");
    ...
    

    具体接口如下:

        public static String get(String key) {}
        public static String get(String key, String def) {}
        public static int getInt(String key, int def) {
        public static long getLong(String key, long def) {}
        public static boolean getBoolean(String key, boolean def) {}
        public static void set(String key, String val) {}
        public static void addChangeCallback(Runnable callback) {}
    

    通过 JNI 最终调用的还是 /system/core/libcutils/properties.c 中的 property_get 和 property_set

    Shell

    Android toolbox 程序提供了两个工具: setprop 和 getprop 获取和设置属性。其使用方法:

    getprop <属性名>
    setprop <属性名><<属性值>
    

    可以通过命令adb shell: getprop查看手机上所有属性状态值。

    默认情况下,设置属性只会使 "init" 守护程序写入共享内存,它不会执行任何脚本或二进制程序。但是,您可以将您的想要的实现的操作与init.rc中某个属性的变化相关联.例如,在默认的init.rc中有:

        # adbd on at boot in emulator
         on property:ro.kernel.qemu=1
            start adbd
         on property:persist.service.adb.enable=1
            start adbd
         on property:persist.service.adb.enable=0
            stop adbd
    

    这样,如果你设置persist.service.adb.enable为1 ,"init"守护程序就知道需要采取行动:开启adbd服务。

    使用时需要注意什么

    特殊属性

    1. ro. 属性,它表示只读属性,它一旦被设置就不能被修改;

    2. NET. 属性,顾名思义,就是与网络相关的属性,net.属性中有一个特殊的属性:net.change,它记录了每一次最新设置和更新的net.属性,也就是每次设置和更新net.属性时则会自动的更新net.change属性,net.change属性的value就是这个被设置或者更新的net属性的name。例如我们更新了属性net.bt.name的值,由于net有属性发生了变化,那么属性服务就会自动更新net.change,[将其值设置为net.bt.name]

    3. persist. 属性,以文件的形式保存在/data/property路径下。persist.属性由于将其保存在了用户空间中,所以在property_init中是不能对其更新的,只能将其更新过程交给用户来处理。

    4. ctl. 属性,虽然是以属性的形式来进行设置,其实它的目的是为了启动或关闭它指定的service 属性“ ctrl.start ”和“ ctrl.stop ”是用来启动和停止服务。每一项服务必须在/init.rc中定义.系统启动时,init守护进程将解析init.rc和启动属性服务。一旦收到设置“ ctrl.start ”属性的请求,属性服务将使用该属性值作为服务名找到该服务,启动该服务。这项服务的启动结果将会放入“ init.svc.<服务名>“属性中 。客户端应用程序可以轮询那个属性值,以确定结果。

    权限鉴定

    只有有权限的进程才能修改属性,要不随便写一个就改系统属性那当黑客也太容易了。权限相关定义在下面两个文件里:

    system/core/init/property_service.c

    property_perms[] = {
        { "net.rmnet0.",      AID_RADIO,    0 },
        { "net.gprs.",        AID_RADIO,    0 },
        { "net.ppp",          AID_RADIO,    0 },
        { "net.qmi",          AID_RADIO,    0 },
        { "ril.",             AID_RADIO,    0 },
        { "gsm.",             AID_RADIO,    0 },
        { "persist.radio",    AID_RADIO,    0 },
        { "net.dns",          AID_RADIO,    0 },
        { "net.",             AID_SYSTEM,   0 },
        { "dev.",             AID_SYSTEM,   0 },
        { "runtime.",         AID_SYSTEM,   0 },
        { "hw.",              AID_SYSTEM,   0 },
        { "sys.",             AID_SYSTEM,   0 },
        ......
    

    system/core/include/private/android_filesystem_config.h

    #define AID_ROOT             0  /* traditional unix root user */
    #define AID_SYSTEM        1000  /* system server */
    #define AID_RADIO         1001  /* telephony subsystem, RIL */
    #define AID_DHCP          1014  /* dhcp client */
    #define AID_SHELL         2000  /* adb and debug shell user */
    #define AID_CACHE         2001  /* cache access */
    #define AID_APP          10000 /* first app user */
    ......
    

    其实一般应用程序都不会去修改系统属性,所以也不用太在意。

    在开机启动后的init操作中,会执行一个loop循环,当检测到有新的设置时,进入设置流程,鉴权失败会提示相关的异常,如sys_prop: permission denied uid:1000 name:gsm.phone.id

    通过以上介绍我们可以了解什么是系统属性,如何使用,以及一些需要注意的地方。后面会详细介绍相关原理。

    相关文章

      网友评论

          本文标题:Android属性系统简介及使用

          本文链接:https://www.haomeiwen.com/subject/bgtnxftx.html