Android 模拟系统事件(二)

简介

JNI(Java Native Interface)是本地编程接口,它允许Java代码和其他语言写的代码进行交互,它可以在 Java 虚拟机 (VM) 内部运行的 Java 代码与用其它编程语言(如 C、C++ 和汇编语言)编写的应用程序和库进行交互操作。

功能

通过jni实现向Android系统注入事件,从而实现模拟按键、模拟触屏等操作!用它直接跳过上面的Android平台权限的问题!

原理是在jni中通过Linux内核的ioctl函数和c语言函数(memset、write)来实现对设备的I/O通道进行管理的。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数如下:

[java]  view plain copy
  1. int ioctl(int fd, ind cmd, …)  
[java]  view plain copy
  1. void *memset(void *s,int c,size_t n)  //总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c。  
[java]  view plain copy
  1. ssize_t write(int fd,const void *buf,size_t nbytes) //将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数.失败时返回-1. 并设置errno变量. 在网络程序中,当我们向套接字文件描述符写时有俩种可能.   


其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和cmd的意义相关的。

代码实现

关键代码如下:

[java]  view plain copy
  1. jint Java_net_pocketmagic_keyinjector_NativeInput_intEnableDebug( JNIEnv* env,jobject thiz, jint enable ) {  
  2.   
  3.     g_debug = enable;  
  4.     if (enable == 1) debug("Debug enabled.");  
  5.     return g_debug;  
  6. }  
  7.   
  8. jint Java_net_pocketmagic_keyinjector_NativeInput_intCreate( JNIEnv* env,jobject thiz, jstring inputdev, jint keyboard, jint mouse)  
  9. {  
  10.       
  11.     jboolean iscopy;  
  12.     char szDev[255] = "";  
  13.     const char *pszDev = (*env)->GetStringUTFChars(env, inputdev, &iscopy);  
  14.     if (pszDev) strncpy(szDev, pszDev, 255);  
  15.     (*env)->ReleaseStringUTFChars(env, inputdev, pszDev);  
  16.     debug("intCreate call (%s)", szDev);  
  17.       
  18.     struct uinput_dev dev;  
  19.     int fd_kb, aux;  
  20.   
  21.     fd_kb = open(szDev, O_RDWR);  
  22.     if (fd_kb < 0) {  
  23.         debug("Can't open input device:%s ", szDev);  
  24.         return -1;  
  25.     }  
  26.   
  27.     memset(&dev, 0, sizeof(dev));  
  28.     strcpy(dev.name, "AndroidKeyInjector Input");  
  29.     dev.id.bustype = 0x0003;// BUS_USB;  
  30.     dev.id.vendor  = 0x0000;  
  31.     dev.id.product = 0x0000;  
  32.     dev.id.version = 0x0000;  
  33.   
  34.     if (write(fd_kb, &dev, sizeof(dev)) < 0) {  
  35.         debug("Can't write device information");  
  36.         close(fd_kb);  
  37.         return -1;  
  38.     }  
  39.   
  40.     if (mouse) {  
  41.         ioctl(fd_kb, UI_SET_EVBIT, EV_REL);  
  42.         for (aux = REL_X; aux <= REL_MISC; aux++)  
  43.             ioctl(fd_kb, UI_SET_RELBIT, aux);  
  44.     }  
  45.   
  46.     if (keyboard) {  
  47.         ioctl(fd_kb, UI_SET_EVBIT, EV_KEY);  
  48.         ioctl(fd_kb, UI_SET_EVBIT, EV_LED);  
  49.         ioctl(fd_kb, UI_SET_EVBIT, EV_REP);  
  50.   
  51.         for (aux = KEY_RESERVED; aux <= KEY_UNKNOWN; aux++)  
  52.             ioctl(fd_kb, UI_SET_KEYBIT, aux);  
  53.   
  54.         //for (aux = LED_NUML; aux <= LED_MISC; aux++)  
  55.         //  ioctl(fd_kb, UI_SET_LEDBIT, aux);  
  56.     }  
  57.   
  58.     if (mouse) {  
  59.         ioctl(fd_kb, UI_SET_EVBIT, EV_KEY);  
  60.   
  61.         for (aux = BTN_LEFT; aux <= BTN_BACK; aux++)  
  62.             ioctl(fd_kb, UI_SET_KEYBIT, aux);  
  63.     }  
  64.   
  65.     ioctl(fd_kb, UI_DEV_CREATE);  
  66.     debug("intCreate success: %d",  fd_kb);  
  67.     return fd_kb;  
  68. }  
  69.   
  70. void  Java_net_pocketmagic_keyinjector_NativeInput_intClose( JNIEnv* env,jobject thiz, jint fd_kb)  
  71. {  
  72.     close(fd_kb);  
  73. }  
  74.   
  75. void Java_net_pocketmagic_keyinjector_NativeInput_intSendEvent( JNIEnv* env,jobject thiz, int fd_kb, uint16_t type, uint16_t code, int32_t value)  
  76. {  
  77.     debug("intSendEvent call (%d,%d,%d,%d)", fd_kb, type, code, value);  
  78.     struct uinput_event event;  
  79.     int len;  
  80.   
  81.     if (fd_kb <= fileno(stderr))  
  82.         return;  
  83.   
  84.     memset(&event, 0, sizeof(event));  
  85.     event.type = type;  
  86.     event.code = code;  
  87.     event.value = value;  
  88.   
  89.     len = write(fd_kb, &event, sizeof(event));  
  90.     debug("intSendEvent done:%d",len);  
  91. }   

其中的事件id 可以参考 Android源码地址

调用代码如下:

[java]  view plain copy
  1. public class NativeInput {  
  2.     int m_fd;  
  3.     final static int EV_KEY = 0x01;  
  4.   
  5.     public NativeInput() {  
  6.         intEnableDebug(1);  
  7.         for (int i = 0; i < 8; i++) {  
  8.             m_fd = intCreate("/dev/input/event" + i, 10);  
  9.             if (m_fd != -1)  
  10.                 break;  
  11.         }  
  12.     }  
  13.   
  14.     public static int chmod(String path, int mode) throws Exception {  
  15.         Class fileUtils = Class.forName("android.os.FileUtils");  
  16.         Method setPermissions = fileUtils.getMethod("setPermissions",  
  17.                 String.classint.classint.classint.class);  
  18.         return (Integer) setPermissions.invoke(null, path, mode, -1, -1);  
  19.     }  
  20.   
  21.     public int SendKey(int key, boolean state) {  
  22.         if (state)  
  23.             return intSendEvent(m_fd, EV_KEY, key, 1); // key down  
  24.         else  
  25.             return intSendEvent(m_fd, EV_KEY, key, 0); // key up  
  26.     }  
  27.   
  28.     native int intEnableDebug(int enabled); // 1 will output to logcat, 0 will  
  29.                                             // disable  
  30.     //  
  31.   
  32.     native int intCreate(String dev, int kb, int mouse);  
  33.   
  34.     native void intClose(int fd);  
  35.   
  36.     native int intSendEvent(int fd, int type, int code, int value);  
  37.   
  38.     static {  
  39.         System.loadLibrary("input");  
  40.     }  
  41. }  

其它相关代码如下:

[java]  view plain copy
  1. int EVT_open(struct NATIVE_INFO *info)  
  2. {  
  3.     struct input_absinfo absinfo;  
  4.    
  5.     if(initEVT)  
  6.         return 0;  
  7.    
  8.     if(info == NULL)  
  9.     {  
  10.         LOGE("info null point.");  
  11.         goto fail;  
  12.     }  
  13.    
  14.     if(info->FB_width == 0 || info->FB_height == 0)  
  15.     {  
  16.         LOGE("error width %d and height %d.", info->FB_width, info->FB_height);  
  17.         goto fail;  
  18.     }  
  19.    
  20.     memset(&ei, 0, sizeof(ei));  
  21.     ei.screen_width = info->FB_width;  
  22.     ei.screen_height = info->FB_height;  
  23.    
  24.     scan_dir(DEV_DIR);  
  25.    
  26.     if(ioctl(ei.fd_touch, EVIOCGABS(ABS_X), &absinfo)) {  
  27.         LOGI("Error reading absolute controller ABS_X[%d]: %s", errno, strerror(errno));  
  28.         return;  
  29.     }  
  30.     ei.abs_x_min = absinfo.minimum;  
  31.     ei.abs_x_max = absinfo.maximum;  
  32.    
  33.     if(ioctl(ei.fd_touch, EVIOCGABS(ABS_Y), &absinfo)) {  
  34.         LOGI("Error reading absolute controller ABS_Y[%d]: %s", errno, strerror(errno));  
  35.         return;  
  36.     }  
  37.     ei.abs_y_min = absinfo.minimum;  
  38.     ei.abs_y_max = absinfo.maximum;  
  39.    
  40.     initEVT = 1;  
  41.     return 0;  
  42.    
  43. fail:  
  44.     EVT_close();  
  45.     return -1;  
  46. }  
  47.    
  48. int EVT_close()  
  49. {  
  50.     if(ei.fd_key > 0)  
  51.         close(ei.fd_key);  
  52.     if(ei.fd_touch > 0)  
  53.         close(ei.fd_touch);  
  54.    
  55.     initEVT = 0;  
  56.     return 0;  
  57. }  
  58.    
  59. int EVT_touch(int action, float x, float y)  
  60. {  
  61.     int abs_x, abs_y;  
  62.    
  63.     if(initEVT == 0)  
  64.     {  
  65.         LOGE("event not inital");  
  66.         return -1;  
  67.     }  
  68.    
  69.     switch(action)  
  70.     {  
  71.     case ACTION_DOWN:  
  72.         calculateXY(x, y, &abs_x, &abs_y);  
  73.         write_event(ei.fd_touch, 30, abs_x);  
  74.         write_event(ei.fd_touch, 31, abs_y);  
  75.         write_event(ei.fd_touch, 13301);  
  76.         write_event(ei.fd_touch, 000);  
  77.         break;  
  78.     case ACTION_UP:  
  79.         write_event(ei.fd_touch, 13300);  
  80.         write_event(ei.fd_touch, 000);  
  81.         break;  
  82.     case ACTION_MOVE:  
  83.         calculateXY(x, y, &abs_x, &abs_y);  
  84.         write_event(ei.fd_touch, 30, abs_x);  
  85.         write_event(ei.fd_touch, 31, abs_y);  
  86.         write_event(ei.fd_touch, 000);  
  87.         break;  
  88.     }  
  89.     return 0;  
  90. }  
  91.    
  92. int EVT_key(int action, int key)  
  93. {  
  94.     if(initEVT == 0)  
  95.     {  
  96.         LOGE("event not inital");  
  97.         return -1;  
  98.     }  
  99.    
  100.     switch(action)  
  101.     {  
  102.     case ACTION_DOWN:  
  103.         write_event(ei.fd_key, 1, key, 1);  
  104.         break;  
  105.     case ACTION_UP:  
  106.         write_event(ei.fd_key, 1, key, 0);  
  107.         break;  
  108.     }  
  109.     return 0;  
  110. }  
  111.    
  112.    
  113. int scan_dir(const char *dirname)  
  114. {  
  115.     char devname[PATH_MAX];  
  116.     char *filename;  
  117.     DIR *dir;  
  118.     struct dirent *de;  
  119.     dir = opendir(dirname);  
  120.     if(dir == NULL)  
  121.         return -1;  
  122.     strcpy(devname, dirname);  
  123.     filename = devname + strlen(devname);  
  124.     *filename++ = '/';  
  125.     while((de = readdir(dir))) {  
  126.         if(de->d_name[0] == '.' &&  
  127.            (de->d_name[1] == '\0' ||  
  128.             (de->d_name[1] == '.' && de->d_name[2] == '\0')))  
  129.             continue;  
  130.         strcpy(filename, de->d_name);  
  131.         open_dev(devname);  
  132.     }  
  133.     closedir(dir);  
  134.     return 0;  
  135. }  
  136.    
  137. int open_dev(const char *deviceName)  
  138. {  
  139.     int fd;  
  140.     int version;  
  141.     uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];  
  142.     uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];  
  143.    
  144.     fd = open(deviceName, O_RDWR);  
  145.     if(fd < 0) {  
  146.         LOGI("could not open device[%d]: %s", errno, strerror(errno));  
  147.         return -1;  
  148.     }  
  149.    
  150.     if(ioctl(fd, EVIOCGVERSION, &version)) {  
  151.         return -1;  
  152.     }  
  153.    
  154.     memset(key_bitmask, 0, sizeof(key_bitmask));  
  155.     if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {  
  156.         if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))  
  157.                 || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),  
  158.                         sizeof_bit_array(BTN_DIGI))  
  159.                 || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),  
  160.                         sizeof_bit_array(KEY_MAX + 1))) {  
  161.             ei.fd_key = fd;  
  162.             LOGI("get key input device: %s", deviceName);  
  163.         }  
  164.     }  
  165.    
  166.     memset(abs_bitmask, 0, sizeof(abs_bitmask));  
  167.     if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {  
  168.         // Is this a new modern multi-touch driver?  
  169.         if (test_bit(ABS_MT_POSITION_X, abs_bitmask)  
  170.                 && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {  
  171.             ei.fd_touch = fd;  
  172.             LOGI("get multi-touch input device: %s", deviceName);  
  173.    
  174.         // Is this an old style single-touch driver?  
  175.         } else if (test_bit(BTN_TOUCH, key_bitmask)  
  176.                 && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {  
  177.             ei.fd_touch = fd;  
  178.             LOGI("get single-touch input device: %s", deviceName);  
  179.         }  
  180.     }  
  181. }  
  182.    
  183. int write_event(int fd, int type, int code, int value)  
  184. {  
  185.     struct input_event event;  
  186.    
  187.     memset(&event, 0, sizeof(event));  
  188.     event.type = type;  
  189.     event.code = code;  
  190.     event.value = value;  
  191.     if(write(fd, &event, sizeof(event)) < sizeof(event)) {  
  192.         LOGI("write event failed[%d]: %s", errno, strerror(errno));  
  193.         return -1;  
  194.     }  
  195.     return 0;  
  196. }  
  197.    
  198. void calculateXY(float x, float y, int *abs_x, int *abs_y)  
  199. {  
  200.     *abs_x = ei.abs_x_min +  
  201.             (int)((x * (float)(ei.abs_x_max - ei.abs_x_min)) / ei.screen_width + 0.5);  
  202.     *abs_y = ei.abs_y_min +  
  203.             (int)((y * (float)(ei.abs_y_max - ei.abs_y_min)) / ei.screen_height + 0.5);  
  204. }  
  205.    
  206. int containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex)  
  207. {  
  208.     const uint8_t* end = array + endIndex;  
  209.     array += startIndex;  
  210.     while (array != end) {  
  211.         if (*(array++) != 0) {  
  212.             return 1;  
  213.         }  
  214.     }  
  215.     return 0;  
  216. }  

结论

以上是使用ioctl来实现对设备i/o控制,如果不用ioctl的话,也可以实现对设备I/O通道的控制。例如,我们可以在驱动程序中实现write的时候检查一下是否有特殊约定的数据流通过,如果有的话,那么后面就跟着控制命令。但是如果这样做的话,会导致代码分工不明,程序结构混乱,程序员自己也会头昏眼花的。所以,我们就使用ioctl来实现控制的功能。


下载

项目下载


From: http://blog.csdn.net/banketree/article/details/10474331


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值