一丶简介
平台:msm8953
环境:ubuntu16.04
Android app对/dev下的设备是不具有读写权限的,应用程序怎样才能读写/dev下设备呢?本文以spi设备为例,应用程序通过jni的方法去访问/dev下的spi设备。
配置好spi后,在dev下出现了spidev6.0的设备节点,通过ls -l -Z /dev/spidev6.0,可见:
crw------- 1 root root u:object_r:device:s0 226
此设备拥有者为root,其他用户或用户组不具有读写权限。
二丶步骤
1. 给spidev6.0读写权限:
位置:device/qcom/common/rootdir/etc/init.qcom.rc
添加,
chmod 777 /dev/spidev6.0
编译boot烧写后,运行测试程序:
打开失败,android具有selinux机制,不允许未知来源的app读写设备。所以我们得配置/dev/spidev6.0允许未知来源app读写。
2.添加设备:
位置:device/qcom/sepolicy/common/file_contexts
Dev nodes下添加,
/dev/spidev6.0 u:object_r:spidev_device:s0
3.自定义设备类型
位置:device/qcom/sepolicy/common/device.te
添加,
type spidev_device, dev_type, mlstrustedobject;
4.允许未知来源app操作spi
未知:device/qcom/sepolicy/common/untrusted_app.te
allow untrusted_app spidev_device:chr_file rw_file_perms;
此时运行应用程序,打开spidev成功!
附源码:
MainActivity.java:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private final static String TAG = "MainActivity";
public final static String SPIDEV = "/dev/spidev6.0";
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Spi spi = new Spi();
int ret = spi.open(SPIDEV);
if(ret == -1)
Log.e(TAG,"open spidev failed :"+ SPIDEV);
else
Log.e(TAG,"success,fd :"+ ret);
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
Spi.java
public class Spi {
int fd;
private final static String TAG = "Spi";
private String spiName;
public Spi() {}
public Spi(String spiName){
this.spiName = spiName;
}
public int open(String spiName){
fd = open_native(spiName);
return fd > 0 ? fd :-1;
}
private native int open_native(String spiName);
}
spi.cpp
//
// Created by liujian on 2019/10/9.
//
#include <cstring>
#include <fcntl.h>
#include "jni.h"
/**
* @author liujian
* @date 2019-07-02
* @brief open spi
* @param deviceName:index
* @return file descriptor
*/
static int spiOpen(char const* deviceName){
int fd=open(deviceName,O_RDWR);//读写方式 int fd=open(deviceName,O_RDWR|O_NONBLOCK);
if(fd<0){
return -1;
}
return fd;
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_sc60devicesutils_Spi_open_1native(JNIEnv *env, jobject instance,
jstring spiName_) {
const char *spiName = env->GetStringUTFChars(spiName_, 0);
char item_value[128];
strcpy(item_value, spiName);
env->ReleaseStringUTFChars(spiName_, spiName);
return spiOpen(item_value);
}
别忘了在CMakeList里面加入spi.cpp:
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp
spi.cpp)