Android System Property分析(3):property接口实现

原创 2015年11月17日 18:43:49

    无论是命令行,java层最后都是调用c层的接口来实现,property_set, property_get,property_list。

    ./system/core/libcutils/properties.c中有三种实现方式,在我们的平台中定义了HAVE_LIBC_SYSTEM_PROPERTIES,这里以HAVE_LIBC_SYSTEM_PROPERTIES为例。

    ./build/core/combo/include/arch/linux-arm/AndroidConfig.h:249:#define HAVE_LIBC_SYSTEM_PROPERTIES 1


    property_get:

int property_get(const char *key, char *value, const char *default_value){
    len = __system_property_get(key, value);
    return len;
}
int __system_property_get(const char *name, char *value){
    const prop_info *pi = __system_property_find(name); // 根据名字找到对应的prop_info
    return __system_property_read(pi, 0, value); // 读取值
}
const prop_info *__system_property_find(const char *name){
    return __system_property_find_compat(name);
}
int __system_property_read(const prop_info *pi, char *name, char *value){
    return __system_property_read_compat(pi, name, value);
}
const prop_info *__system_property_find_compat(const char *name){
    prop_area_compat *pa = (prop_area_compat *)__system_property_area__;
    unsigned count = pa->count;
    unsigned *toc = pa->toc;
    unsigned len = strlen(name);
    prop_info_compat *pi;

    // 遍历__system_property_area__
    while(count--) {
        unsigned entry = *toc++;
        if(TOC_NAME_LEN(entry) != len) continue; // 长度不同就不用比较

        pi = TOC_TO_INFO(pa, entry);
        if(memcmp(name, pi->name, len)) continue; // 继续比较名称是否相同
        return (const prop_info *)pi;
    }
    return 0;
}

int __system_property_read_compat(const prop_info *_pi, char *name, char *value)
{
    unsigned serial, len;
    const prop_info_compat *pi = (const prop_info_compat *)_pi;

    for(;;) {
        serial = pi->serial;
        while(SERIAL_DIRTY(serial)) {
            __futex_wait((volatile void *)&pi->serial, serial, 0);
            serial = pi->serial;
        }
        len = SERIAL_VALUE_LEN(serial);
        memcpy(value, pi->value, len + 1);
        if(serial == pi->serial) {
            if(name != 0) {
                strcpy(name, pi->name);
            }
            return len;
        }
    }
}


从全局变量__system_property_area__中查找
property_list:

int __system_property_foreach_compat(
        void (*propfn)(const prop_info *pi, void *cookie),
        void *cookie){
    prop_area_compat *pa = (prop_area_compat *)__system_property_area__;
    unsigned i;

    for (i = 0; i < pa->count; i++) {
        unsigned entry = pa->toc[i];
        prop_info_compat *pi = TOC_TO_INFO(pa, entry);
        propfn((const prop_info *)pi, cookie);
    }

    return 0;
}

共享内存只读权限,set走以下方式,通过socket发送命令设置属性。

property_set:

int property_set(const char *key, const char *value){
    return __system_property_set(key, value);
}
int __system_property_set(const char *key, const char *value)
{
    int err;
    prop_msg msg;

    if(key == 0) return -1;
    if(value == 0) value = "";
    if(strlen(key) >= PROP_NAME_MAX) return -1;
    if(strlen(value) >= PROP_VALUE_MAX) return -1;

    memset(&msg, 0, sizeof msg);
    msg.cmd = PROP_MSG_SETPROP; // 发送命令
    strlcpy(msg.name, key, sizeof msg.name);
    strlcpy(msg.value, value, sizeof msg.value);

    err = send_prop_msg(&msg);
    if(err < 0) {
        return err;
    }

    return 0;
}
static int send_prop_msg(prop_msg *msg){
    struct pollfd pollfds[1];
    struct sockaddr_un addr;
    socklen_t alen;
    size_t namelen;
    int s;
    int r;
    int result = -1;

    s = socket(AF_LOCAL, SOCK_STREAM, 0); // property_service服务启动时创建的socket
    // ...
}

init中监听处理:

init的main函数最后会进入一个循环:

        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;

        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents & POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
处理property设置:

void handle_property_set_fd(){
    switch(msg.cmd) {
    case PROP_MSG_SETPROP:  // msg.cmd = PROP_MSG_SETPROP;
        msg.name[PROP_NAME_MAX-1] = 0;
        msg.value[PROP_VALUE_MAX-1] = 0;

        if(memcmp(msg.name,"ctl.",4) == 0) { // 如果是ctl开头,则为守护进程服务命令控制方式
            // Keep the old close-socket-early behavior when handling
            // ctl.* properties.
            close(s);
            if (check_control_perms(msg.value, cr.uid, cr.gid, source_ctx)) {
                handle_control_message((char*) msg.name + 4, (char*) msg.value);
            } else {
                ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n",
                        msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);
            }
        } else { // 否则先检查权限,调用init中的property_set来设置属性值
            if (check_perms(msg.name, cr.uid, cr.gid, source_ctx)) {
                property_set((char*) msg.name, (char*) msg.value);
            } else {
                ERROR("sys_prop: permission denied uid:%d  name:%s\n",
                      cr.uid, msg.name);
            }
        }
    }
}
ctl.命令操作守护进程服务

ctl.start,ctl.stop,ctl.restart


init中设置属性:

int property_set(const char *name, const char *value){
    pi = (prop_info*) __system_property_find(name); // 查找属性是否存在

    if(pi != 0) {
        /* ro.* properties may NEVER be modified once set */
        if(!strncmp(name, "ro.", 3)) return -1; // ro.开头的属性不能被改变

        __system_property_update(pi, value, valuelen); // 更新属性值
    } else {
        ret = __system_property_add(name, namelen, value, valuelen); // 添加新属性
    }
    /* If name starts with "net." treat as a DNS property. */
    if (strncmp("net.", name, strlen("net.")) == 0)  {
        if (strcmp("net.change", name) == 0) {
            return 0;
        }
       /*
        * The 'net.change' property is a special property used track when any
        * 'net.*' property name is updated. It is _ONLY_ updated here. Its value
        * contains the last updated 'net.*' property.
        */
        property_set("net.change", name);
    } else if (persistent_properties_loaded &&
            strncmp("persist.", name, strlen("persist.")) == 0) {
            char bootmode[PROP_VALUE_MAX];
            ret = property_get("ro.bootmode", bootmode);
            if (ret <= 0 || (strcmp(bootmode, "charger") != 0))         //do not write prop while charger mode
        /*
         * Don't write properties to disk until after we have read all default properties
         * to prevent them from being overwritten by default values.
         */
        write_persistent_property(name, value); // persistent属性,写到/data/property中
    }
    property_changed(name, value); // 查询init中是否有action被触发。 on property: xxx

    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Android System Property分析

Android System Property 属性变更的请求时init事件循环处理的另一个事件,在Android平台中,为了让运行中的所有进程共享系统运行时所需要的各种设置值,系统...

Android System Property分析(1):property接口

属性系统是android的一个重要特性,它作为一个服务运行在init中,管理系统配置和状态。 1. 命令行使用property方法: getprop setprop 2. init.rc中使用p...

Android Property System

/system/build.prop 是一个属性文件,在Android系统中.prop文件很重要,记录了系统的设置和改变,类似於/etc中的文件。这个文件是如何生成的呢?build/tools/bui...
  • magod
  • magod
  • 2012年02月13日 15:37
  • 2719

Android平台上使用属性系统(property system)

在使用Android的属性系统(property system)时遇到了一些问题,结合此次经历,对属性系统的使用做以简单介绍。...
  • wxzking
  • wxzking
  • 2011年05月14日 11:25
  • 9475

android property system

android property systemProperty system is an important feature on android. It runs as a service and ...

Android系统属性System Property

Android System Property 一 System Property   代码中大量存在:SystemProperties.set()/SystemProperties.get();...

android ndk开发支持64位时遇到undefined reference to `__system_property_get'

android 做守护进程时用ndk实现,但是打包执行文件时要支持android5.1以上的64位手机时遇到undefined reference to `__system_property_get'...

Android 属性系统: Android Property System

Android中大量使用属性文件来记录系统的设置和进程间的信息交换; 而且属性文件是全局可见的,每一个进程都可以获取设置属性。 Every property has a name and val...

Android Property System | Android属性系统

         属性系统是android的一个重要特性。它作为一个服务运行,管理系统配置和状态。所有这些配置和状态都是属性。每个属性是一个键值对(key/value pair),其类型都是字符串。 ...

Android: Android Property System

//看完就明白prop系统,想prop关机后保存用persist.xxEvery property has a name and value. Both name and value are text...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android System Property分析(3):property接口实现
举报原因:
原因补充:

(最多只允许输入30个字)