1.添加.cpp文件
- frameworks/base/services/core/jni/com_android_server_IrScanManagerService.cpp
...
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <jni.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include "com_android_server_IrScanManagerService.h"
#include "android/log.h"
static const char *TAG="serial_port";
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)
#define INTERCOM_UART_NAME "/dev/ttyMT1"
#define SCAN_DEV_NAME "/dev/scan_dev"
#define CHECK_SENSOR_STATE_CMD_LEN 6
#define GET_DEVICE_INFO_CMD_LEN 6
#define WAKEUP_SCAN_CMD_LEN 1
#define SCAN_OPEN_BEEP_LEN 8
#define SCAN_GETVERSION_LEN 6
#define SCAN_DECODE_PRE_CMD_LEN 11
#define SCAN_DECODE_START_CMD_LEN 6
#define SCAN_IOC_MAGIC 'S'
#define SCAN_SET_POWER_ON -IO(SCAN_IOC_MAGIC,0)
#define SCAN_SET_POWER_OFF -IO(SCAN_IOC_MAGIC,1)
static int fd;
static int fd_uart_dev = 0;
static int fd_scan_dev = 0;
static pthread_rwlock_t uart_rwlock;
unsigned char check_sensor_state_cmd[CHECK_SENSOR_STATE_CMD_LEN] = {0x04,0xA3,0x04,0x00,0xFF,0x55};
unsigned char get_device_info_cmd[GET_DEVICE_INFO_CMD_LEN] = {0x1F,0x0F,0x00,0x03,0x01,0x00};
unsigned char wakeup_scan_cmd[WAKEUP_SCAN_CMD_LEN] = {0x00};
unsigned char scan_open_beep_cmd[SCAN_OPEN_BEEP_LEN] = {0x06,0xD7,0x04,0x00,0x04,0x4D,0xFE,0xCE};
unsigned char scan_getversion_cmd[SCAN_GETVERSION_LEN] = {0x04,0xA3,0x04,0x00,0xFF,0x55};
unsigned char scan_decode_pre_cmd[SCAN_DECODE_PRE_CMD_LEN] = {0x09,0xD6,0x04,0x00,0x00,0x01,0x91,0x01,0x05,0xFE,0x85};
unsigned char scan_decode_start_cmd[SCAN_DECODE_START_CMD_LEN] = {0x04,0xE4,0x04,0x00,0xFF,0x14};
static int config_serial(int fd,int nSpeed,int nBits,char nEvent,int nStop)
{
struct termios newtio;
bzero(&newtio, sizeof (newtio));
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
//set speed
switch (nSpeed)
{
case 9600:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
LOGE("UART Speed = 9600 !\n");
break;
case 19200:
cfsetispeed(&newtio,B19200);
cfsetospeed(&newtio,B19200);
LOGE("UART Speed = 19200 !\n");
break;
case 57600:
cfsetispeed(&newtio,B57600);
cfsetospeed(&newtio,B57600);
LOGE("UART Speed = 57600 !\n");
break;
default :
break;
}
switch (nBits)
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
//set verify
switch (nEvent)
{
case 'o':
case 'O': //odd
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'e':
case 'E': //even
newtio.c_iflag |= (INPCK |ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'n':
case 'N': //no
newtio.c_cflag &= ~PARENB;
newtio.c_iflag &= ~INPCK;
break;
}
//set stop bit
if (nStop == 1)
{
newtio.c_cflag &= ~CSTOPB;
}
else if (nStop == 2)
{
newtio.c_cflag |= CSTOPB;
}
if ((tcsetattr(fd,TCSANOW,&newtio)) != 0)
{
return -1;
}
else
{
//ALOGE("----- tcflush ---- 1 ---");
//tcflush (fd,TCIOFLUSH);//這裏會影響短信的接收,所以要屏蔽
}
return 0;
}
static speed_t getBaudrate(jint baudrate)
{
switch(baudrate) {
case 0: return B0;
case 50: return B50;
case 75: return B75;
case 110: return B110;
case 134: return B134;
case 150: return B150;
case 200: return B200;
case 300: return B300;
case 600: return B600;
case 1200: return B1200;
case 1800: return B1800;
case 2400: return B2400;
case 4800: return B4800;
case 9600: return B9600;
case 19200: return B19200;
case 38400: return B38400;
case 57600: return B57600;
case 115200: return B115200;
case 230400: return B230400;
case 460800: return B460800;
case 500000: return B500000;
case 576000: return B576000;
case 921600: return B921600;
case 1000000: return B1000000;
case 1152000: return B1152000;
case 1500000: return B1500000;
case 2000000: return B2000000;
case 2500000: return B2500000;
case 3000000: return B3000000;
case 3500000: return B3500000;
case 4000000: return B4000000;
default: return -1;
}
}
/*
* Class: com_android_server_IrScanManagerService
* Method: open
* Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
*/
JNIEXPORT jobject JNICALL Java_com_android_server_IrScanManagerService_open
(JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags)
{
speed_t speed;
jobject mFileDescriptor;
/* Check arguments */
{
speed = getBaudrate(baudrate);
if (speed == -1) {
/* TODO: throw an exception */
LOGE("Invalid baudrate");
return NULL;
}
}
/* Opening device */
{
jboolean iscopy;
const char *path_utf = env->GetStringUTFChars(path, &iscopy);
LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags);
fd = open(path_utf, O_RDWR | flags);
LOGD("open() fd = %d", fd);
env->ReleaseStringUTFChars( path, path_utf);
if (fd == -1)
{
/* Throw an exception */
LOGE("Cannot open port %s",path_utf);
/* TODO: throw an exception */
return NULL;
}
}
/* Configure device */
{
struct termios cfg;
LOGD("Configuring serial port");
if (tcgetattr(fd, &cfg))
{
LOGE("tcgetattr() failed");
close(fd);
/* TODO: throw an exception */
return NULL;
}
cfmakeraw(&cfg);
cfsetispeed(&cfg, speed);
cfsetospeed(&cfg, speed);
// cfg.c_cflag &= ~CSIZE;
// cfg.c_cflag |= CS8;
// cfg.c_cflag &= ~CSTOPB;
if (tcsetattr(fd, TCSANOW, &cfg))
{
LOGE("tcsetattr() failed");
close(fd);
/* TODO: throw an exception */
return NULL;
}
}
/* Create a corresponding file descriptor */
{
jclass cFileDescriptor = env->FindClass( "java/io/FileDescriptor");
jmethodID iFileDescriptor = env->GetMethodID( cFileDescriptor, "<init>", "()V");
jfieldID descriptorID = env->GetFieldID( cFileDescriptor, "descriptor", "I");
mFileDescriptor = env->NewObject( cFileDescriptor, iFileDescriptor);
env->SetIntField( mFileDescriptor, descriptorID, (jint)fd);
}
return mFileDescriptor;
}
/*
* Class: com_android_server_IrScanManagerService
* Method: close
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_android_server_IrScanManagerService_close
(JNIEnv *env, jobject thiz)
{
jclass SerialPortClass = env->GetObjectClass( thiz);
jclass FileDescriptorClass = env->FindClass( "java/io/FileDescriptor");
jfieldID mFdID = env->GetFieldID( SerialPortClass, "mFd", "Ljava/io/FileDescriptor;");
jfieldID descriptorID = env->GetFieldID( FileDescriptorClass, "descriptor", "I");
jobject mFd = env->GetObjectField( thiz, mFdID);
jint descriptor = env->GetIntField( mFd, descriptorID);
LOGD("close(fd = %d)", descriptor);
close(descriptor);
// pthread_rwlock_destroy(&uart_rwlock);//destroy rwlock.
}
static int wakeup_machine(void)
{
jint ret;
int i;
if(fd<=0){
LOGE("uart open is error");
return 0;
}
for(i=0;i<3;i++){
ret = write(fd,wakeup_scan_cmd,WAKEUP_SCAN_CMD_LEN);
usleep(2000);
}
if(ret<0){
LOGE("wakeup_machine uart write error, ret=%d",ret);
}else{
LOGE("wakeup_machine uart wirte is ok,ret=%d",ret);
}
usleep(25000);
return 0;
}
/*
* Class: com_android_server_IrScanManagerService
* Method: openUart
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_android_server_IrScanManagerService_openUart(JNIEnv *env, jclass thiz)
{
LOGE("JNI open uart start---1----");
int ret = 0;
//return;
if (fd_scan_dev <= 0)
{
fd_scan_dev = open(SCAN_DEV_NAME,O_RDWR | O_NOCTTY);
if (fd_scan_dev > 0){
LOGE("Open scan_dev and fd=%d\n",fd_scan_dev);
//config_serial(fd_uart_dev,9600,8,'n',1);
//ret = ioctl(fd_scan_dev,SCAN_SET_POWER_ON);
write(fd_scan_dev,"1",2);
}
else
{
LOGE("Open scan_dev fail!\n");
_exit;
}
LOGE("Open scan_dev sucessful!fd=%d\n",fd_scan_dev);
}
LOGE("----- tcflush ---- 2 ---");
//tcflush(fd_uart_dev, TCIOFLUSH); //clear the buffer
}
/*
* Class: com_android_server_IrScanManagerService
* Method: closeUart
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_android_server_IrScanManagerService_closeUart(JNIEnv *env, jclass thiz)
{
LOGE("JNI close uart start----0----");
//return ;
if (fd_scan_dev){
write(fd_scan_dev,"0",2);
close(fd_scan_dev);
LOGE("close %s sucessful!\n",SCAN_DEV_NAME);
}
fd_scan_dev = 0;
}
/*
* Class: com_android_server_IrScanManagerService
* Method: getScanCode
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_android_server_IrScanManagerService_getScanCode(JNIEnv *env, jclass thiz)
{
int ret;
int i;
LOGE("JNI check sensor state start,fd=%d",fd);
if(fd<=0){
LOGE("uart open is error");
return;
}
wakeup_machine();
ret = write(fd,scan_decode_pre_cmd,SCAN_DECODE_PRE_CMD_LEN);
ret = write(fd,scan_decode_start_cmd,SCAN_DECODE_START_CMD_LEN);
if(ret<0){
LOGE("uart write error, ret=%d",ret);
}else{
LOGE("uart wirte is ok,ret=%d",ret);
}
}
2.添加頭文件
- frameworks/base/services/core/jni/com_android_server_IrScanManagerService.h
#include <jni.h>
#ifndef PORTABLEPOWERBANKCTRLDEMO_SERIALPORT_H
#define PORTABLEPOWERBANKCTRLDEMO_SERIALPORT_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_android_server_IrScanManagerService
* Method: open
* Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
*/
JNIEXPORT jobject JNICALL Java_com_android_server_IrScanManagerService_open
(JNIEnv *, jclass, jstring, jint, jint);
JNIEXPORT void JNICALL Java_com_android_server_IrScanManagerService_close
(JNIEnv *, jobject);
JNIEXPORT void JNICALL Java_com_android_server_IrScanManagerService_openUart
(JNIEnv *env, jclass thiz);
JNIEXPORT void JNICALL Java_com_android_server_IrScanManagerService_closeUart
(JNIEnv *env, jclass thiz);
JNIEXPORT void JNICALL Java_com_android_server_IrScanManagerService_getScanCode
(JNIEnv *env, jclass thiz);
#ifdef __cplusplus
}
#endif
#endif //PORTABLEPOWERBANKCTRLDEMO_SERIALPORT_H
3.引入.cpp文件
- frameworks/base/services/core/jni/Android.mk
$(LOCAL_REL_DIR)/com_android_server_IrScanManagerService.cpp \
4.添加本地調用
- frameworks/base/services/core/java/com/android/server/IrScanManagerService.java
package com.android.server
import android.app.IIrScanManager;
import android.content.Context;
import andorid.util.Log;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class IrScanManagerService extends IIrScanManager.Stud {
private static final String TAG = "IrScanManagerService ";
private Context mContext;
private String mUartPort = "/dev/ttyMT1";
private int mUartBaudrate = 9600;
private FileInputStream mFileInputStream;
private FileOutputStream mFileOutputStream ;
private ReadThread mReadThread;
public IrScanManagerService (Context context){
mContext = context;
}
public initSerialPort(String path, int baudrate, int flags){
File file = new File(path);
FileDescriptor mFd = open(file .getAbsolutePath(), baudrate, flags);
mFileInputStream = new FileInputStream(mFd);
mFileOutputStream = new FileOutputStream(mFd);
mReadThread = new ReadThread();
mReadThread.start();
}
@Override
public void open(){
Log.d(TAG,"open");
initSerialPort(mUartPort,mUartBaudrate,0);
}
@Override
public void close(){
Log.d(TAG,"close");
closeStream();
close();
}
@Override
public void getUartData(){
Log.d(TAG,"getUartData");
getScanCode();
}
@Override
public void powerOn(){
Log.d(TAG,"powerOn");
openUart();
}
@Override
public void powerOff(){
Log.d(TAG,"powerOff");
closeUart();
}
// 接收串口數據
private class ReadThread extends Thread {
@Override
public void run() {
super.run();
while (!interrupted()) {
int size = 0;
try {
byte[] buffer = new byte[1024];
if (mInputStream == null) return;
Log.d(TAG, "-------ReadThread");
size = mInputStream.read(buffer);
Log.d(TAG, "-------size:" + size);
if (size > 0) {
String dataStr = "";
int data;
byte[] revBuff = new byte[size];
System.arraycopy(buffer, 0, revBuff, 0, size);
dataStr = new String(revBuff);
Log.d(TAG , "ReadThread uart data:" + dataStr + "!!!!");
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}
/**
* 關閉uart
*/
private void closeStream(){
try {
if(mOutputStream != null) {
mOutputStream.close();
}
if(mInputStream != null) {
mInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
// close();
}
// JNI
private native static FileDescriptor open(String path, int baudrate, int flags);
public native void close();
public native void getScanCode();
public native void openUart();
public native void closeUart();
}
需要注意
本文.cpp中的寫法是JNIEXPORT void JNICALL Java_com_android_server_IrScanManagerService_closeUart(JNIEnv *env, jclass thiz),這種寫法不需要再手動註冊native方法,如果是其他寫法,需要在.cpp中添加手動註冊方法,並在onload.cpp中註冊
- frameworks/base/services/core/jni/onload.cpp
寫法可參考系統中其他.cpp文件
JNI RegisterNatives註冊本地方法
JNI 調用錯誤: No implementation found for native
JNI 原生方法命名規則