Android 的系统属性(SystemProperties)设置分析

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.       }


设置keyvalue时,需要作鉴权,根据设置程序所在进程的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   -  ;
  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 -  ]  =   0 ;
  56.               msg.value[PROP_VALUE_MAX -  ]  =   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:000
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[  ].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.   
  27.               if  (ufds[  ].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.       }

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

你可能感兴趣的:(Android)