image

背景

  • Platform: RK3399
  • OS: Android7.1.2
  • Kernel: v4.4.103

内核及系统配置

正常流程

RK3399的串口采用的是8250通用驱动.

  1. 确定DTS里面已经okey,dev下设备节点是否存在
  2. 确认设备节点权限:
    文件(./device/rockchip/common/ueventd.rockchip.rc):
    /dev/ttyS4          0666   system     system

    Selinux问题(未验证,开启Selinux后需注意):

  3. 在device/rockchip/rk3399/xxx/sepolicy/目录下,添加untrusted_app.te;
    allow  untrusted_app  serial_device:chr_file  {read open ioctl getattr create write};
  4. 在device.mk和system_server.te添加并编译权限;
    +BOARD_SEPOLICY_DIRS += \
    +  device/rockchip/rk3399/rk3399_firefly_edp_box/sepolicy
    +
    +BOARD_SEPOLICY_UNION += \
    +  untrusted_app.te
    rw_dir_perms包含read write;
    
    +#untrusted_app
    +allow system_server serial_device:chr_file rw_file_perms;
  5. selinux security level引起的denied u:r:untrusted_app:s0:c512,c768问题,由于security level为MLS访问机制所添加的安全上下文的扩展部分mlstrustedsubject,这一attribute包含了所有能越过MLS检查的客体type。所以在device.te加入type serial_device, dev_type, mlstrustedobject;
    2019-06-04 11:40:17.518 1696-1696/? W/ample.hello_ros: type=1400 audit(0.0:74): avc: denied { write } for name="ttyS3" dev="tmpfs" ino=2524 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_f

    JNI

    Android并没有包含串口的JNI, 需要我们自己实现。(Android Thing已经有实现)
    串口JNI的参考范例见谷歌的开源代码 android_serial_api: https://github.com/cepr/android-serialport-api

准备SO文件

使用现成的SO文件,但可能存在版本不兼容问题。
使用NDK重新编译so文件,可参考:使用NDK编译原生库或可执行应用程序

配置工程

  1. 在工程java目录下新建package, 名称固定为android_serialport_api
  2. 将源码里的Java文件SerialPort.javaSerialportFinder.java拷贝到上面新建的包下
  3. 新建libs目录,拷贝编译好的SO文件到该目录,根据自己的平台选择对应的APP_ABI文件夹
  4. 在build.grandle(Moudle:app)中添加:
    android{
        ...
        sourceSets {
            main() {
                jniLibs.srcDirs = ['libs']
            }
        }
        ...
    }

    参考

  5. [RK3399][Android7.1] 调试笔记 — 串口JNI测试用例
  6. Android 串口通讯集成
  7. Android 串口开发