最近添加一些默认的属性设置,原代码已有的框架是加载到android属性系统中,所以看了一下android属性系统是怎么回事。

        公司原有的框架是这么一回事:添加属性到一个xls文件中,用python读取xls文件,写为一个文本文件,将文本文件copy到手机中的/system/flex目录下,这个目录原先是不存在的,具体怎么操作的,以后再说。假设这个新建的属性文件叫my.prop。代码中加载这个属性文件,然后就是和其他属性一般操作这些自定义的属性了。


        android系统默认文件定义在/bionic/include/sys/_system_properties.h文件中,如下:

#define PROP_PATH_RAMDISK_DEFAULT  "/default.prop"
 #define PROP_PATH_SYSTEM_BUILD     "/system/build.prop"
 #define PROP_PATH_SYSTEM_DEFAULT   "/system/default.prop"
 #define PROP_PATH_LOCAL_OVERRIDE   "/data/local.prop"

目前后两个文件是没有的。

除了这些文件(加上my.prop),还有一些零星的定义,主要是通过方法定义的,例如/init.rc中有部分,init.c中main()中定义有部分等等。


android初始化从init.c的main()函数开始:

有这么几句:

property_init();
 property_set_fd = start_property_service();

    ufds[1].fd = property_set_fd;
     ufds[1].events = POLLIN;for(;;) {
         int nr, i, timeout = -1;

         for (i = 0; i < fd_count; i++)
             ufds[i].revents = 0;

         drain_action_queue();
         restart_processes();

         if (process_needs_restart) {
             timeout = (process_needs_restart - gettime()) * 1000;
             if (timeout < 0)
                 timeout = 0;
         }

 #if BOOTCHART
         if (bootchart_count > 0) {
             if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
                 timeout = BOOTCHART_POLLING_MS;
             if (bootchart_step() < 0 || --bootchart_count == 0) {
                 bootchart_finish();
                 bootchart_count = 0;
             }
         }
 #endif
         nr = poll(ufds, fd_count, timeout);
         if (nr <= 0)
             continue;

         if (ufds[2].revents == POLLIN) {
             /* we got a SIGCHLD - reap and restart as needed */
             read(signal_recv_fd, tmp, sizeof(tmp));
             while (!wait_for_one_process(0))
                 ;
             continue;
         }

         if (ufds[0].revents == POLLIN)
             handle_device_fd(device_fd);

         if (ufds[1].revents == POLLIN)
             handle_property_set_fd(property_set_fd);
         if (ufds[3].revents == POLLIN)
             handle_keychord(keychord_fd);
     }



property_init()代码(位于/system/core/init/property_service.c)如下:

void property_init(void)
 {
     init_property_area();
     load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT);
 }


第一行分配了property内存空间,这里很有趣啊,不知道他具体怎么整的,空间大小用的数值是32768,PROP_NAME_MAX=32, PROP_VALUE_NAME=92,我如果这样算的,32768/(8*(32+92))=33,很明显不止33条记录。望有研究的朋友给个提示。

分配的空间用__system_property_area__指向的。其他地方要用。

第二行加载了/default.prop这个属性文件,不知道原作者是基于什么样的考虑将几个文件分开加载。


看main()函数中的第二行 property_set_fd = start_property_service();

int start_property_service(void)
 {
     int fd;

     //Load my FLEX property
     load_properties_from_file("/system/flex/my.prop");
     load_properties_from_file(PROP_PATH_SYSTEM_BUILD);
     load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT);
     load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE);
     /* Read persistent properties after all default values have been loaded. */
     load_persistent_properties();

     fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0);
     if(fd < 0) return -1;
     fcntl(fd, F_SETFD, FD_CLOEXEC);
     fcntl(fd, F_SETFL, O_NONBLOCK);

     listen(fd, 8);
     return fd;
 }

加载其余几个属性文件。 load_persistent_properties();加载/data/property目录下的属性。


main中的其余部分主要用于检测是否有新的设置,有的时候进入设置流程,鉴权失败会提示相关的异常,这里疑惑就是新的设置是怎么进入的。流程是怎么走的。求解。。。


以上部分是为开机部分的加载内容。应用上主要集中在两个部分:

c/c++层次上主要在/system/core/libcutil/properties.c,提供了property_set(),property_get(),property_list()等函数,对应的提供了几个shell工具,就是在adb shell中可以直接调用,可以查看/system/bin目录下有getprop,setprop,工具,事实上,init.rc也用到了这些工具。例如:

setprop ro.FOREGROUND_APP_ADJ 0
     setprop ro.VISIBLE_APP_ADJ 1
     setprop ro.SECONDARY_SERVER_ADJ 2
     setprop ro.BACKUP_APP_ADJ 2
     setprop ro.HOME_APP_ADJ 4
     setprop ro.HIDDEN_APP_MIN_ADJ 7
     setprop ro.CONTENT_PROVIDER_ADJ 14
     setprop ro.EMPTY_APP_ADJ 15
     setprop wifi.interface eth0
     setprop ro.opengles.version 131072


这里提供一个listprop的工具,显示当前所有的property name-value对,已经测试过可行:

新建一个目录,包含两个文件:Android.mk和list_property.c文件

Android.mk文件如下:

LOCAL_PATH:= $(call my-dir)

 include $(CLEAR_VARS)

 LOCAL_SRC_FILES:= list_property.c

 LOCAL_SHARED_LIBRARIES := /
                     libcutils /
                     libutils /

 LOCAL_MODULE:= listprop

 include $(BUILD_EXECUTABLE)

 include $(call all-makefiles-under,$(LOCAL_PATH))


list_property.c如下:

#include <cutils/properties.h>  
 #include <stdio.h>  
 void print_prop(const char* key,const char* value,void* cookie)  
 {  
     printf("key=%s,/tvalue=%s/n",key,value);  
 }  
   
 int main()  
 {  
     property_list(print_prop,NULL);  
     return 0;
 }

确保Android.mk被编译进去就行了。


Java层次上的应用主要在SystemProperties.java这个类中,无非是get/set方法。


11:10:37 2011-01-08