0
点赞
收藏
分享

微信扫一扫

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  
     } 
设置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  
     } 
OVER!

举报

相关推荐

0 条评论