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

    无论是命令行,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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值