Android 的系统属性包括两部分:文件保存的持久属性和每次开机导入的cache属性。前者主要保存在下面几个文件中:

bionic / libc / include / sys / _system_properties.h

  1. #definePROP_SERVICE_NAME "property_service"
  2. #definePROP_PATH_RAMDISK_DEFAULT"/default.prop"
  3. #definePROP_PATH_SYSTEM_BUILD "/system/build.prop"
  4. #definePROP_PATH_SYSTEM_DEFAULT "/system/default.prop"
  5. #definePROP_PATH_LOCAL_OVERRIDE "/data/local.prop"


后者则通过frameworks/base/core/java/android/os/SystemProperties.java的接口定义,

  1. private static nativeString native_get(String key);
  2. private static nativeString native_get(String key, String def);
  3. private static native voidnative_set(String key, String def);
  4. public static voidset(String key, String val) {
  5. if(key.length()>PROP_NAME_MAX) {
  6. throw newIllegalArgumentException( " key.length >" +PROP_NAME_MAX);
  7. }
  8. if(val!= null &&val.length()>PROP_VALUE_MAX) {
  9. throw newIllegalArgumentException( " 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. namespaceandroid {
  2. extern intregister_android_os_SystemProperties(JNIEnv* env);
  3. }


frameworks/base/core/jni/android_os_SystemProperties.cpp



  1. static voidSystemProperties_set(JNIEnv* env, jobject clazz, jstring keyJ, jstring valJ)
  2. {
  3. interr;
  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. }


设置keyvalue时,需要作鉴权,根据设置程序所在进程的fd获知uid值,比如system server进程可以设置net打头的key,不可以设置gsm打头的key,相关的定义如下:

system/core/include/private/android_filesystem_config.h

  1. #defineAID_ROOT 0/* traditional unix root user */
  2. #defineAID_SYSTEM 1000/* system server */
  3. #defineAID_RADIO 1001/* telephony subsystem, RIL */
  4. #defineAID_DHCP 1014/* dhcp client */
  5. #defineAID_SHELL 2000/* adb and debug shell user */
  6. #defineAID_CACHE 2001/* cache access */
  7. #defineAID_APP 10000 /* first app user */


system/core/init/property_service.c



  1. #definePERSISTENT_PROPERTY_DIR"/data/property"
  2. struct{
  3. const char * prefix;
  4. unsignedintuid;
  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. intproperty_set( const char * name,const char * value)
  29. {
  30. property_changed(name, value);
  31. return 0 ;
  32. }
  33. intstart_property_service( void )
  34. {
  35. intfd;

  36. load_properties_from_file(PROP_PATH_SYSTEM_BUILD);
  37. load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT);
  38. load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE);
  39. /*Read persistent properties after all default values have been loaded.*/
  40. load_persistent_properties();

  41. fd=create_socket(PROP_SERVICE_NAME, SOCK_STREAM,0666 ,0 ,0 );
  42. if (fd< 0 )return -;
  43. fcntl(fd, F_SETFD, FD_CLOEXEC);
  44. fcntl(fd, F_SETFL, O_NONBLOCK);

  45. listen(fd,8 );
  46. returnfd;
  47. }
  48. voidhandle_property_set_fd( intfd)
  49. {
  50. switch (msg.cmd) {
  51. casePROP_MSG_SETPROP:
  52. msg.name[PROP_NAME_MAX -]= 0 ;
  53. msg.value[PROP_VALUE_MAX -]= 0 ;

  54. if (memcmp(msg.name, " ctl. " , 4 )== 0 ) {
  55. if(check_control_perms(msg.value, cr.uid)) {
  56. handle_control_message(( char * ) msg.name+ 4 , ( char * ) msg.value);
  57. }else{
  58. ERROR( " sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n " ,
  59. msg.name+ 4 , msg.value, cr.uid, cr.pid);
  60. }
  61. }else{
  62. if(check_perms(msg.name, cr.uid)) {
  63. property_set(( char * ) msg.name, ( char * ) msg.value);
  64. }else{
  65. ERROR( " sys_prop: permission denied uid:%dname:%s\n " ,
  66. cr.uid, msg.name);
  67. }
  68. }
  69. break ;

  70. default :
  71. break ;
  72. }
  73. }


在开机启动后的init操作中,会执行一个loop循环,当检测到有新的设置时,进入设置流程,鉴权失败会提示相关的异常,如sys_prop: permission denied uid:000
name:gsm.phone.id

system/core/init/init.c

  1. voidproperty_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. intmain( intargc,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[].fd=property_set_fd;
  19. ufds[].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. if(ufds[].revents==POLLIN)
  27. handle_property_set_fd(property_set_fd);
  28. if(ufds[ 3 ].revents==POLLIN)
  29. handle_keychord(keychord_fd);
  30. }
  31. return 0 ;
  32. }

来自:http://blog.csdn.net/mars5337/archive/200/07/0/5705840.aspx

更多相关文章

  1. Android(安卓)ImageView图片自适应
  2. Android通过onDraw实现在View中绘图操作
  3. Android(安卓)录音
  4. android 驱动文件权限设置
  5. android 模拟器中启用相机API支持
  6. (4.1.10) ImageView图片自适应
  7. Android一些关于分辨率和布局的设置
  8. Android--EditText控件属性汇总
  9. ProgressBar的简单使用

随机推荐

  1. Django连接本地mysql数据库(pycharm)的步
  2. 通过实例判断mysql update是否会锁表
  3. 基于mysql实现group by取各分组最新一条
  4. MySQL变量原理及应用实例
  5. 防止MySQL重复插入数据的三种方法
  6. MySQL死锁的产生原因以及解决方案
  7. MySQL循环插入千万级数据
  8. 解压版MYSQL中文乱码问题解决方案
  9. MYSQL中 char 和 varchar的区别
  10. Mysql表创建外键报错解决方案