java.io.FileNotFoundException: /proc/tty/drivers: read failed: EACCES (Permission denied)

如题:java.io.FileNotFoundException: /proc/tty/drivers: read failed: EACCES Permission denied

问题的出现

在使用Google开源的串口库时,其中有一个类是去扫描节点文件的这个文件叫SerialPortFinder,它会去专门扫描一个路径 /proc/tty/drivers,如果是在Android低版本下有读写存储权限且路径 /proc/tty/drivers 权限大于等于666时,基本上都是可以直接扫描到 /dev/tty 这些路径节点的,但是如果在Android高版本时,因为SELinux的加入导致大多数涉及串口开发的应用都会碰壁,本章博客就告诉你为什么在系统权限都赋予的情况下,为什么依旧还是报错

Android高版本权限处理

    private void checkExternalPermission() {
        Log.e(TAG, "checkExternalPermission Build.VERSION.SDK_INT = " + Build.VERSION.SDK_INT);

        //Android 6.0 (23) 之上 Android 11 (30) 以下申请权限
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
            if (checkAllPermissionGranted(permissions, this)) {
                jumpToMainActivity();
            } else {
                ActivityCompat.requestPermissions(this, permissions, requestExternalPermission);
            }
        }
        //Android11申请权限
        else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            //判断是否有管理外部存储的权限
            if (!Environment.isExternalStorageManager()) {
                Log.e(TAG, "MANAGE_EXTERNAL_STORAGE DENIED...");
                goManagerFileAccess();
                return;
            }
            Log.e(TAG, "MANAGE_EXTERNAL_STORAGE GRANTED...");
            jumpToMainActivity();
        }
    }

上述代码区分了Android11和Android11之下的权限申请问题,只是为说明问题而写请不要copy使用!因为还有Android10和9等等一些版本也要区别对待,否则有可能会报错!
意思是在11之下申请所需要的权限就行了,11之后需要手动去设置给与manager权限,当你拿到权限之后以为可以读写串口了,但你错了,这并不会使你成功

你会得到如下log日志信息:

2023-07-06 21:35:14.963 3630-3630/com.licheedev.serialtool W/edev.serialtool: type=1400 audit(0.0:91): avc: denied { read } for name="drivers" dev="proc" ino=4026531853 scontext=u:r:system_app:s0 tcontext=u:object_r:proc_tty_drivers:s0 tclass=file permissive=0
2023-07-06 21:35:14.967 3630-3630/com.licheedev.serialtool W/System.err: java.io.FileNotFoundException: /proc/tty/drivers: open failed: EACCES (Permission denied)
2023-07-06 21:35:14.971 3630-3630/com.licheedev.serialtool W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:492)
2023-07-06 21:35:14.971 3630-3630/com.licheedev.serialtool W/System.err:     at java.io.FileInputStream.<init>(FileInputStream.java:160)
2023-07-06 21:35:14.971 3630-3630/com.licheedev.serialtool W/System.err:     at java.io.FileInputStream.<init>(FileInputStream.java:115)
2023-07-06 21:35:14.971 3630-3630/com.licheedev.serialtool W/System.err:     at java.io.FileReader.<init>(FileReader.java:58)
2023-07-06 21:35:14.971 3630-3630/com.licheedev.serialtool W/System.err:     at android.serialport.SerialPortFinder.getDrivers(SerialPortFinder.java:71)
2023-07-06 21:35:14.972 3630-3630/com.licheedev.serialtool W/System.err:     at android.serialport.SerialPortFinder.getAllDevicesPath(SerialPortFinder.java:114)
2023-07-06 21:35:14.972 3630-3630/com.licheedev.serialtool W/System.err:     at com.licheedev.serialtool.activity.MainActivity.initDevice(MainActivity.java:107)
2023-07-06 21:35:14.972 3630-3630/com.licheedev.serialtool W/System.err:     at com.licheedev.serialtool.activity.MainActivity.onCreate(MainActivity.java:76)
2023-07-06 21:35:14.972 3630-3630/com.licheedev.serialtool W/System.err:     at android.app.Activity.performCreate(Activity.java:8000)
2023-07-06 21:35:14.973 3630-3630/com.licheedev.serialtool W/System.err:     at android.app.Activity.performCreate(Activity.java:7984)
2023-07-06 21:35:14.973 3630-3630/com.licheedev.serialtool W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
2023-07-06 21:35:14.974 3630-3630/com.licheedev.serialtool W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
2023-07-06 21:35:14.974 3630-3630/com.licheedev.serialtool W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
2023-07-06 21:35:14.974 3630-3630/com.licheedev.serialtool W/System.err:     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
2023-07-06 21:35:14.974 3630-3630/com.licheedev.serialtool W/System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
2023-07-06 21:35:14.974 3630-3630/com.licheedev.serialtool W/System.err:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
2023-07-06 21:35:14.975 3630-3630/com.licheedev.serialtool W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
2023-07-06 21:35:14.975 3630-3630/com.licheedev.serialtool W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
2023-07-06 21:35:14.975 3630-3630/com.licheedev.serialtool W/System.err:     at android.os.Looper.loop(Looper.java:223)
2023-07-06 21:35:14.976 3630-3630/com.licheedev.serialtool W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7656)
2023-07-06 21:35:14.976 3630-3630/com.licheedev.serialtool W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2023-07-06 21:35:14.976 3630-3630/com.licheedev.serialtool W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
2023-07-06 21:35:14.977 3630-3630/com.licheedev.serialtool W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2023-07-06 21:35:14.978 3630-3630/com.licheedev.serialtool W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
2023-07-06 21:35:14.978 3630-3630/com.licheedev.serialtool W/System.err:     at libcore.io.Linux.open(Native Method)
2023-07-06 21:35:14.978 3630-3630/com.licheedev.serialtool W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
2023-07-06 21:35:14.978 3630-3630/com.licheedev.serialtool W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
2023-07-06 21:35:14.979 3630-3630/com.licheedev.serialtool W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
2023-07-06 21:35:14.979 3630-3630/com.licheedev.serialtool W/System.err:     at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7542)
2023-07-06 21:35:14.979 3630-3630/com.licheedev.serialtool W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:478)

此时你肯定很疑惑,为什么权限都有了还报没有权限的错误,现在请看下面这段Log

2023-07-06 21:35:14.963 3630-3630/com.licheedev.serialtool W/edev.serialtool: type=1400 audit(0.0:91): avc: denied { read } for name="drivers" dev="proc" ino=4026531853 scontext=u:r:system_app:s0 tcontext=u:object_r:proc_tty_drivers:s0 tclass=file permissive=0

此段log为系统SELinux报的错误,当然要想解决还得从系统上解决

问题的解决

首先你得要熟悉系统SELinux代码和配置,找到安全规则和权限配置文件后,需要添加如下权限给
/proc/tty/drivers

allow system_app proc_tty_drivers:file { read write open getattr };

如笔者的配置则在/device/&{product}/&{board}/common/sepolicy/system_app.te

allow system_app serial_device:chr_file rw_file_perms;
allow system_app tty_device:chr_file { read write ioctl open };
allow system_app vendor_cusdata_file:dir { search getattr open read };
allow system_app vendor_cusdata_file:file { getattr open read write};
allow system_app tv_certificate_file:dir { search getattr read };
allow system_app tv_certificate_file:file { getattr open read write};
allow system_app apk_data_file:dir { search getattr read };
allow system_app apk_data_file:file { getattr open read write};
allow mediaserver vendor_cusdata_file:file { getattr open read };
allow system_app serial_device:chr_file { read write open ioctl}; 
# give /proc/tty/drivers read write open getattr permission
allow system_app proc_tty_drivers:file { read write open getattr }; 

这里笔者介绍一些语法的意义,该段规则为允许系统级app 对 /proc/tty/drivers 进行 read write open getattr 操作,请大家一定要把这些权限加上

缺 read 权限时,报错:
java.io.FileNotFoundException: /proc/tty/drivers: read failed: EACCES (Permission denied)

缺 open 权限时,报错:
java.io.FileNotFoundException: /proc/tty/drivers: open failed: EACCES (Permission denied)

缺 getattr 权限时,报错:
java.io.FileNotFoundException: /proc/tty/drivers: fstat failed: EACCES (Permission denied)

除write权限可选之外,其他3个权限必须要给予!否则都会报错!

题外拓展

上述 te 文件中 allow 后面的 system_app 为系统及 app,何为系统app呢,就是原生framework下的一些系统级app,当然还有后期内置的有系统签名的app,在 selinux 中app主要分为三大类,按照权限高低分别是 system_app 、platform_app、untrusted_app

system_app :拥有系统权限、系统签名、当AndroidManifest.xml中申明persistent时可以生效

platform_app:没有系统权限、系统签名、当AndroidManifest.xml中申明android:sharedUserId=“android.uid.system” 时也可以生效为系统app(需要再配置mk文件),当app为系统级时,此种方式可以不用push直接studio run apk就可以安装到系统并且具有系统权限,做系统开发时非常的方便

untrusted_app:没有系统权限、没有系统签名、来自第三方的app(安装此类型app需要在开发者中关闭USB安装授权,否则安装不了)

三方app如何具备系统签名

1.首先需要下载一个工具,keytool-importkeypair-master
2.下载完后进行解压,然后进入系统根目录下 build/target/product/security
3. 拷贝 platform.x509.pem、platform.pk8 两个文件到2步骤解压的目录下
4.执行命令(需要linux环境,如果没有可以使用Git的Open Git Bash here) keytool-importkeypair -k [jks文件名] -p [jks的密码] -pk8 platform.pk8 -cert platform.x509.pem -alias [jks的别名]
5.将生成的jks拷贝到Android studio中并且配置gradle文件

解压目录图示:

解压图示
拷贝至Android studio中图示:

拷贝到studio中

配置gradle文件图示:

配置gradle

继续处理权限问题

当配置完 te 的权限问题后,全编系统代码待系统编译完后烧录固件查看效果

获得权限
可以看到我们的app已经可以正常操作 /proc/tty/drivers 了,也读取到了 /dev/tty 的各个节点文件

原创不易,希望各位老板点赞关注!后续会更加努力创作!

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Engineer-Jsp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值