美文网首页
Android4.4-属性的使用总结

Android4.4-属性的使用总结

作者: DD_Dog | 来源:发表于2019-08-02 11:06 被阅读0次

    一、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
    

    以上为本人使用中的总结,欢迎指正和补充,谢谢大家!

    相关文章

      网友评论

          本文标题:Android4.4-属性的使用总结

          本文链接:https://www.haomeiwen.com/subject/dhdkdctx.html