作者:徐建祥(netpirate@gmail.com) 日期:2009/11/11 网址:http://www.anymobile.org Android 的系统属性包括两部分:文件保存的持久属性和每次开机导入的cache属性。前者主要保存在下面几个文件中: bionic/libc/include/sys/_system_properties.h 1 #define PROP_SERVICE_NAME "property_service" 2 #define PROP_PATH_RAMDISK_DEFAULT "/default.prop" 3 #define PROP_PATH_SYSTEM_BUILD "/system/build.prop" 4 #define PROP_PATH_SYSTEM_DEFAULT "/system/default.prop" 5 #define PROP_PATH_LOCAL_OVERRIDE "/data/local.prop" 后者则通过frameworks/base/core/java/android/os/SystemProperties.java的接口定义, 1 private static native String native_get(String key); 2 private static native String native_get(String key, String def); 3 private static native void native_set(String key, String def); 4 public static void set(String key, String val) { 5 if (key.length() > PROP_NAME_MAX) { 6 throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX); 7 } 8 if (val != null && val.length() > PROP_VALUE_MAX) { 9 throw new IllegalArgumentException("val.length > " + 10 PROP_VALUE_MAX); 11 } 12 native_set(key, val); 13 } 该接口类在初始化运行环境中注册对应的cpp接口android_os_SystemProperties.cpp,实际操作通过JNI调用的是cpp文件对应的接口: frameworks/base/core/jni/AndroidRuntime.cpp 1 namespace android { 2 extern int register_android_os_SystemProperties(JNIEnv *env); 3 } frameworks/base/core/jni/android_os_SystemProperties.cpp 1 static void SystemProperties_set(JNIEnv *env, jobject clazz, jstring keyJ, jstring valJ) 2 { 3 int err; 4 const char* key; 5 const char* val; 6 key = env->GetStringUTFChars(keyJ, NULL); 7 if (valJ == NULL) { 8 val = ""; /* NULL pointer not allowed here */ 9 } else { 10 val = env->GetStringUTFChars(valJ, NULL); 11 } 12 err = property_set(key, val); 13 env->ReleaseStringUTFChars(keyJ, key); 14 if (valJ != NULL) { 15 env->ReleaseStringUTFChars(valJ, val); 16 } 17 } 设置key的value时,需要作鉴权,根据设置程序所在进程的fd获知uid值,比如system server进程可以设置net打头的key,不可以设置gsm打头的key,相关的定义如下: system/core/include/private/android_filesystem_config.h 1 #define AID_ROOT 0 /* traditional unix root user */ 2 #define AID_SYSTEM 1000 /* system server */ 3 #define AID_RADIO 1001 /* telephony subsystem, RIL */ 4 #define AID_DHCP 1014 /* dhcp client */ 5 #define AID_SHELL 2000 /* adb and debug shell user */ 6 #define AID_CACHE 2001 /* cache access */ 7 #define AID_APP 10000 /* first app user */ system/core/init/property_service.c 1 #define PERSISTENT_PROPERTY_DIR "/data/property" 2 struct { 3 const char *prefix; 4 unsigned int uid; 5 } property_perms[] = { 6 { "net.rmnet0.", AID_RADIO }, 7 { "net.gprs.", AID_RADIO }, 8 { "ril.", AID_RADIO }, 9 { "gsm.", AID_RADIO }, 10 { "net.dns", AID_RADIO }, 11 { "net.usb0", AID_RADIO }, 12 { "net.", AID_SYSTEM }, 13 { "dev.", AID_SYSTEM }, 14 { "runtime.", AID_SYSTEM }, 15 { "hw.", AID_SYSTEM }, 16 { "sys.", AID_SYSTEM }, 17 { "service.", AID_SYSTEM }, 18 { "wlan.", AID_SYSTEM }, 19 { "dhcp.", AID_SYSTEM }, 20 { "dhcp.", AID_DHCP }, 21 { "debug.", AID_SHELL }, 22 { "log.", AID_SHELL }, 23 { "service.adb.root", AID_SHELL }, 24 { "persist.sys.", AID_SYSTEM }, 25 { "persist.service.", AID_SYSTEM }, 26 { NULL, 0 } 27 }; 28 int property_set(const char *name, const char *value) 29 { 30 property_changed(name, value); 31 return 0; 32 } 33 int start_property_service(void) 34 { 35 int fd; 36 37 load_properties_from_file(PROP_PATH_SYSTEM_BUILD); 38 load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT); 39 load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE); 40 /* Read persistent properties after all default values have been loaded. */ 41 load_persistent_properties(); 42 43 fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0); 44 if(fd < 0) return -1; 45 fcntl(fd, F_SETFD, FD_CLOEXEC); 46 fcntl(fd, F_SETFL, O_NONBLOCK); 47 48 listen(fd, 8); 49 return fd; 50 } 51 void handle_property_set_fd(int fd) 52 { 53 switch(msg.cmd) { 54 case PROP_MSG_SETPROP: 55 msg.name[PROP_NAME_MAX-1] = 0; 56 msg.value[PROP_VALUE_MAX-1] = 0; 57 58 if(memcmp(msg.name,"ctl.",4) == 0) { 59 if (check_control_perms(msg.value, cr.uid)) { 60 handle_control_message((char*) msg.name + 4, (char*) msg.value); 61 } else { 62 ERROR("sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d/n", 63 msg.name + 4, msg.value, cr.uid, cr.pid); 64 } 65 } else { 66 if (check_perms(msg.name, cr.uid)) { 67 property_set((char*) msg.name, (char*) msg.value); 68 } else { 69 ERROR("sys_prop: permission denied uid:%d name:%s/n", 70 cr.uid, msg.name); 71 } 72 } 73 break; 74 75 default: 76 break; 77 } 78 } 在开机启动后的init操作中,会执行一个loop循环,当检测到有新的设置时,进入设置流程,鉴权失败会提示相关的异常,如sys_prop: permission denied uid:1000 name:gsm.phone.id system/core/init/init.c 1 void property_changed(const char *name, const char *value) 2 { 3 if (property_triggers_enabled) { 4 queue_property_triggers(name, value); 5 drain_action_queue(); 6 } 7 } 8 int main(int argc, char **argv) 9 { 10 parse_config_file("/init.rc"); 11 qemu_init(); 12 device_fd = device_init(); 13 property_init(); 14 fd = open(console_name, O_RDWR); 15 property_set_fd = start_property_service(); 16 ufds[0].fd = device_fd; 17 ufds[0].events = POLLIN; 18 ufds[1].fd = property_set_fd; 19 ufds[1].events = POLLIN; 20 ufds[2].fd = signal_recv_fd; 21 ufds[2].events = POLLIN; 22 fd_count = 3; 23 for(;;) { 24 if (ufds[0].revents == POLLIN) 25 handle_device_fd(device_fd); 26 27 if (ufds[1].revents == POLLIN) 28 handle_property_set_fd(property_set_fd); 29 if (ufds[3].revents == POLLIN) 30 handle_keychord(keychord_fd); 31 } 32 return 0; 33 }
Android 的系统属性(SystemProperties)设置分析
最新推荐文章于 2024-09-28 00:15:00 发布