屬性系統(tǒng)介紹
Android 里有很多屬性(property)涮瞻,每個屬性都有一個名稱和值近顷,他們都是字符串格式。這些屬性定義了 Android 系統(tǒng)的一些公共系統(tǒng)屬性饱须。借用大神的一句話譬挚,系統(tǒng)屬性就是 真·全局變量
屬性變更的請求時init事件循環(huán)處理的另一個事件,在Android平臺中蚪腋,為了讓運行中的所有進(jìn)程共享系統(tǒng)運行時所需要的各種設(shè)置值,系統(tǒng)開辟了屬性存儲區(qū)域悠砚,并提供了訪問該區(qū)域的API。屬性由鍵(key)與值(value)構(gòu)成枢泰,其表現(xiàn)形式為“鍵=值”。
在Android平臺中毛甲,在訪問屬性值時,添加了訪問權(quán)限控制七咧,增強了訪問的安全性。系統(tǒng)中所有運行中的進(jìn)程都可以訪問屬性值终蒂,但僅有init進(jìn)程才能修改屬性值。其他進(jìn)程修改屬性值時矮锈,必須向init進(jìn)程提出請求褪贵,最終由init進(jìn)程負(fù)責(zé)修改屬性值震蒋。在此過程中沐寺,init進(jìn)程會先檢查各屬性的訪問權(quán)限,而后再修改屬性值囊拜。
當(dāng)屬性值更改后冠跷,若定義在init.rc文件中的某個特定條件得到滿足,則與此條件相匹配的動作就會發(fā)生,每個動作都有一個觸發(fā)器仪糖,決定動作的執(zhí)行時間,記錄在“on property”關(guān)鍵字后的命令即被執(zhí)行故爵。
屬性系統(tǒng)有什么強大的地方
個人看來屬性系統(tǒng)有一下四個優(yōu)點劲室,當(dāng)然缺點也很明顯,只能支持三種基本類型:string喉磁、int、boolean
- 全局:只要擁有對應(yīng)的權(quán)限斤讥,就可以同步獲取和修改
- 通用:在Java層,native層,shell層都可以獲取和修改
- 初始化早:屬性服務(wù)實在 init 進(jìn)程中啟動的簸州,
- 使用簡單:主要就兩個方法 set 和 get
如何使用系統(tǒng)屬性
native
當(dāng)編寫本地應(yīng)用程序時,可以使用 property_get 和 property_set 這兩個API來讀取/設(shè)置屬性矢洲。要使用它們,我們需要 include cutils/properties.h,并鏈接 libcutils 庫揩徊。
int property_get(const char *key, char *value, const char *default_value);
int8_t property_get_bool(const char *key, int8_t default_value);
int64_t property_get_int64(const char *key, int64_t default_value);
int32_t property_get_int32(const char *key, int32_t default_value);
int property_set(const char *key, const char *value);
int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie);
以上就是 properties.h 中申明的所有方法,其中 property_set 返回 0 表示執(zhí)行成功,返回值 <0 表示失敗。
Java
java 層調(diào)用 /frameworks/base/core/java/android/os/SystemProperties.java 中的 set 和 get 方法即可設(shè)置和獲取系統(tǒng)屬性
public static String get(String key) {}
public static String get(String key, String def) {}
public static int getInt(String key, int def) {
public static long getLong(String key, long def) {}
public static boolean getBoolean(String key, boolean def) {}
public static void set(String key, String val) {}
public static void addChangeCallback(Runnable callback) {}
通過 JNI 最終調(diào)用的還是 /system/core/libcutils/properties.c 中的 property_get 和 property_set
Shell
Android toolbox 程序提供了兩個工具: setprop 和 getprop 獲取和設(shè)置屬性。其使用方法:
getprop <屬性名>
setprop <屬性名><<屬性值>
可以通過命令adb shell: getprop查看手機上所有屬性狀態(tài)值仆葡。
默認(rèn)情況下,設(shè)置屬性只會使 "init" 守護程序?qū)懭牍蚕韮?nèi)存,它不會執(zhí)行任何腳本或二進(jìn)制程序窖铡。但是,您可以將您的想要的實現(xiàn)的操作與init.rc中某個屬性的變化相關(guān)聯(lián).例如箍铲,在默認(rèn)的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
這樣膘融,如果你設(shè)置persist.service.adb.enable為1 春畔,"init"守護程序就知道需要采取行動:開啟adbd服務(wù)。
使用時需要注意什么
特殊屬性
ro. 屬性扣孟,它表示只讀屬性,它一旦被設(shè)置就不能被修改利诺;
NET. 屬性,顧名思義侣滩,就是與網(wǎng)絡(luò)相關(guān)的屬性,net.屬性中有一個特殊的屬性:net.change葛躏,它記錄了每一次最新設(shè)置和更新的net.屬性,也就是每次設(shè)置和更新net.屬性時則會自動的更新net.change屬性,net.change屬性的value就是這個被設(shè)置或者更新的net屬性的name猾愿。例如我們更新了屬性net.bt.name的值,由于net有屬性發(fā)生了變化姻僧,那么屬性服務(wù)就會自動更新net.change赌莺,[將其值設(shè)置為net.bt.name]
persist. 屬性,以文件的形式保存在/data/property路徑下。persist.屬性由于將其保存在了用戶空間中港谊,所以在property_init中是不能對其更新的,只能將其更新過程交給用戶來處理。
ctl. 屬性蛀缝,雖然是以屬性的形式來進(jìn)行設(shè)置,其實它的目的是為了啟動或關(guān)閉它指定的service 屬性“ ctrl.start ”和“ ctrl.stop ”是用來啟動和停止服務(wù)。每一項服務(wù)必須在/init.rc中定義.系統(tǒng)啟動時构哺,init守護進(jìn)程將解析init.rc和啟動屬性服務(wù)。一旦收到設(shè)置“ ctrl.start ”屬性的請求碟嘴,屬性服務(wù)將使用該屬性值作為服務(wù)名找到該服務(wù)眠菇,啟動該服務(wù)。這項服務(wù)的啟動結(jié)果將會放入“ init.svc.<服務(wù)名>“屬性中 》妫客戶端應(yīng)用程序可以輪詢那個屬性值,以確定結(jié)果续捂。
權(quán)限鑒定
只有有權(quán)限的進(jìn)程才能修改屬性间校,要不隨便寫一個就改系統(tǒng)屬性那當(dāng)黑客也太容易了胁附。權(quán)限相關(guān)定義在下面兩個文件里:
system/core/init/property_service.c
property_perms[] = {
{ "net.rmnet0.", AID_RADIO, 0 },
{ "net.gprs.", AID_RADIO, 0 },
{ "net.ppp", AID_RADIO, 0 },
{ "net.qmi", AID_RADIO, 0 },
{ "ril.", AID_RADIO, 0 },
{ "gsm.", AID_RADIO, 0 },
{ "persist.radio", AID_RADIO, 0 },
{ "net.dns", AID_RADIO, 0 },
{ "net.", AID_SYSTEM, 0 },
{ "dev.", AID_SYSTEM, 0 },
{ "runtime.", AID_SYSTEM, 0 },
{ "hw.", AID_SYSTEM, 0 },
{ "sys.", AID_SYSTEM, 0 },
......
system/core/include/private/android_filesystem_config.h
#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 */
......
其實一般應(yīng)用程序都不會去修改系統(tǒng)屬性,所以也不用太在意弓叛。
在開機啟動后的init操作中,會執(zhí)行一個loop循環(huán)毕籽,當(dāng)檢測到有新的設(shè)置時,進(jìn)入設(shè)置流程睡榆,鑒權(quán)失敗會提示相關(guān)的異常,如sys_prop: permission denied uid:1000 name:gsm.phone.id
通過以上介紹我們可以了解什么是系統(tǒng)屬性宿崭,如何使用,以及一些需要注意的地方锭硼。后面會詳細(xì)介紹相關(guān)原理轰异。