隨筆-1  評論-68  文章-98  trackbacks-0
          作者:徐建祥(netpirate@gmail.com)
          日期:2009/11/11
          網址:http://www.anymobile.org

          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, 066600);
          44         if(fd < 0return -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!
          posted on 2009-11-11 17:40 Xu Jianxiang 閱讀(36220) 評論(1)  編輯  收藏 所屬分類: Android

          評論:
          # re: Android 的系統屬性(SystemProperties)設置分析 2016-05-18 16:57 | 困死了 草 夠逼玩意
          多福多壽  回復  更多評論
            
          主站蜘蛛池模板: 格尔木市| 怀化市| 文山县| 洛阳市| 内江市| 东兰县| 同心县| 县级市| 新平| 景德镇市| 攀枝花市| 永顺县| 石棉县| 自贡市| 江西省| 上栗县| 定兴县| 拜城县| 富宁县| 竹山县| 岢岚县| 浪卡子县| 漯河市| 广河县| 新泰市| 阳曲县| 平安县| 汉寿县| 和田县| 永泰县| 长武县| 广宗县| 福州市| 肇庆市| 洛浦县| 会宁县| 永春县| 溧水县| 荥阳市| 桓台县| 唐河县|