Android4.4-屬性的使用總結

Android4.4-屬性的使用總結

https://www.jianshu.com/p/69e6b34475ff

 

DD_Dog關注

2019.08.02 11:06:02字數 1,575閱讀 152

一、Android4.4屬性系統系列文章

Android4.4屬性系統-初始化
Android4.4屬性系統-系統服務
Android4.4屬性系統-內存空間共享
Android4.4屬性系統-屬性獲取
Android4.4屬性系統-屬性設置
Android4.4-屬性的使用總結

二、屬性的使用總結

前面的幾篇文章都是分析了屬性系統的運作流程,但是日常開發中用到最多的還是對屬性的獲取和設置,以及不同類型的屬性有什麼特點,可讀可寫的權限問題,這篇文章就很接地氣,總結了如何在安卓系統開發中獲取、設置和添加屬性。

2.1 屬性的獲取

屬性的獲取可以從java層接口和C接口進行分類,當然對於framework和APP開發者來說,用得最多的自然是java/JNI的接口,而對於JNI開發或者c庫的開發來說,用的最多的應該是c接口。

2.1.1 java獲取屬性接口

獲取屬性並不需要額外的權限,對於是否是系統應用也沒有要求。
使用示例

import android.os.SystemProperties;
//獲取自定義的屬性"persist.flyscale.wifi",默認值爲-1
//獲取int值
int wifiInt = SystemProperties.getInt("persist.flyscale.wifi.int", -1);
//獲取long值
int wifiLong = SystemProperties.getLong("persist.flyscale.wifi.long", -1);
//獲取bool值
boolean wifiBool = SystemProperties.getBoolean("persist.flyscale.wifi", false);
//獲取string,如果沒有則返回空字符串""
String wifiStr1 = SystemProperties.getInt("persist.flyscale.wifi");
//獲取string,如果沒有則返回指定默認值"def"
String wifiStr2 = SystemProperties.getInt("persist.flyscale.wifi", "def");

如果需要使用到c接口獲取屬性,請參考Android4.4屬性系統-屬性獲取

2.2 安卓屬性的設置

如果看過前面的Android4.4屬性系統-屬性設置,就容易得出結論:屬性設置是有權限要求的,對於uid爲root是絕對允許的,而對於其它用戶則是禁止的,除非通過了白名單的權限檢查

2.2.1 property權限檢查

在說明如何進行設置之前,必須首先了解property的權限檢查機制,否則只能是雲裏霧裏,不知所云
看過Android4.4屬性系統-屬性設置的讀者應該瞭解了,屬性是有幾種分類的:

2.2.1.1 控制類屬性ctl.*

ctl.開頭的,例如ctl.start=property_service表示啓動名爲"property_service"的服務,也即屬性服務,這樣就明白了,ctl.開頭的屬性表示控制服務的屬性,需要AID_ROOT和AID_SYSTEM權限,除此之外在control_perms白名單中的也可以通過權限檢查,如下:

/*
 * White list of UID that are allowed to start/stop services.
 * Currently there are no user apps that require.
 */
struct {
    const char *service;
    unsigned int uid;
    unsigned int gid;
} control_perms[] = {
    { "dumpstate",AID_SHELL, AID_LOG },  //表示允許AID_SHELL用戶控制 "dumpstate"服務
    { "ril-daemon",AID_RADIO, AID_RADIO },  //表示允許AID_RADIO用戶控制 "ril-daemon"服務
     {NULL, 0, 0 }
};

除了白名單中的兩種服務可以被ROOT和SYSTEM之外的AID_SHELL和AID_RADIO用戶控制之外,其它的一概拒絕!!!

2.2.1.2 其它的屬性

除了控制屬性之外的屬性也需要通過權限檢查,一般來說ROOT用戶是絕對是被允許的,但是系統中除了少數核心進程之外,大部分不是ROOT用戶,它們是通過另外一個白名單property_perms來控制的,如下:

/* White list of permissions for setting property services. */
struct {
    const char *prefix;
    unsigned int uid;
    unsigned int gid;
} property_perms[] = {
    { "net.rmnet0.",      AID_RADIO,    0 },  //
    { "net.gprs.",        AID_RADIO,    0 },
    { "net.ppp",          AID_RADIO,    0 },
    { "net.qmi",          AID_RADIO,    0 },
    { "net.lte",          AID_RADIO,    0 },
    { "net.cdma",         AID_RADIO,    0 },
    { "ril.",             AID_RADIO,    0 },
    { "gsm.",             AID_RADIO,    0 },
    { "persist.radio",    AID_RADIO,    0 },
    { "persist.radio",    AID_SYSTEM,   0 },
    { "net.dns",          AID_RADIO,    0 },
    { "sys.usb.config",   AID_RADIO,    0 },
    { "net.",             AID_SYSTEM,   0 },
    { "dev.",             AID_SYSTEM,   0 },
    { "runtime.",         AID_SYSTEM,   0 },
    { "hw.",              AID_SYSTEM,   0 },
    { "sys.",             AID_SYSTEM,   0 },
    { "sys.powerctl",     AID_SHELL,    0 },
    { "service.",         AID_SYSTEM,   0 },
    { "wlan.",            AID_SYSTEM,   0 },
    { "bluetooth.",       AID_BLUETOOTH,   0 },
    { "dhcp.",            AID_SYSTEM,   0 },
    { "dhcp.",            AID_DHCP,     0 },
    { "debug.",           AID_SYSTEM,   0 },
    { "debug.",           AID_SHELL,    0 },
    { "log.",             AID_SHELL,    0 },
    { "service.adb.root", AID_SHELL,    0 },
    { "service.adb.tcp.port", AID_SHELL,    0 },
    { "persist.sys.",     AID_SYSTEM,   0 },  //系統類屬性
    { "persist.msms.",    AID_RADIO,   0 },//SPRD: add for dsds
    { "persist.msms.",    AID_SYSTEM,   0 },
    { "persist.service.", AID_SYSTEM,   0 },
    { "persist.security.", AID_SYSTEM,   0 },
    { "media.", AID_MEDIA,   0 },
    { "persist.service.bdroid.", AID_BLUETOOTH,   0 },
    { "selinux."         , AID_SYSTEM,   0 },
    { "persist.modem.",    AID_RADIO,    0 },//SPRD: add for lte
    { NULL, 0, 0 }
};

看着很多,其實很好理解 ,就拿 { "persist.sys.", AID_SYSTEM, 0 },來說吧,它表示以"persist.sys."開頭的屬性是允許AID_SYSTEM用戶修改的,其它的類同。
還有很重要的一點,以ro.開頭的表示只讀屬性,即使是AID_ROOT用戶也是不允許修改的。
做一個小總結:如果需要修改/添加屬性,那麼修改屬性的代碼運行的進程必須要通過權限檢查,否則會失敗,權限檢查的細節也已經分析過了,很簡單吧,立即推==》一切難題都是紙老虎

2.2.2 java接口設置屬性

java層的設置接口API只有一個SystemProperties.set(String key, String value),也就是說所有的屬性value值要轉爲字符串被設置進去。

2.2.2.1uid(權限)配置爲system

首先要想成功設置你的APP uid爲system,就需要做一些配置了。

  1. 在AndroidManifest.xml中,以系統應用的Settings爲例,配置android:sharedUserId屬性
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.android.settings"
        coreApp="true"
        android:sharedUserId="android.uid.system">

  1. 另外在對應的Android.mk中使用系統平臺簽名:
    如果你有源碼編譯環境,對mk做如下配置
LOCAL_CERTIFICATE := platform

在模塊目錄下執行mm編譯即可。
當然如果你沒有源碼環境,也是可以進行平臺簽名的,請參考的另一篇文章Android4.4-APP系統簽名的實現方案,其最終目的是一樣的

2.2.2.2 調用java接口

只是簡單的接口調用,很簡單了

import android.os.SystemProperties;

SystemProperties.set("persist.sys.volte.enable", "1");

2.2.3 案例分析

我預置的一個測試應用,測試代碼如下,按上鍵獲取"persist.sys.volte.enable",默認爲false

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_UP:
                Log.i("HomeActivity", "persist.sys.volte.enable=" + SystemProperties.getBoolean("persist.sys.volte.    enable", false));
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:
                SystemProperties.set("persist.sys.volte.enable", "false");
                Log.i("HomeActivity", "persist.sys.volte.enable=" + SystemProperties.getBoolean("persist.sys.volte.    enable", true));
                break;

此時用戶uid爲radio,因爲AndroidManifest.xml中配置了android:sharedUserId="android.uid.phone":

USER     PID   PPID  VSIZE  RSS     WCHAN    PC          NAME
radio       845   145   222304 9032  ffffffff 00000000 S     com.flyscale.launcher

先獲取一次,再設置爲1,再獲取,輸出結果如下:

com.flyscale.launcher I/HomeActivity: persist.sys.volte.enable=true  //設置爲false前
com.flyscale.launcher I/HomeActivity: persist.sys.volte.enable=true  //設置爲false後仍然爲true

在設置屬性的時候報錯如下:

init: sys_prop: permission denied uid:1001  name:persist.sys.volte.enable=true

顯然權限未通過啊。在經過之前兩步配置uid後:

system    864   142   222796 11388 ffffffff 00000000 S com.flyscale.launcher

再次運行結果

com.flyscale.launcher I/HomeActivity: persist.sys.volte.enable=true  //修改前
com.flyscale.launcher I/HomeActivity: persist.sys.volte.enable=false  //修改後

修改成功!

2.3屬性的添加

在代碼中添加屬性與設置屬性的接口是一樣的,也需要注意權限檢查。如果該屬性存在就會更新,如果不存在就會創建,但是要注意,屬性是不能被刪除的。
另外我們經常在安卓源碼中預置一些屬性配置,那麼都在哪些地方可以配置屬性呢,要注意些什麼呢?

  1. 注意權限檢查
    例如我要添加一個屬性persist.flyscale.wifi=0,那麼它肯定是無法通過權限檢查的,因爲它不在白名單中,那麼怎麼辦呢?可以改成persist.sys.flyscale.wifi=0,這樣就可以了,因爲白名單中有persist.sys.開頭的屬性,是可以被AID_SYSTEM修改的。

  2. 可以在源碼中默認配置的文件
    首先工程目錄下的system.prop是可以直接添加的,如下:
    device/***/scx35l/sp9820w_poc_780/system.prop

#add for test
persist.sys.flyscale.wifi=0

另外在工程編譯的mk文件中也可以配置,但是要使用PRODUCT_PROPERTY_OVERRIDES語句

PRODUCT_PROPERTY_OVERRIDES += persist.sys.volte.enable=true

以上爲本人使用中的總結,歡迎指正和補充,謝謝大家!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章