Android系统韦根调试从驱动到应用(二)

Android系统韦根调试从驱动到应用

软件开发平台:android P 源码。
硬件开发平台:nxp imx8m mini开发板。

本文记录在nxp 8m mini 硬件平台, androidP 源码的软件平台上调试韦根驱动,增加韦根的framework 层,并能在APP 应用层 获取韦根数据的流程。

二.韦根Framework 层调试
作为APP开发者是不需要知道驱动是如何工作的,只需要在读卡器贴卡时能得到卡号就可以了。上面我们完成了驱动的开发,那怎么上报给APP开发者呢, 就需要framework 这个桥梁了。
Framework 就相当于上面驱动代码的应用层。只是在framework在 read 到卡号后,还需要将卡号广播到android 系统中。所以 韦根framework层要做两件事,读到卡号,广播卡号.
这里贴出 WiegandManagerService的代码

class WiegandManagerService extends SystemService {

    static final String TAG = "WiegandManagerService";


    byte[] wiegand_value = new byte[ 20 ];

    public WiegandManagerService(Context context) {
        super(context);

    }

    public void onStart() {
        Log.d(TAG, "onStart: ");
        //   mNativeData = init();

         WiegandThread waitThread = new WiegandThread();
         waitThread.start();
     }


    private class WiegandThread extends Thread
    {
        public WiegandThread()
        {
            super("WiegandThread");
        }

        public void run()
        {

            while (true) {

                try {
                    Log.d(TAG, "run: waitForWiegand");
                    //long result = waitForWiegand();
                    Arrays.fill(wiegand_value, (byte)0);
		//阻塞的这里等待读卡器读卡号, 这里需要判断返回值如果是韦根OPEN出错,说明驱动未准备好,则应该退出 service,否则会占用资源. 如果是读卡号出错,继续等待.
                    int result = waitForWiegand(wiegand_value);
                    String CARD_NO = new String(wiegand_value, "UTF-8");
                    Log.d(TAG, "run: waitForWiegand " + result+" CARD_NO :"+CARD_NO+" length "+CARD_NO.length() );

                    String localChartSet = System.getProperty("file.encoding");
                    Log.d(TAG,"localChartSet>>>>"+localChartSet);   //查看本地默认字符集
		//发送广播 ,在Intent.java 增加广播
                    Intent intent = new Intent(Intent.ACTION_WIEGAND_CHANGED);
                    intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
                            | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
                            | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
                    intent.putExtra("wiegand_value", CARD_NO);
                    getContext().sendBroadcastAsUser(intent, UserHandle.ALL);


                }catch(Exception e){
                    Log.d(TAG, "e: "+e.toString() );
                }
            }
        }
    }


    //private native long waitForWiegand( );
    private native int waitForWiegand(byte[] value);
}

在SystemServer中启动WiegandManagerService。
Android系统韦根调试从驱动到应用(二)_第1张图片
并注册ACTION_WIEGAND_CHANGED 广播。
Android系统韦根调试从驱动到应用(二)_第2张图片
JNI 部分代码如下:

#define LOG_TAG "WiegandManagerService"

#include 
#include "jni.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


namespace android {

#define WIEGAND_FILE "dev/wiegand"
static int fd;
//java 的byte 是8 个字节,和C 的char 字长一致,这里使用jbyteArray
static jint android_server_WiegandManagerService_waitForWiegand(JNIEnv* env, jobject clazz/* this */, jbyteArray  byteArray)
{

    int result = 0;

    ALOGD("%s\n",__func__);
    jsize numChars   = env->GetArrayLength(byteArray);
    ALOGD("%s length %d\n",__func__, numChars);
    jbyte *jbytes  = (jbyte*)calloc(numChars, sizeof(jbyte));//开辟jbyte类型内存空间
    memset(jbytes, 0, numChars);
    if(jbytes == NULL){
        ALOGD("UPON : calloc error.\n");
        return -1;
    }
    fd = open(WIEGAND_FILE, O_RDWR);//打开dev/wiegand设备文件
    if (fd < 0)//小于0说明没有成功
    {
        ALOGD("error, can't open wiegand file (%s)\n", strerror(errno));
        return -1;
    }

    ALOGD("%s read fd %d\n", __func__ , fd);
//阻塞在这里等待读卡号
    result = read(fd, jbytes, numChars );
    //copy buffer to jchar array
    ALOGD("%s read %s  result : %d\n",__func__, (char *)jbytes , result);

    env->SetByteArrayRegion(byteArray,0,numChars,jbytes);//复制pArray的jbytes数据元素到jbyteArray

    free(jbytes);//
    return (jint)result;

}

static const JNINativeMethod sMethods[] = {
     /* name, signature, funcPtr */
    {"waitForWiegand", "([B)I", (void*)android_server_WiegandManagerService_waitForWiegand},

};

int register_android_server_WiegandManagerService(JNIEnv* env)
{
    return jniRegisterNativeMethods(env, "com/android/server/WiegandManagerService",
                                    sMethods, NELEM(sMethods));
}

} /* namespace android */

将com_android_server_WiegandManagerService.cpp加入系统
Android系统韦根调试从驱动到应用(二)_第3张图片
因为驱动是root 用户权限, WiegandManagerService 是system_server 用户,所以存在selinux 权限不通过的问题。

在这里插入图片描述

使用 external/selinux/prebuilts/bin/audit2allow 可以解决权限问题,
#============= system_server ==============
allow system_server device:chr_file open;
修改文件权限
Android系统韦根调试从驱动到应用(二)_第4张图片
如果有编译问题,再解决编译问题。

运行后可以看到 在读卡器不贴卡时 WiegandManagerServcie 阻塞在read 函数等待

在这里插入图片描述

贴卡后,
在这里插入图片描述
读出卡号,再次等待。这里有个乱码的问题。

————————————————
版权声明:本文为CSDN博主「大熊的瓜地」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/blueheart05/article/details/106116954

你可能感兴趣的:(android开发)