Android 12.0 工厂模式增加串口功能测试

Android 12.0 工厂模式增加串口功能测试

最近接到项目需求需要增加一个串口功能测试项,具体修改参考如下:

1./vendor/freeme/packages/apps/FreemeFactoryTest/res/values/strings.xml

+    <string name="uhf_label">UART</string>
+    <string name="uhf_hint">Uart data to send.</string>
+    <string name="send_transmit_power_data">Send</string>

2./vendor/freeme/packages/apps/FreemeFactoryTest/res/layout/uhf.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/main_background"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >
        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAppearance="@android:style/TextAppearance.DeviceDefault.Large"
            android:text="@string/uhf_hint" />
            
        <Button
            android:id="@+id/send_transmit_power"
            android:text="@string/send_transmit_power_data"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAllCaps="false"/>

        <TextView
            android:layout_height="wrap_content"
            android:layout_width="fill_parent"
            android:hint="Uart data to send."
	    android:textSize="20sp" 
            android:id="@+id/get_transmit_power">
        </TextView>

    </LinearLayout>

    <include layout="@layout/common_bottom_bar"/>
</LinearLayout>

3./vendor/freeme/packages/apps/FreemeFactoryTest/AndroidManifest.xml

+        <activity
+            android:name=".serial.UHF"
+            android:label="@string/uhf_label"
+            android:screenOrientation="portrait" />

4./vendor/freeme/packages/apps/FreemeFactoryTest/jni/com_freeme_factory_serial_SerialPort.cpp

#include "jni.h"

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <jni.h>
#include <strings.h>

#include "android/log.h"

static const char *TAG="serial_port";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO,  TAG, fmt, ##args)
#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)

#ifndef _Included_com_freeme_factory_serial_SayHello
#define _Included_com_freeme_factory_serial_SayHello

#ifdef __cplusplus
extern "C" {
#endif

int fd;

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;
    }
}

int set_opt(jint nBits, jchar nEvent, jint nStop ,speed_t speed)
{
    LOGE("set_opt: nBits=%d, nEvent=%c, nStop=%d", nBits, nEvent, nStop);
    struct termios newtio;

    if(tcgetattr(fd, & newtio) != 0)
    {
        LOGE("setup serial failure");
        return -1;
    }

    bzero( & newtio, sizeof(newtio));
    newtio.c_cflag |= CLOCAL | CREAD;

    switch(nBits)
    {
        case 7:
            newtio.c_cflag &= ~CSIZE;
            newtio.c_cflag |= CS7;
            break;
        case 8:
            newtio.c_cflag &= ~CSIZE;
            newtio.c_cflag |= CS8;
            break;
        default:
            newtio.c_cflag &= ~CSIZE;
            newtio.c_cflag |= CS8;
            break;
    }

    switch(nEvent)
    {
        case 'o':
        case 'O':
            newtio.c_cflag |= (PARODD | PARENB);
            newtio.c_iflag |= INPCK;
            break;
        case 'e':
        case 'E':
            newtio.c_cflag |= PARENB;
            newtio.c_cflag &= ~PARODD;
            newtio.c_iflag |= INPCK;
            break;
        case 'N':
        case 'n':
            newtio.c_cflag &= ~PARENB;
            break;
        default:
            newtio.c_cflag &= ~PARENB;
            break;
    }

	cfsetispeed(&newtio, speed);
	cfsetospeed(&newtio, speed);

    switch(nStop)
    {
        case 1:
            newtio.c_cflag &= ~CSTOPB;
            break;
        case 2:
            newtio.c_cflag |= CSTOPB;
            break;
        default:
            newtio.c_cflag &= ~CSTOPB;
            break;
    }

    newtio.c_cc[VTIME] = 100;
    newtio.c_cc[VMIN] = 0;

    tcflush(fd, TCIFLUSH);
    if(tcsetattr(fd, TCSANOW, & newtio) != 0)
    {
        LOGE("options set error");
        close(fd);
        return -1;
    }
    LOGE("options set success");
    return 1;
}

 /*
  * Class:     android_serialport_SerialPort
  * Method:    open
  * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
  */
 JNIEXPORT jobject JNICALL Java_com_freeme_factory_serial_SerialPort_open
    (JNIEnv *env, jobject thiz, jstring path, jint baudrate,
     jint databits, jint stopbits, jchar parity)
{
    speed_t speed;
    jobject mFileDescriptor;

    {
        speed = getBaudrate(baudrate);
        LOGE("set_opt: baudrate=%d", baudrate);
        LOGE("set_opt: nSpeed=%d", speed);
        if (speed == -1)
        {
            /* TODO: throw an exception */
            LOGE("Invalid baudrate");
            return NULL;
        }
    }

    /* Opening device */
    {
        jint flags = 0;
        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|O_NOCTTY|O_NONBLOCK);
        LOGD("open() fd = %d", fd);
        env->ReleaseStringUTFChars(path, path_utf);
        if (fd == -1)
        {
            /* Throw an exception */
            LOGE("Cannot open port");
            /* 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);
		set_opt(databits, parity, stopbits,speed);
		
        //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:     cedric_serial_SerialPort
 * Method:    close
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_freeme_factory_serial_SerialPort_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);
}

#ifdef __cplusplus
}
#endif
#endif

5./vendor/freeme/packages/apps/FreemeFactoryTest/jni/Android.mk

LOCAL_SRC_FILES := \
+    com_freeme_factory_serial_SerialPort.cpp

6./vendor/freeme/packages/apps/FreemeFactoryTest/src/com/freeme/factory/FactoryTest.java

+import com.freeme.factory.serial.UHF;

public void testItem(int item) {

+        case TestConfig.TEST_ITEM_UHF:
+            intent.setClass(this, UHF.class);
+            startActivityForResult(intent, item);
+            break;

7./vendor/freeme/packages/apps/FreemeFactoryTest/src/com/freeme/factory/config/TestConfig.java

+    public static final boolean TEST_EN_UHF                = true;

+    public static final int TEST_ITEM_UHF                 = 62;

private static final int[] kTestItems_Full = {

+        TEST_ITEM_UHF,

static {
        /* -- TODO: Custom */

+        __disable_feature(TEST_ITEM_UHF, TEST_EN_UHF);

public static String getNameByItemId(Context c, int id) {

+        case TEST_ITEM_UHF:
+            resid = R.string.uhf_label;
+            break;

8./vendor/freeme/packages/apps/FreemeFactoryTest/src/com/freeme/factory/serial/SerialPort.java
 

package com.freeme.factory.serial;


import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.util.Log;

public class SerialPort {

    private static final String TAG = "SerialPort";
    /*
    * Do not remove or rename the field mFd: it is used by native method close();
    */
    private FileDescriptor mFd;
    private FileInputStream mFileInputStream;
    private FileOutputStream mFileOutputStream;

    public SerialPort(File device, int baudrate) throws SecurityException, IOException {
        mFd = open(device.getAbsolutePath(), baudrate);
        if (mFd == null) {
            Log.e(TAG, "native open returns null");
            throw new IOException();
        }
        mFileInputStream = new FileInputStream(mFd);
        mFileOutputStream = new FileOutputStream(mFd);
    }

    public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
        mFd = open(device.getAbsolutePath(), baudrate, 8, 1, 'N');
        if (mFd == null) {
            Log.e(TAG, "native open returns null");
            throw new IOException();
        }
        mFileInputStream = new FileInputStream(mFd);
        mFileOutputStream = new FileOutputStream(mFd);
    }

    public SerialPort(File device, int baudrate, int dataBits, int stopBits, char parity) throws SecurityException, IOException {
        mFd = open(device.getAbsolutePath(), baudrate, dataBits, stopBits, parity);
        if (mFd == null) {
            Log.e(TAG, "native open returns null");
            throw new IOException();
        }
        mFileInputStream = new FileInputStream(mFd);
        mFileOutputStream = new FileOutputStream(mFd);
    }

    // Getters and setters
    public InputStream getInputStream() {
        return mFileInputStream;
    }

    public OutputStream getOutputStream() {
        return mFileOutputStream;
    }

    // JNI
    private native static FileDescriptor open(String path, int baudrate);
    private native static FileDescriptor open(String path, int baudrate, int flags);
    private native static FileDescriptor open(String path, int baudrate, int dataBits, int stopBits, char parity);
    public native void close();
    static {
        System.loadLibrary("jni_factory_speaker");
    }
}

9./vendor/freeme/packages/apps/FreemeFactoryTest/src/com/freeme/factory/serial/UHF.java

package com.freeme.factory.serial;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.RadioButton;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;

import com.freeme.factory.base.BaseTest;
import com.freeme.factory.FactoryTest;
import com.freeme.factory.R;

public class UHF extends BaseTest{
    private static final String TAG = "UHF";

    private static final int MSG_TRANSMIT_POWER = 0;

    private static boolean isFlagSerial = false;
    private TextView mGetTransmitPower ;
    private Button mSendTransmitPower ;
    private FileOutputStream mOutputStream;
    private FileInputStream mInputStream;
    private SerialPort mSerialPort;
    private String strData = "";
    
    private byte[] get_transmit_power_cmd = {input data};
	
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_TRANSMIT_POWER:
                    mSendTransmitPower.setEnabled(true);
                    sendString(byteToStr(get_transmit_power_cmd, get_transmit_power_cmd.length));
                    break;

                default:
                    break;
            }
            Log.e(TAG, "handleMessage---> " + msg.what);
            receive(msg.what);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.uhf);

        mGetTransmitPower = (TextView) findViewById(R.id.get_transmit_power);

        mSendTransmitPower = (Button) findViewById(R.id.send_transmit_power);
        mSendTransmitPower.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                mSendTransmitPower.setEnabled(false);
                mGetTransmitPower.setText("");
                mHandler.sendEmptyMessageDelayed(MSG_TRANSMIT_POWER, 1000);
            }
        });
        //writeFile("/sys/switch_power/uhf_power", "1");
        SetupSerial();
        testActionCompleted(false);
    }

    private void sendString(String sendData) {
        if (!isFlagSerial || mOutputStream == null) {
            return;
        }
        try {
            Log.d(TAG, "sendString ---> sendData  " + sendData );
            mOutputStream.write(hex2byte(sendData));
            mOutputStream.flush();
            Toast.makeText(getApplicationContext(), "=> " + getFileAddSpace(sendData), Toast.LENGTH_SHORT).show();
            Log.e(TAG, "=> " + getFileAddSpace(sendData));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void receive(int type) {
        if (isFlagSerial) {
            try {
                byte[] readData = new byte[4096];
                if (mInputStream == null) {
                    return;
                }
                int size = mInputStream.read(readData);
                Log.d(TAG, "receive---> size " + size );
                if (size > 0) {
                    strData = byteToStr(readData, size);
                    strData = getFileAddSpace(strData);
                    Log.d(TAG, "receive---> strData " + strData);
                    onDataReceived(strData, type);
                    testActionCompleted(true);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void onDataReceived(String strData, int type) {
        runOnUiThread(new Runnable() {
            public void run() {
                if (mGetTransmitPower != null && type == 0) {
                    mGetTransmitPower.append(strData);
                    Log.e(TAG, "<= " + getFileAddSpace(strData));
                }
            }
        });
    }

    private void SetupSerial() {
        try {
            mSerialPort = new SerialPort(new File("UART PATH"), 115200, 8, 1, 'N');
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        isFlagSerial = true;
        Log.e(TAG, "SetupSerial---> " + mSerialPort);
        if (mSerialPort != null) {
            mInputStream = (FileInputStream) mSerialPort.getInputStream();
            mOutputStream = (FileOutputStream) mSerialPort.getOutputStream();
            Log.e(TAG, "SetupSerial---> mInputStream " + mInputStream);
            Log.e(TAG, "SetupSerial---> mOutputStream " + mOutputStream);
        }
    }

    private void writeFile(String psam_path, String val) {
        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(psam_path);
            if (fileWriter != null) {
                fileWriter.write(val);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fileWriter != null) {
                try {
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy...");
        resetSerial();
        super.onDestroy();
    }

    private void waitFor(int seconds) {
        try {
            Thread.sleep(seconds);
        } catch (InterruptedException ignore) {
            // ignore exception
        }
    }

    private void resetSerial() {
        isFlagSerial = false;
        //writeFile("/sys/switch_power/uhf_power", "0");
        //writeFile(PSAM_CONTROL1_PATH, "0");
    }

    private String getFileAddSpace(String replace) {
        String regex = "(.{2})";
        return replace.replaceAll(regex, "$1 ");
    }

    private static byte[] hex2byte(String hex) {
        String digital = "0123456789ABCDEF";
        String hex1 = hex.replace(" ", "");
        char[] hex2char = hex1.toCharArray();
        byte[] bytes = new byte[hex1.length() / 2];
        byte temp;
        for (int p = 0; p < bytes.length; p++) {
            temp = (byte) (digital.indexOf(hex2char[2 * p]) * 16);
            temp += digital.indexOf(hex2char[2 * p + 1]);
            bytes[p] = (byte) (temp & 0xff);
            Log.d(TAG,"hex2byte " + bytes[p]);
        }
        return bytes;
    }

    private static String byteToStr(byte[] b, int size) {
        String ret = "";
        for (int i = 0; i < size; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret += hex.toUpperCase();
        }
        return ret;
    }

    private static String getSum16(byte[] msg, int length) {
        long mSum = 0;
        byte[] mByte = new byte[length];

        for (byte byteMsg : msg) {
            long mNum = ((long) byteMsg >= 0) ? (long) byteMsg : ((long) byteMsg + 256);
            mSum += mNum;
        }

        for (int liv_Count = 0; liv_Count < length; liv_Count++) {
            mByte[length - liv_Count - 1] = (byte) (mSum >> (liv_Count * 8) & 0xff);
        }
        return byteToStr(msg, length) + byteToStr(mByte, mByte.length).substring(byteToStr(mByte, mByte.length).length() - 4, byteToStr(mByte, mByte.length).length());
    }
}

重新编译验证,修改生效,工厂模式已增加串口功能测试

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jeffries_C

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

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

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

打赏作者

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

抵扣说明:

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

余额充值