Android开发之input子系统一
2018-02-07 18:08
405 查看
一、了解
Android系统主机默认携带input子系统,并且开机就会产生默认的mouse和keyboard事件,这样使得用户开机就可以触屏点击和使用按键。可通过adb shell getevent 命令看到用户input事件产生的信息。Android系统主机也支持链接遥控设备(蓝牙遥控器,dongle遥控器(2.4G),鼠标,键盘等)并根据遥控设备向系统注册的信息,系统生成对应的input事件event,所有event均由uinput 在 /dev/input/event*(数字) 生成。二、input子系统相关命令
2.1 getevent 得到input信息基于Android N,sendevent 源代码位于:/system/core/toolbox/getevent.c
查看源码可知使用如下:
static void usage(char *name) { fprintf(stderr, "Usage: %s [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]\n", name); fprintf(stderr, " -t: show time stamps\n"); fprintf(stderr, " -n: don't print newlines\n"); fprintf(stderr, " -s: print switch states for given bits\n"); fprintf(stderr, " -S: print all switch states\n"); fprintf(stderr, " -v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)\n"); fprintf(stderr, " -d: show HID descriptor, if available\n"); fprintf(stderr, " -p: show possible events (errs, dev, name, pos. events)\n"); fprintf(stderr, " -i: show all device info and possible events\n"); fprintf(stderr, " -l: label event types and names in plain text\n"); fprintf(stderr, " -q: quiet (clear verbosity mask)\n"); fprintf(stderr, " -c: print given number of events then exit\n"); fprintf(stderr, " -r: print rate events are received\n"); }
getevent -i/p 可以查看该event支持的所有keyType和keyCode。
2.2 sendevent 模拟input事件
基于Android N,sendevent源代码位于:/system/core/toolbox/sendevent.c
#include <errno.h> #include <fcntl.h> #include <linux/input.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <unistd.h> int sendevent_main(int argc, char *argv[]) { int fd; ssize_t ret; int version; struct input_event event; if(argc != 5) { fprintf(stderr, "use: %s device type code value\n", argv[0]); return 1; } fd = open(argv[1], O_RDWR); if(fd < 0) { fprintf(stderr, "could not open %s, %s\n", argv[optind], strerror(errno)); return 1; } if (ioctl(fd, EVIOCGVERSION, &version)) { fprintf(stderr, "could not get driver version for %s, %s\n", argv[optind], strerror(errno)); return 1; } memset(&event, 0, sizeof(event)); event.type = atoi(argv[2]); event.code = atoi(argv[3]); event.value = atoi(argv[4]); ret = write(fd, &event, sizeof(event)); if(ret < (ssize_t) sizeof(event)) { fprintf(stderr, "write event failed, %s\n", strerror(errno)); return -1; } return 0; }
通过阅读sendevent.c源码可以得出sendevent的命令格式为:
sendevent event事件 eventType eventKeyCode eventValue
event事件:/dev/input/event*(数字)
eventType:
EV_SYN 0x00 同步事件
EV_KEY 0x01 按键事件
EV_REL 0x02 相对坐标
EV_ABS 0x03 绝对坐标
EV_MSC 0x04 其它
EV_LED 0x11 LED
EV_SND 0x12 声音
EV_REP 0x14 Repeat
EV_FF 0x15 力反馈
EV_PWR 电源
EV_FF_STATUS 状态
eventKeyCode: 通过getevent -i/p查询到的信息
eventValue: 0001 表示down 0000表示up
130|p212:/ $ sendevent /dev/input/event4 1 28 1 p212:/ $ sendevent /dev/input/event4 0 0 0 p212:/ $ sendevent /dev/input/event4 1 28 0 p212:/ $ sendevent /dev/input/event4 0 0 0
这样就模拟了一个确认键。
2.3 input 模拟input 事件
基于Android N,input.java 源代码位于:
/frameworks/base/cmds/input/src/com/android/commands/input
private void showUsage() { System.err.println("Usage: input [<source>] <command> [<arg>...]"); System.err.println(); System.err.println("The sources are: "); for (String src : SOURCES.keySet()) { System.err.println(" " + src); } System.err.println(); System.err.println("The commands and default sources are:"); System.err.println(" text <string> (Default: touchscreen)"); System.err.println(" keyevent [--longpress] <key code number or name> ..." + " (Default: keyboard)"); System.err.println(" tap <x> <y> (Default: touchscreen)"); System.err.println(" swipe <x1> <y1> <x2> <y2> [duration(ms)]" + " (Default: touchscreen)"); System.err.println(" press (Default: trackball)"); System.err.println(" roll <dx> <dy> (Default: trackball)"); }
根据源码可知模拟按键事件:
input keyevent keycode number/name
基于Android N,keycode number/name对应
/frameworks/base/core/java/android/view/KeyEvent.java
input keyevent KEYCODE_DPAD_CENTER
等同于
input keyevent 23
模拟确认键
三、input子系统映射流程
以下源码基于android N3.1 用户按键,发送hid keycode,映射到内核驱动input.c
3.2 input.c将hid keycode 转换成scancode。
3.3 scancode 映射到该event*对应的.kl文件,可通过
dumpsys input
命令查看event*对应的.kl文件,.kl定义内容粗略如下:
key 1 ESCAPE
key 2 1
key 3 2
key 4 3
key 5 4
key 6 5
中间的数组为scancode,最右边的String字符为对应的KeyCodeLabel,
假设现在scancode为1,则映射到对应String字符KeyCodeLabel为: ESCAPE
3.4 ESCAPE 映射到源码目录:
/frameworks/native/include/input/InputEventLabels.h
最终映射到InputEventLabels.h中KEYCODES数组,粗略定义如下:
#define DEFINE_KEYCODE(key) { #key, AKEYCODE_##key } #define DEFINE_AXIS(axis) { #axis, AMOTION_EVENT_AXIS_##axis } #define DEFINE_LED(led) { #led, ALED_##led } #define DEFINE_FLAG(flag) { #flag, POLICY_FLAG_##flag } static const InputEventLabel KEYCODES[] = { // NOTE: If you add a new keycode here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. DEFINE_KEYCODE(UNKNOWN), DEFINE_KEYCODE(SOFT_LEFT), DEFINE_KEYCODE(SOFT_RIGHT), DEFINE_KEYCODE(HOME), DEFINE_KEYCODE(BACK), DEFINE_KEYCODE(CALL), DEFINE_KEYCODE(ENDCALL), ............... { NULL, 0 } };
经过此次映射,ESCAPE变成AKEYCODE_ESCAPE。
3.5 AKEYCODE_ESCAPE映射到keycodes.h中所对应的value,源码位于:
/frameworks/native/include/android/keycodes.h
3.6value 映射到 keyEvent.java,源码位于:
/frameworks/base/core/java/android/view/keyEvent.java
相关文章推荐
- Android开发之input子系统二之创建自己的input
- android input子系统详解
- Android之Input子系统事件分发流程
- Android 4.2 之Input子系统事件分发流程
- Android Framework------之Input子系统
- Android驱动之 Linux Input子系统之TP——A/B(Slot)协议
- Linux/Android——输入子系统input_event传递 (二)
- Android开发2(Toast,AlertDialog,Snackbar,TextInputLayout的使用)
- Android Camera子系统之Linux C应用开发人员View
- Android之Input子系统事件分发流程
- Android4.1 Input子系统中间层算法漏洞分析
- i.mx6 Android6.0.1分析input子系统:测试
- Android Framework------之Input子系统
- input输入子系统:Android-Keylayout英文说明文档
- Android Framework------之Input子系统
- Android开发笔记(一百三十八)文本输入布局TextInputLayout
- linux驱动开发:input子系统三
- Android距离传感调试与input子系统探究
- Linux/Android——输入子系统input_event传递 (二)【转】
- Android之Input子系统与输入法