`

Android 系统属性 SystemProperties 分析

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

1.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"

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


  1. privatestaticnativeStringnative_get(Stringkey);
  2. privatestaticnativeStringnative_get(Stringkey,Stringdef);
  3. privatestaticnativevoidnative_set(Stringkey,Stringdef);
  4. publicstaticvoidset(Stringkey,Stringval){
  5. if(key.length()>PROP_NAME_MAX){
  6. thrownewIllegalArgumentException("key.length>"+PROP_NAME_MAX);
  7. }
  8. if(val!=null&&val.length()>PROP_VALUE_MAX){
  9. thrownewIllegalArgumentException("val.length>"+
  10. PROP_VALUE_MAX);
  11. }
  12. native_set(key,val);
  13. }
3.该接口类在初始化运行环境中注册对应的cpp接口android_os_SystemProperties.cpp,实际操作通过JNI调用的是cpp文件对应的接口:

frameworks/base/core/jni/AndroidRuntime.cpp

  1. namespaceandroid{
  2. externintregister_android_os_SystemProperties(JNIEnv*env);
  3. }
frameworks/base/core/jni/android_os_SystemProperties.cpp

  1. staticvoidSystemProperties_set(JNIEnv*env,jobjectclazz,jstringkeyJ,jstringvalJ)
  2. {
  3. interr;
  4. constchar*key;
  5. constchar*val;
  6. key=env->GetStringUTFChars(keyJ,NULL);
  7. if(valJ==NULL){
  8. val="";/*NULLpointernotallowedhere*/
  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. }
4.设置key的value时,需要作鉴权,根据设置程序所在进程的fd获知uid值,比如system server进程可以设置net打头的key,不可以设置gsm打头的key,相关的定义如下:
system/core/include/private/android_filesystem_config.h

  1. #defineAID_ROOT0/*traditionalunixrootuser*/
  2. #defineAID_SYSTEM1000/*systemserver*/
  3. #defineAID_RADIO1001/*telephonysubsystem,RIL*/
  4. #defineAID_DHCP1014/*dhcpclient*/
  5. #defineAID_SHELL2000/*adbanddebugshelluser*/
  6. #defineAID_CACHE2001/*cacheaccess*/
  7. #defineAID_APP10000/*firstappuser*/
system/core/init/property_service.c

  1. #definePERSISTENT_PROPERTY_DIR"/data/property"
  2. struct{
  3. constchar*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(constchar*name,constchar*value)
  29. {
  30. property_changed(name,value);
  31. return0;
  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. /*Readpersistentpropertiesafteralldefaultvalueshavebeenloaded.*/
  40. load_persistent_properties();
  41. fd=create_socket(PROP_SERVICE_NAME,SOCK_STREAM,0666,0,0);
  42. if(fd<0)return-1;
  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-1]=0;
  53. msg.value[PROP_VALUE_MAX-1]=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:Unableto%sservicectl[%s]uid:%dpid:%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:permissiondenieduid:%dname:%s\n",
  66. cr.uid,msg.name);
  67. }
  68. }
  69. break;
  70. default:
  71. break;
  72. }
  73. }

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

system/core/init/init.c

  1. voidproperty_changed(constchar*name,constchar*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[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. if(ufds[1].revents==POLLIN)
  27. handle_property_set_fd(property_set_fd);
  28. if(ufds[3].revents==POLLIN)
  29. handle_keychord(keychord_fd);
  30. }
  31. return0;
  32. }
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics