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

bionic/libc/include/sys/_system_properties.h

12345
     #define  PROP_SERVICE_NAME "property_service"      #define  PROP_PATH_RAMDISK_DEFAULT  "/default.prop"      #define  PROP_PATH_SYSTEM_BUILD     "/system/build.prop"      #define  PROP_PATH_SYSTEM_DEFAULT   "/system/default.prop"      #define  PROP_PATH_LOCAL_OVERRIDE   "/data/local.prop"

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

12345678910111213
       private   static   native  String native_get(String key);       private   static   native  String native_get(String key, String def);       private   static   native   void  native_set(String key, String def);       public   static   void  set(String key, String val) {           if  (key.length()  >  PROP_NAME_MAX) {               throw   new  IllegalArgumentException( " key.length >  "   +  PROP_NAME_MAX);          }           if  (val  !=   null   &&  val.length()  >  PROP_VALUE_MAX) {               throw   new  IllegalArgumentException( " val.length >  "   +                   PROP_VALUE_MAX);          }          native_set(key, val);      }

该接口类在初始化运行环境中注册对应的cpp接口android_os_SystemProperties.cpp,实际操作通过JNI调用的是cpp文件对应的接口:

frameworks/base/core/jni/AndroidRuntime.cpp

123
       namespace  android {       extern   int  register_android_os_SystemProperties(JNIEnv  * env);      }

frameworks/base/core/jni/android_os_SystemProperties.cpp

1234567891011121314151617
       static   void  SystemProperties_set(JNIEnv  * env, jobject clazz, jstring keyJ, jstring valJ)      {           int  err;           const   char *  key;           const   char *  val;          key  =  env -> GetStringUTFChars(keyJ, NULL);           if  (valJ  ==  NULL) {              val  =   "" ;        /*  NULL pointer not allowed here  */           }  else  {              val  =  env -> GetStringUTFChars(valJ, NULL);          }          err  =  property_set(key, val);          env -> ReleaseStringUTFChars(keyJ, key);                   if  (valJ  !=  NULL) {              env -> ReleaseStringUTFChars(valJ, val);          }      }

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

system/core/include/private/android_filesystem_config.h

1234567
      #define  AID_ROOT             0  /* traditional unix root user */       #define  AID_SYSTEM        1000  /* system server */       #define  AID_RADIO         1001  /* telephony subsystem, RIL */       #define  AID_DHCP          1014  /* dhcp client */       #define  AID_SHELL         2000  /* adb and debug shell user */       #define  AID_CACHE         2001  /* cache access */       #define  AID_APP          10000 /* first app user */

system/core/init/property_service.c

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
       #define  PERSISTENT_PROPERTY_DIR  "/data/property"        struct  {           const   char   * prefix;          unsigned  int  uid;      } property_perms[]  =  {          {  " net.rmnet0. " ,    AID_RADIO },          {  " net.gprs. " ,      AID_RADIO },          {  " ril. " ,           AID_RADIO },          {  " gsm. " ,           AID_RADIO },          {  " net.dns " ,        AID_RADIO },          {  " net.usb0 " ,       AID_RADIO },          {  " net. " ,           AID_SYSTEM },          {  " dev. " ,           AID_SYSTEM },          {  " runtime. " ,       AID_SYSTEM },          {  " hw. " ,            AID_SYSTEM },          {  " sys. " ,        AID_SYSTEM },          {  " service. " ,    AID_SYSTEM },          {  " wlan. " ,        AID_SYSTEM },          {  " dhcp. " ,        AID_SYSTEM },          {  " dhcp. " ,        AID_DHCP },          {  " debug. " ,        AID_SHELL },          {  " log. " ,        AID_SHELL },          {  " service.adb.root " ,    AID_SHELL },          {  " persist.sys. " ,    AID_SYSTEM },          {  " persist.service. " ,   AID_SYSTEM },          { NULL,  0  }      };       int  property_set( const   char   * name,  const   char   * value)      {          property_changed(name, value);           return   0 ;      }       int  start_property_service( void )      {           int  fd;          load_properties_from_file(PROP_PATH_SYSTEM_BUILD);          load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT);          load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE);           /*  Read persistent properties after all default values have been loaded.  */           load_persistent_properties();          fd  =  create_socket(PROP_SERVICE_NAME, SOCK_STREAM,  0666 ,  0 ,  0 );           if (fd  <   0 )  return   - 1 ;          fcntl(fd, F_SETFD, FD_CLOEXEC);          fcntl(fd, F_SETFL, O_NONBLOCK);          listen(fd,  8 );           return  fd;      }       void  handle_property_set_fd( int  fd)      {           switch (msg.cmd) {           case  PROP_MSG_SETPROP:              msg.name[PROP_NAME_MAX - 1 ]  =   0 ;              msg.value[PROP_VALUE_MAX - 1 ]  =   0 ;               if (memcmp(msg.name, " ctl. " , 4 )  ==   0 ) {                   if  (check_control_perms(msg.value, cr.uid)) {                      handle_control_message(( char * ) msg.name  +   4 , ( char * ) msg.value);                  }  else  {                      ERROR( " sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n " ,                              msg.name  +   4 , msg.value, cr.uid, cr.pid);                  }              }  else  {                   if  (check_perms(msg.name, cr.uid)) {                      property_set(( char * ) msg.name, ( char * ) msg.value);                  }  else  {                      ERROR( " sys_prop: permission denied uid:%d  name:%s\n " ,                            cr.uid, msg.name);                  }              }               break ;           default :               break ;          }      }

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

system/core/init/init.c

123456789101112131415161718192021222324252627282930313233
       void  property_changed( const   char   * name,  const   char   * value)      {           if  (property_triggers_enabled) {              queue_property_triggers(name, value);              drain_action_queue();          }      }       int  main( int  argc,  char   ** argv)      {          parse_config_file( " /init.rc " );          qemu_init();          device_fd  =  device_init();          property_init();          fd  =  open(console_name, O_RDWR);          property_set_fd  =  start_property_service();          ufds[ 0 ].fd  =  device_fd;          ufds[ 0 ].events  =  POLLIN;          ufds[ 1 ].fd  =  property_set_fd;          ufds[ 1 ].events  =  POLLIN;          ufds[ 2 ].fd  =  signal_recv_fd;          ufds[ 2 ].events  =  POLLIN;          fd_count  =   3 ;           for (;;) {               if  (ufds[ 0 ].revents  ==  POLLIN)                  handle_device_fd(device_fd);               if  (ufds[ 1 ].revents  ==  POLLIN)                  handle_property_set_fd(property_set_fd);               if  (ufds[ 3 ].revents  ==  POLLIN)                  handle_keychord(keychord_fd);          }           return   0 ;      }

OVER!

更多相关文章

  1. Android(安卓)- 永不锁屏,开机不锁屏,删除设置中休眠时间选项
  2. Android图片轮播控件---com.youth.banner.Banner
  3. EditText属性简介
  4. 【Android】android:padding属性设置对ImageButton无效问题
  5. Android(安卓)- 绘画出圆并保存为图片(详)
  6. Android(安卓)Interface Definition Language (AIDL) android接
  7. Android(安卓)FloatingActionButton控件
  8. Android之Telephony各文件解释
  9. android 设置特殊字体

随机推荐

  1. android中intent的作用
  2. Android中shape属性详解
  3. Android电话拨号器
  4. Android事件分发机制完全解析(终极版二)
  5. Android中ExpandableListView的使用
  6. Android(安卓)View坐标getLeft, getRight
  7. Android屏幕密度的深刻理解
  8. com/android/phone/INetworkQueryService
  9. Android中ExpandableListView的使用
  10. android静态图片和动态壁纸