发布网友 发布时间:2022-04-22 07:20
共1个回答
热心网友 时间:2022-06-17 14:08
1.运行toolbox的getevent 工具。
# getevent -help
getevent -help
Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-p] [-q] [-c count] [-r] [device]
-t: show time stamps
-n: don't print newlines
-s: print switch states for given bits
-S: print all switch states
-v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32)
-p: show possible events (errs, dev, name, pos. events)
-q: quiet (clear verbosity mask)
-c: print given number of events then exit
-r: print rate events are received
# getevent -c 20
getevent -c 20
add device 1: /dev/input/event4
name: "sensor-input"
add device 2: /dev/input/event3
name: "88pm860x_hook"
add device 3: /dev/input/event2
name: "88pm860x_on"
add device 4: /dev/input/event1
name: "88pm860x-touch"
add device 5: /dev/input/event0
name: "pxa27x-keypad"
/dev/input/event0: 0001 0066 00000001
/dev/input/event0: 0000 0000 00000000
/dev/input/event0: 0001 0066 00000000
/dev/input/event0: 0000 0000 00000000
/dev/input/event1: 0003 0000 00000c48
/dev/input/event1: 0003 0001 00000751
/dev/input/event1: 0001 014a 00000001
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0000 00000c67
/dev/input/event1: 0003 0001 000006f9
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0000 00000c9e
/dev/input/event1: 0003 0001 0000069e
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0000 00000cc4
/dev/input/event1: 0003 0001 00000620
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0000 00000ce8
/dev/input/event1: 0003 0001 000005ba
/dev/input/event1: 0000 0000 00000000
运行这个工具,然后按键或者滑动触摸屏,会看到程序会实时打印event。从上面的输出来看,系统有5个input 子系统。它们分别是
add device 1: /dev/input/event4
name: "sensor-input"
#Sensor input 子系统
add device 2: /dev/input/event3
name: "88pm860x_hook"
#耳机Hook键子系统。可支持接电话挂电话的耳机上面有一个按键,对应的就是这个input 子系统。
add device 3: /dev/input/event2
name: "88pm860x_on"
#开机键 input 子系统
add device 4: /dev/input/event1
name: "88pm860x-touch"
#Touch Screen input 子系统
add device 5: /dev/input/event0
name: "pxa27x-keypad"
#按键子系统,包括Home/Menu/Back等按键。
可以尝试多种event,实际感觉一下出来的log。
2.阅读getevent的代码。代码为./core/toolbox/getevent.c
从代码中,我们知道,程序在while(1)的一个死循环里,不断地在读取 (select 操作)/dev/input 下面的文件,检查是否Kernel往里面更新内容,如果有内容更新,就把它打印出来。并且从代码中,我们还知道,任何一个event都有三种属性,type,code,value.
while(1) {
pollres = poll(ufds, nfds, -1);
//printf("poll %d, returned %d/n", nfds, pollres);
if(ufds[0].revents & POLLIN) {
read_notify(device_path, ufds[0].fd, print_flags);
}
for(i = 1; i < nfds; i++) {
if(ufds[i].revents) {
if(ufds[i].revents & POLLIN) {
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("%ld-%ld: ", event.time.tv_sec, event.time.tv_usec);
}
if(print_device)
printf("%s: ", device_names[i]);
printf("%04x %04x %08x", event.type, event.code, event.value);
if(sync_rate && event.type == 0 && event.code == 0) {
int_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;
}
}
}
3.问题来了,Android Framework是否也是一样的原理呢??猜测应该是一样的才对,不然这个工具就没有调试的价值了。
我们来阅读和分析framework中input event的相关代码。
我们从Kernel层往上看,先看看Framework中,直接操纵/dev/input设备的代码。
在.frameworks/base/libs/ui/EventHub.cpp 中,我们看到跟getevent工具类似的代码。
bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
int32_t* outValue, nsecs_t* outWhen)
{
....
while(1) {
....
release_wake_lock(WAKE_LOCK_ID);
pollres = poll(mFDs, mFDCount, -1);
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
if (pollres <= 0) {
if (errno != EINTR) {
LOGW("select failed (errno=%d)/n", errno);
usleep(100000);
}
continue;
}
....
// mFDs[0] is used for inotify, so process regular events starting at mFDs[1]
for(i = 1; i < mFDCount; i++) {
if(mFDs[i].revents) {
LOGV("revents for %d = 0x%08x", i, mFDs[i].revents);
if(mFDs[i].revents & POLLIN) {
res = read(mFDs[i].fd, &iev, sizeof(iev));
if (res == sizeof(iev)) {
LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d",
mDevices[i]->path.string(),
....
}