屬性系統是android的一個重要特性。它作為一個服務運行,管理系統配置和狀態。所有這些配置和狀態都是屬性。每個屬性是一個索引值對(key/value pair),其類型都是字串。
從功能上看,屬性與windows系統的註冊表非常相似。許多android應用程式和庫直接或者間接地依賴此特性,以決定它們的運行時行為。例如,adbd進程查詢屬性服務已確認當前是否運行在模擬器環境中。另一個例子是java.io.File.pathSpearator,其返回儲存於屬性服務中的值。
屬性系統是如何工作的
屬性系統的上層架構如所示。
圖中有3個進程、一組永久屬性檔案和一塊共用記憶體地區。共用記憶體地區是所有屬性記錄的儲存所在。只有屬性服務進程才可以寫入共用記憶體地區,它負責從永久檔案中載入屬性記錄並將它們儲存在共用記憶體中。
consumer進程將共用記憶體載入到其自身的虛擬位址空間並直接存取這些屬性。setter進程同樣將共用記憶體載入到其自身的虛擬位址空間,但其不能直接寫該記憶體。當setter試圖增加或者更新一個屬性時,它將該屬性通過unix domain socket發送至屬性服務。屬性服務代表setter進程將該屬性寫入共用記憶體和永久檔案中。
屬性服務運行於init進程中。init進程首先建立一個共用記憶體地區,並儲存一個指向該地區的描述符fd。init進程將該地區通過使用了MAP_SHARED標誌的mmap映射至它自身的虛擬位址空間,這樣,任何對於該地區的更新對於所有進程都是可見的。fd和地區大小被儲存在一個名為ANDROID_PROPERTY_WORKSPACE的變數中。任何其他進程,比如consumer和setter將使用這個變數來獲得fd和尺寸,這樣它們就能mmap這個地區到它們自身的虛擬位址空間中。該共用記憶體地區如所示。
在這之後,init進程將從下列檔案載入屬性:
/default.prop
/system/build.prop
/system/default.prop
/data/local.prop
下一步是啟動屬性服務。在這一步中,一個unix
domain socket服務被建立。此socket的路徑是/dev/socket/property_service,該路徑對於其他用戶端進程是熟知的。最後,init進程調用poll來等待該socket上的串連事件。
在consumer一邊,當它初始化libc(bionic/libc/bionic/libc_common.c
__libc_init_common 函數),它將從環境變數中返回fd和尺寸,並映射共用記憶體到其自身的地址空間(bionic/libc/bionic/system_properties.c __system_properties_init 函數)。在這之後,libcutils可以想讀取普通記憶體那樣為consumer讀取屬性。
目前,屬性是不能夠被刪除的。也就是說,一旦添加了一個屬性,它將不能夠被刪除,其鍵也不能夠被改變。
如何讀取/設定屬性
Android上有三種主要途徑來get/set屬性。
1、 native code
當編寫本地應用程式時,可以使用property_get和property_set 這兩個API來讀取/設定屬性。要使用它們,我們需要include cutils/properties.h,並連結libcutils庫。
2、 java code
在Java包(java.lang.System)中提供有System.getProperty和System.setProperty方法。但值得注意的是,儘管這兩個API在語義上等同native函數,但其將資料存放區於完全不同的位置。實際上,dalvik VM使用一個雜湊表來儲存這些屬性。所以,用這兩個API儲存的屬性是獨立的,不能存取native屬性,反之亦然。
然而Android有一個內部隱藏類(@hide,對SDK不可見)android.os.SystemProperties來操縱native屬性。其通過jni來存取native屬性庫。
3、 shell指令碼
Android提供getprop和setprop命令列工具來擷取和更新屬性。其依賴libcutils實現。
以上翻譯自http://rxwen.blogspot.com/2010/01/android-property-system.html,有修正。
補充:通過查看property_service.c,我們可以明確以下事實:
1、 屬性名稱不是隨意取的。在property_perms數組中定義了當前系統上可用的所有屬性的首碼,以及相對應的存取許可權UID。對屬性的設定要滿足許可權要求,同時命名也要在這些定義的範圍內。
2、 PA_COUNT_MAX指定了系統(共用記憶體地區中)最多能儲存多少個屬性。
3、 PROP_NAME_MAX指定了一個屬性的key最大允許長度;PROP_VALUE_MAX則指定了value的最大允許長度。
此外,http://blog.csdn.net/tekkamanitachi/archive/2009/06/18/4280982.aspx 這篇文章翻譯了Android的官方文檔,從另一個角度敘述了屬性系統,需要者請參看。