android 系統添加jni,註冊本地方法

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 原生方法命名規則

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章