oreo上system_app向驱动节点写值

背景

遇到一个需求,需要在Settings中添加一个开关,开关需要控制一个驱动节点,打开时向节点写1,关闭时写0
看起来是个很普通的问题,但坑却不小。

跳坑

需求大部分已经写好,只需要在开关上写值就可以。于是很快的去加上写值的代码。
/packages/apps/Settings/src/com/android/settings/gestures/GestureSettings.java
在onPreferenceTreeClick()中适当位置加入以下任意方法
第一种写法:

public static void setNode(String node_path){
    BufferedWriter bufWriter = null;
    bufWriter = new BufferedWriter(new FileWriter(NODE_PATH));
    bufWriter.write("1");  // 写操作
    bufWriter.close();
    Toast.makeText(getApplicationContext(),"功能已激活",Toast.LENGTH_SHORT).show();
    Log.d(TAG,"功能已激活 angle " + getString(ANGLE_PATH));
}
复制代码

第二种写法:

public static void writeSysFile(String node_path){
        Process p = null;
        DataOutputStream os = null;
        try {
            p = Runtime.getRuntime().exec("sh");
            os = new DataOutputStream(p.getOutputStream());
            os.writeBytes("echo 1 > "+node_path + "\n");
            os.writeBytes("exit\n");
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(MainActivity.TAG, " can't write " + sys_path+e.getMessage());
        } finally {
            if(p != null){
                p.destroy();
            }
            if(os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
}
复制代码

这两种写法都是对驱动节点写值,本质上等同于

adb root  
adb remount  
adb shell   
:/ echo 1 > /sys/bus/i2c/drivers/fts_ts/3-0038/fts_gesture_mode 
:/ cat /sys/bus/i2c/drivers/fts_ts/3-0038/fts_gesture_mode  
Gesture Mode: On
Reg(0xD0) = 0
复制代码

其中 /sys/bus/i2c/drivers/fts_ts/3-0038/fts_gesture_mode 就是 node_path,这里随便写了一个做示范。
这里看起来还行,编译也不会出错。

出现问题

试了两种写法都未生效,这里第二种方法相当于sh,因而只管写入,不生效也没有log比较坑。 第一种写法报出的log很明显是SELinux问题。

avc: denied { write } for name="fts_gesture_mode" dev="sysfs" ino=29040 scontext=u:r:system_app:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0
复制代码

关于这类报错,有很多介绍说明。谷歌官方快速解决
简单的说就是分解下面这段

denied { write } *** context=u:r:system_app:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0  
复制代码

写成这种格式 allow context tcontext:tclass denied;
得到这样的语句 allow system_app sysfs:file write;
ps(因为添加上述代码在/packages/apps/Settings/中,即Settings应用,拥有android.uid.system,属于system_app)
于是去“system_app.te”添加allow权限。(system_app.te在QCOM平台放置在devices/qcom/sepolicy/msm89**)

allow system_app sysfs:file write;  
或  
allow system_app sysfs:file rw_file_perms;
复制代码

添加完开始编译~~

libsepol.report failure: neverallow on line 489 of system/sepolicy/private/app.te (or line 22022 of policy.conf) violated by allow system_app sysfs:file { write );
libsepol.check_assertions: 1 neverallow failures occurred
Error while expanding policy
复制代码

然鹅编译报错,看报错信息是 1 neverallow failures occurred
基本上,出现neverallow说明此路不通,如果只是临时验证,可以临时关闭,临时关闭的话,此时:

adb root
adb remount
adb shell 
:/ setenforce 0  ##设置SELinux 成为permissive模式(SELinux开启,但对违反selinux规则的行为只记录,不会阻止)
:/ getenforce    ##获取SELinux状态(permissive,enforcing,disabled)
Permissive
复制代码

这样再操作开关就可以正常写值,不会报错。这可以用来验证上层代码是否OK。 但是作为系统版本不能这么做。强行修改neverallow语法会导致CTS问题,那就是挖了个更大的坑。

解决办法

以上方法走不通,于是找了一会。发现有更简便的方法。
init.rc 这个开机启动并持续运行的服务可以解决很多问题。
回到需求本身,只是在settings的开关状态改变时,对应的改变驱动节点值。 那么init.rc可以做到监听一个状态的改变,并执行命令。(在QCOM平台上init.rc对应为init.target.rc位于devices/qcom/msm89**)
如下格式:

on <trigger> [&& <trigger>]*     //设置触发器  
   <command>  
   <command>                  //动作触发之后要执行的命令  
   <command>  
复制代码

于是立刻写上:

on property:persist.gesture.dclick=1
    write /sys/bus/i2c/devices/3-0038/fts_gesture_mode 1
on property:persist.gesture.dclick=0
    write /sys/bus/i2c/devices/3-0038/fts_gesture_mode 0
复制代码

那么“persist.gesture.dclick”则是在settings中点击时赋值。

private void setDoubleTap(int value) { 
    try{
        Log("Write double tap on value--" + value);
        SystemProperties.set(PERSIST_GESTURES_DLICK, Integer. tostring(value)); 
    } catch (IllegalArgumentException e) {
        Log.w( TAG, e.toString());
    }
}
复制代码

于是通过 SystemProperties、init.rc 实现了上层对驱动节点的写操作。
同样的,上层对驱动节点没有权限的操作、特殊的开机services、状态监听等等,都可以用此种方式解决。稳得不行。

小结

刚入framework开发,不能局限于app开发思维,需要往底层走走看看。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值