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

    技术2022-05-20  46

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

    作者:徐建祥(netpirate@gmail.com)日期:2009/11/11网址:http://www.anymobile.orgAndroid 的系统属性包括两部分:文件保存的持久属性和每次开机导入的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.idsystem/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      }

     


    最新回复(0)