Android的屬性系統java
每條屬性包含了名字和其對應的值,二者都用字符串來描述。Android系統中大量的使用了屬性系統用於記錄系統的設置(注:和windows系統裏的註冊表相似),以及進程間的信息交互。屬性系統對於整個系統來講是全局的,也就是說每個進程均可以獲取和設置每條屬性。windows
當系統初始化的時候,Android系統會分配一塊共享內存用於存儲屬性信息。這些操做是在"init"這個守護進程裏完成的,其對應的源代碼目錄在:device/system/init。"init"守護進程同時也啓動了屬性服務。屬性服務運行在init進程中(注:是線程?)。客戶端須要設置屬性時,須要鏈接到屬性服務上,同時發送消息給屬性服務。這樣屬性服務就能夠更新保存在共享內存中的屬性信息。當客戶端須要讀取屬性信息時,能夠直接訪問共享內存,這樣作能夠提升性能。app
客戶端程序能夠經過調用libcutils庫裏的API函數實現對屬性的設置和讀取的操做。ionic
libcutils庫對應的源代碼存放在: device/libs/cutils。ide
這些API函數包括:函數
int property_get(const char *key, char *value, const char *default_value);工具
int property_set(const char *key, const char *value);性能
libcutils庫是經過調用libc庫中的__system_property_xxx這一系列函數實現從共享內存中獲取屬性的。對應的libc的源代碼保存在: device/system/bionic。ui
屬性服務也會調用libc庫中的函數__system_property_init來實現對共享內存的初始化。當啓動屬性服務時會經過下面文件來加載默認的屬性信息。this
/default.prop
/system/build.prop
/system/default.prop
/data/local.prop
屬性信息按照上面的順序被加載。後加載的屬性會覆蓋前面的屬性值(注:當屬性名稱相同的時候)。當上面加載完成後,最後加載的是駐留屬性,保存在/data/property文件中。
特別的屬性
若是屬性是有」ro.」字符串開頭,那麼這條屬性被當作一個只讀屬性,一旦設置就不能被修改了。(注:初始化設置的時候是可寫的)
若是屬性是有「persist.」字符串開頭,那麼就認爲是駐留屬性,當修改的時候同時也會被保存在/data/property文件中。
若是屬性是有「net.」字符串開頭,當設置這種屬性的時候,「net.change」這條屬性也會被自動設置,其內容設爲最後更新過的屬性名。
屬性「ctrl.start」 和 「ctrl.stop」 用於啓動和中止服務。這些服務必須在文件/init.rc中被定義。在系統啓動的時候,init守護進程會解析init.rc文件,而後啓動屬性服務。一旦收到了「ctrl.start」這個屬性的設置請求,屬性服務會根據該屬性的值做爲服務名,在列表中找到服務對象並啓動。服務啓動的結果會反映在「init.svc.<service name>」這個屬性之中。客戶端程序能夠輪詢該屬性值來判斷服務的啓動結果。
Android 工具箱
Android 工具箱提供了2個應用程序:setprop 和 getprop用於讀取和設置屬性項目。使用方法是:
getprop <property name>
setprop <property name> <property value>
Java
Java程序能夠經過使用函數System.getProperty() 和 System.setProperty()獲取和設置屬性條目。
動做
默認狀況下設置屬性只會觸發init進程對共享內存進行操做,並不會執行任何腳本和程序。可是你能夠修改文件init.rc,這樣在屬性值發生變化的時候來觸發你定義的動做。例如在默認的init.rc文件中你能夠找到下面這部分:
# adbd on at boot in emulator
on property:ro.kernel.qemu=1
start adbd
on property:persist.service.adb.enable=1
start adbd
on property:persist.service.adb.enable=0
stop adbd
因此當屬性條目persist.service.adb.enable被設置成1的時候,init守護進程知道他須要啓動adbd服務。
原文以下:
Android Property System
Every property has a name and value. Both name and value are text strings. Property is heavily used in Android to record system setting or exchange information between processes. The property is globally visible in the whole system. Every process can get/set a property.
On system initialization, Android will allocates a block of shared memory for storing the properties. This is done in 「init」 daemon whose source code is at: device/system/init. The 「init」 daemon will start a Property Service. The Property Service is running in the process of 「init」 daemon. Every client that wants to SET property needs to connect to the Property Service and send message to Property Service. Property Service will update/create the property in shared memory. Any client that wants to GET property can read the property from the shared memory directly. This promotes the read performance.
The client application can invoke the API function exposed from libcutils to GET/SET a property.
The source code of libcutils locates at: device/libs/cutils.
The API function is:
int property_get(const char *key, char *value, const char *default_value);
int property_set(const char *key, const char *value);
The libcutils is in turn calling the __system_property_xxx function in libc to get a property from the shared memory. The source code of libc is at: device/system/bionic.
The Property Service is also in turn calling the __system_property_init function in libc to initiate the shared memory for properties. When starting the Property Service will load the default properties from below files:
/default.prop
/system/build.prop
/system/default.prop
/data/local.prop
The properties are loaded in the above order. Later loaded properties will override the previous values. After those properties are loaded, the last loaded is the persistent properties which is persisted in /data/property.
Special Properties
If a property’s name begins with 「ro.」, then this property is treated as a read-only property. Once set, the value of the property can’t be changed.
If a property’s name begins with 「persist.」, then when setting this property, the value will be written to /data/property, too.
If a property’s name begins with 「net.」, when when setting this property, the 「net.change」 property will be set automatically to contain the name of the last updated property. (It’s tricky. The netresolve module uses this property to track if there is any change on the net.* properties.)
The property 「ctrl.start」 and 「ctrl.stop」 is used to start and stop a service. Every service must be defined in /init.rc. On system startup, the init daemon will parse the init.rc and start the Property Service. Once received a request to set the property of 「ctrl.start」, the Property Service will use the property value as the service name to find the service and then start the service. The service starting result is then put to the property 「init.svc.<service name>」. The client application can poll the value of that property to determine the result.
Android toolbox
The Android toolbox provides two applets: setprop and getprop to get and set properties. The usage is:
getprop <property name>
setprop <property name> <property value>
Java
The java application can use the System.getProperty() and System.setProperty() function to Get and Set the property.
Action
By default the set property will only cause "init" daemon to write to shared memory, it won't execute any script or binary. But you can add your actions to correspond to property change in init.rc. For example, in the default init.rc, you can find.
# adbd on at boot in emulator
on property:ro.kernel.qemu=1
start adbd
on property:persist.service.adb.enable=1
start adbd
on property:persist.service.adb.enable=0
stop adbd
So if you set persist.service.adb.enable to 1, the "init" daemon knows it has actions to do, then it will start adbd service.