InputReader把一些2进制的数据转换成MoionEvent转换完成后通过InputDispather派发下去InputReader和InputDispather是运行在SystemServer里的2个线程一 getevent详细讲解触摸相关开发都必须要掌握的一个命令getevent1、具体使用方法wkubuntu:~$ adb shell * daemon not running; starting now at tcp:5037 * daemon started successfully generic_x86_64:/ # getevent -h Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device] -t: show time stamps -n: dont print newlines -s: print switch states for given bits -S: print all switch states -v: verbosity mask (errs1, dev2, name4, info8, vers16, pos. events32, props64) -d: show HID descriptor, if available -p: show possible events (errs, dev, name, pos. events) -i: show all device info and possible events -l: label event types and names in plain text -q: quiet (clear verbosity mask) -c: print given number of events then exit -r: print rate events are received 1|generic_x86_64:/ #这里我们来简单看一下这个命令使用方式上面列出了很多参数对应的解释这里就不一一讲解了我们就几个主要的-t: show time stamps --显示事件的发生时间-l: label event types and names in plain text —这里表示要把event事件类型名字打印出来-r: print rate events are received --显示一下接受事件速率一般调试使用命令:getevent -lrt127|generic_x86_64:/ # getevent -ltr add device 1: /dev/input/event0 name: Power Button add device 2: /dev/input/event2 name: goldfish_rotary add device 3: /dev/input/event1 name: qwerty2 could not get driver version for /dev/input/mouse1, Not a typewriter could not get driver version for /dev/input/mouse0, Not a typewriter could not get driver version for /dev/input/mice, Not a typewriter [ 178.261688] /dev/input/event1: EV_ABS ABS_MT_TRACKING_ID 00000000 [ 178.261688] /dev/input/event1: EV_ABS ABS_MT_TOUCH_MAJOR 00000003 [ 178.261688] /dev/input/event1: EV_ABS ABS_MT_PRESSURE 00000081 [ 178.261688] /dev/input/event1: EV_ABS ABS_MT_POSITION_X 00002457 [ 178.261688] /dev/input/event1: EV_ABS ABS_MT_POSITION_Y 00002c88 [ 178.261688] /dev/input/event1: EV_SYN SYN_REPORT 00000000 [ 178.262113] /dev/input/event1: EV_ABS ABS_MT_POSITION_X 0000249b [ 178.262113] /dev/input/event1: EV_SYN SYN_REPORT 00000000 rate 2352 [ 178.270577] /dev/input/event1: EV_ABS ABS_MT_POSITION_Y 00002cb1 [ 178.270577] /dev/input/event1: EV_SYN SYN_REPORT 00000000这里就会打印出对应的格式进行介绍[ 160898.678739] /dev/input/event1: EV_ABS ABS_MT_TOUCH_MAJOR 00000003时间 具体节点文件名 事件类型 事件code 事件value从以上打印就可以看出我们此时手机产生了哪些事件若没有数据输出则驱动出问题了2、getevent源码分析system/core/toolbox/getevent.c//省略部分 static void print_event(int type, int code, int value, int print_flags) { const char *type_label, *code_label, *value_label; if (print_flags PRINT_LABELS) { type_label get_label(ev_labels, type); code_label NULL; value_label NULL; switch(type) { case EV_SYN: code_label get_label(syn_labels, code); break; case EV_KEY: code_label get_label(key_labels, code); value_label get_label(key_value_labels, value); break; case EV_REL: code_label get_label(rel_labels, code); break; case EV_ABS: code_label get_label(abs_labels, code); switch(code) { case ABS_MT_TOOL_TYPE: value_label get_label(mt_tool_labels, value); } break; case EV_MSC: code_label get_label(msc_labels, code); break; case EV_LED: code_label get_label(led_labels, code); break; case EV_SND: code_label get_label(snd_labels, code); break; case EV_SW: code_label get_label(sw_labels, code); break; case EV_REP: code_label get_label(rep_labels, code); break; case EV_FF: code_label get_label(ff_labels, code); break; case EV_FF_STATUS: code_label get_label(ff_status_labels, code); break; } if (type_label) printf(%-12.12s, type_label); else printf(%04x , type); if (code_label) printf( %-20.20s, code_label); else printf( %04x , code); if (value_label) printf( %-20.20s, value_label); else printf( %08x , value); } else { printf(%04x %04x %08x, type, code, value); } } //省略部分 static int open_device(const char *device, int print_flags) { int version; int fd; int clkid CLOCK_MONOTONIC; struct pollfd *new_ufds; char **new_device_names; char name[80]; char location[80]; char idstr[80]; struct input_id id; fd open(device, O_RDONLY | O_CLOEXEC);//打开这个节点 if(fd 0) { if(print_flags PRINT_DEVICE_ERRORS) fprintf(stderr, could not open %s, %s\n, device, strerror(errno)); return -1; } if(ioctl(fd, EVIOCGVERSION, version)) { if(print_flags PRINT_DEVICE_ERRORS) fprintf(stderr, could not get driver version for %s, %s\n, device, strerror(errno)); return -1; } if(ioctl(fd, EVIOCGID, id)) { if(print_flags PRINT_DEVICE_ERRORS) fprintf(stderr, could not get driver id for %s, %s\n, device, strerror(errno)); return -1; } name[sizeof(name) - 1] \0; location[sizeof(location) - 1] \0; idstr[sizeof(idstr) - 1] \0; if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), name) 1) { //fprintf(stderr, could not get device name for %s, %s\n, device, strerror(errno)); name[0] \0; } if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), location) 1) { //fprintf(stderr, could not get location for %s, %s\n, device, strerror(errno)); location[0] \0; } if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), idstr) 1) { //fprintf(stderr, could not get idstring for %s, %s\n, device, strerror(errno)); idstr[0] \0; } if (ioctl(fd, EVIOCSCLOCKID, clkid) ! 0) { fprintf(stderr, Cant enable monotonic clock reporting: %s\n, strerror(errno)); // a non-fatal error } new_ufds realloc(ufds, sizeof(ufds[0]) * (nfds 1)); if(new_ufds NULL) { fprintf(stderr, out of memory\n); return -1; } ufds new_ufds; new_device_names realloc(device_names, sizeof(device_names[0]) * (nfds 1)); if(new_device_names NULL) { fprintf(stderr, out of memory\n); return -1; } device_names new_device_names; if(print_flags PRINT_DEVICE) printf(add device %d: %s\n, nfds, device); if(print_flags PRINT_DEVICE_INFO) printf( bus: %04x\n vendor %04x\n product %04x\n version %04x\n, id.bustype, id.vendor, id.product, id.version); if(print_flags PRINT_DEVICE_NAME) printf( name: \%s\\n, name); if(print_flags PRINT_DEVICE_INFO) printf( location: \%s\\n id: \%s\\n, location, idstr); if(print_flags PRINT_VERSION) printf( version: %d.%d.%d\n, version 16, (version 8) 0xff, version 0xff); if(print_flags PRINT_POSSIBLE_EVENTS) { print_possible_events(fd, print_flags); } if(print_flags PRINT_INPUT_PROPS) { print_input_props(fd); } if(print_flags PRINT_HID_DESCRIPTOR) { print_hid_descriptor(id.bustype, id.vendor, id.product); } ufds[nfds].fd fd;//非常关键点这里赋值给了ufds后面会把ufds统一加入poll ufds[nfds].events POLLIN;//感兴趣的事件只有POLLIN即有数据可以读取了 device_names[nfds] strdup(device); nfds; return 0; } int close_device(const char *device, int print_flags) { int i; for(i 1; i nfds; i) { if(strcmp(device_names[i], device) 0) { int count nfds - i - 1; if(print_flags PRINT_DEVICE) printf(remove device %d: %s\n, i, device); free(device_names[i]); memmove(device_names i, device_names i 1, sizeof(device_names[0]) * count); memmove(ufds i, ufds i 1, sizeof(ufds[0]) * count); nfds--; return 0; } } if(print_flags PRINT_DEVICE_ERRORS) fprintf(stderr, remote device: %s not found\n, device); return -1; } //读取/dev/input路径下面的节点内容变化 static int read_notify(const char *dirname, int nfd, int print_flags) { int res; char devname[PATH_MAX]; char *filename; char event_buf[512]; int event_size; int event_pos 0; struct inotify_event *event; res read(nfd, event_buf, sizeof(event_buf)); if(res (int)sizeof(*event)) { if(errno EINTR) return 0; fprintf(stderr, could not get event, %s\n, strerror(errno)); return 1; } //printf(got %d bytes of event information\n, res); strcpy(devname, dirname); filename devname strlen(devname); *filename /; while(res (int)sizeof(*event)) { event (struct inotify_event *)(event_buf event_pos); //printf(%d: %08x \%s\\n, event-wd, event-mask, event-len ? event-name : ); if(event-len) { strcpy(filename, event-name); if(event-mask IN_CREATE) { open_device(devname, print_flags); } else { close_device(devname, print_flags); } } event_size sizeof(*event) event-len; res - event_size; event_pos event_size; } return 0; } //读取扫描路径下的节点 static int scan_dir(const char *dirname, int print_flags) { char devname[PATH_MAX]; char *filename; DIR *dir; struct dirent *de; dir opendir(dirname); if(dir NULL) return -1; strcpy(devname, dirname); filename devname strlen(devname); *filename /; while((de readdir(dir))) { if(de-d_name[0] . (de-d_name[1] \0 || (de-d_name[1] . de-d_name[2] \0))) continue; strcpy(filename, de-d_name); open_device(devname, print_flags); } closedir(dir); return 0; } int getevent_main(int argc, char *argv[]) { int c; int i; int res; int get_time 0; int print_device 0; char *newline \n; uint16_t get_switch 0; struct input_event event; int print_flags 0; int print_flags_set 0; int dont_block -1; int event_count 0; int sync_rate 0; int64_t last_sync_time 0; const char *device NULL; const char *device_path /dev/input; /* disable buffering on stdout */ setbuf(stdout, NULL); opterr 0; do { c getopt(argc, argv, tns:Sv::dpilqc:rh);//过滤参数 if (c EOF) break; switch (c) { case t: get_time 1; break; case n: newline ; break; case s: get_switch strtoul(optarg, NULL, 0); if(dont_block -1) dont_block 1; break; case S: get_switch ~0; if(dont_block -1) dont_block 1; break; case v: if(optarg) print_flags | strtoul(optarg, NULL, 0); else print_flags | PRINT_DEVICE | PRINT_DEVICE_NAME | PRINT_DEVICE_INFO | PRINT_VERSION; print_flags_set 1; break; case d: print_flags | PRINT_HID_DESCRIPTOR; break; case p: print_flags | PRINT_DEVICE_ERRORS | PRINT_DEVICE | PRINT_DEVICE_NAME | PRINT_POSSIBLE_EVENTS | PRINT_INPUT_PROPS; print_flags_set 1; if(dont_block -1) dont_block 1; break; case i: print_flags | PRINT_ALL_INFO; print_flags_set 1; if(dont_block -1) dont_block 1; break; case l: print_flags | PRINT_LABELS; break; case q: print_flags_set 1; break; case c: event_count atoi(optarg); dont_block 0; break; case r: sync_rate 1; break; case ?: fprintf(stderr, %s: invalid option -%c\n, argv[0], optopt); case h: usage(argv[0]); exit(1); } } while (1); if(dont_block -1) dont_block 0; if (optind 1 argc) { device argv[optind]; optind; } if (optind ! argc) { usage(argv[0]); exit(1); } nfds 1; ufds calloc(1, sizeof(ufds[0])); ufds[0].fd inotify_init();//初始化inotify主要负责监听文件夹内容变化 ufds[0].events POLLIN; if(device) { if(!print_flags_set) print_flags | PRINT_DEVICE_ERRORS; res open_device(device, print_flags); if(res 0) { return 1; } } else { if(!print_flags_set) print_flags | PRINT_DEVICE_ERRORS | PRINT_DEVICE | PRINT_DEVICE_NAME; print_device 1; //添加inotify观察路径为device_path res inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE); if(res 0) { fprintf(stderr, could not add watch for %s, %s\n, device_path, strerror(errno)); return 1; } res scan_dir(device_path, print_flags);//扫描遍历所有节点且打开节点 if(res 0) { fprintf(stderr, scan dir failed for %s\n, device_path); return 1; } } //省略部分 while(1) { //int pollres poll(ufds, nfds, -1); //最为核心的poll类似以前说过epoll但是效率比epoll低 //printf(poll %d, returned %d\n, nfds, pollres); if(ufds[0].revents POLLIN) {//第1个fd其实是文件夹里面内容变化 read_notify(device_path, ufds[0].fd, print_flags); } for(i 1; i nfds; i) { if(ufds[i].revents) { if(ufds[i].revents POLLIN) {//非第1个fd其实具体节点内容有变化 res read(ufds[i].fd, event, sizeof(event));//读取对应内容数据 if(res (int)sizeof(event)) { fprintf(stderr, could not get event\n); return 1; } if(get_time) { printf([%8ld.%06ld] , event.time.tv_sec, event.time.tv_usec); } if(print_device) printf(%s: , device_names[i]); print_event(event.type, event.code, event.value, print_flags);//打印具体event内容 if(sync_rate event.type 0 event.code 0) { int64_t now event.time.tv_sec * 1000000LL event.time.tv_usec; if(last_sync_time) printf( rate %lld, 1000000LL / (now - last_sync_time)); last_sync_time now; } printf(%s, newline); if(event_count --event_count 0) return 0; } } } } return 0; }从代码可以看出其实这个程序整体逻辑是非常非常清晰主要就分为2个大部分1、监听/dev/input目录中里面内容的变化即该目录下是否有增加和减少节点2、监听/dev/input下面具体每个节点中的内容变化如果有内容变化则读取内容打印出读取内容