最近添加一些默认的属性设置,原代码已有的框架是加载到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