Android 4.0触摸屏消息(writing)
2475 点击·0 回帖
![]() | ![]() | |
![]() | “消息”一词最早出现于《易经》:“日中则昃,月盈则食,天地盈虚,与时消息。“意思是说,太阳到了中午就要逐渐西斜,月亮圆了就逐渐亏缺,天地间的事物,或丰盈或虚弱,都随着时间的推移而变化,有时消减,有时滋长。由此可见,中国古代就把客观世界的变化,把它们的发生、发展和结局,把它们的枯荣、聚散、沉浮、升降、兴衰、动静、得失等等变化中的事实称之为”消息“。----------摘自度娘。 因此,在此处我们所要学习的消息也是有这样的一种产生,发展和结束的过程。而产生就是指当硬件接受到人的触摸的情况之下,通过中断将消息上报,从而我们能够通过上层的线程得到这个消息,而具体是如何处理的都将通过线程内部或者线程间的调用完成,最后通过分发线程将消息分发出去供消费者去消耗。 在深入学习之前我们先要思考如下几个问题: 1 消息是如何让系统得到的? 2 消息是如何被系统读取和处理的? 3 应用程序开发者是如何利用消息的? 1 首先kernel中我们会使用下面的函数来上报事件。(linux/input.h) 设置: 1227 unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; 1228 unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; 1229 unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; 1230 unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; 上报: 1474 static inline void input_report_key(struct input_dev *dev, unsigned int code, int value) 1475 { 1476 input_event(dev, EV_KEY, code, !!value); 1477 } 1478 1479 static inline void input_report_rel(struct input_dev *dev, unsigned int code, int value) 1480 { 1481 input_event(dev, EV_REL, code, value); 1482 } 1483 1484 static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value) 1485 { 1486 input_event(dev, EV_ABS, code, value); 1487 } 其中调用的input_event函数如下: 347 void input_event(struct input_dev *dev, 348 unsigned int type, unsigned int code, int value) 349 { 350 unsigned long flags; 351 352 if (is_event_supported(type, dev->evbit, EV_MAX)) { 353 354 spin_lock_irqsave(;dev->event_lock, flags); 355 add_input_randomness(type, code, value); 356 input_handle_event(dev, type, code, value); 357 spin_unlock_irqrestore(;dev->event_lock, flags); 358 } 359 } 360 EXPORT_SYMBOL(input_event); 此处的input_handle_event()会调用到input_pass_event()函数 77 static void input_pass_event(struct input_dev *dev, 78 unsigned int type, unsigned int code, int value) 79 { 80 struct input_handler *handler; 81 struct input_handle *handle; 82 83 rcu_read_lock(); 84 85 handle = rcu_dereference(dev->grab); 86 if (handle) 87 handle->handler->event(handle, type, code, value); 88 else { 89 bool filtered = false; 90 91 list_for_each_entry_rcu(handle, ;dev->h_list, d_node) { 92 if (!handle->open) 93 continue; 94 95 handler = handle->handler; 96 if (!handler->filter) { 97 if (filtered) 98 break; 99 100 handler->event(handle, type, code, value); 101 102 } else if (handler->filter(handle, type, code, value)) 103 filtered = true; 104 } 105 } 106 107 rcu_read_unlock(); 108 } 上面的handler就是函数evdev_handler()。定义在evdev.c文件中。在evdev_init()中通过调用input_register_handler(;ev_handler)的注册完成了input_dev和evdev_handler的关联。并且调用了evdev_event()函数完成了对evdev_pass_event()将数据存放在buffer中。代码如下: 59 static void evdev_pass_event(struct evdev_client *client, 60 struct input_event *event) 61 { 62 /* interrupts are disabled, just acquire the lock. */ 63 spin_lock(;client->buffer_lock); 64 65 wake_lock_timeout(;client->wake_lock, 5 * HZ); 66 client->buffer[client->head++] = *event; 67 client->head ;= client->bufsize - 1; 68 69 if (unlikely(client->head == client->tail)) { 70 /* 71 * This effectively "drops" all unconsumed events, leaving 72 * EV_SYN/SYN_DROPPED plus the newest event in the queue. 73 */ 74 client->tail = (client->head - 2) ; (client->bufsize - 1); 75 76 client->buffer[client->tail].time = event->time; 77 client->buffer[client->tail].type = EV_SYN; 78 client->buffer[client->tail].code = SYN_DROPPED; 79 client->buffer[client->tail].value = 0; 80 81 client->packet_head = client->tail; 82 } 83 84 if (event->type == EV_SYN ;; event->code == SYN_REPORT) { 85 client->packet_head = client->head; 86 kill_fasync(;client->fasync, SIGIO, POLL_IN); 87 } 88 89 spin_unlock(;client->buffer_lock); 90 } 在底层设备的注册和分配工作也就大体上完成了。此时我们需要考虑如何读取数据的问题了。在kernel部分的读取先暂时不做介绍。 这样我们就能够完成对触摸屏的设置。这些我们在前面的文章中描述过。 2 在frameworks层数据的读取过程 首先我们需要了解最重要的一个环节就是EventHub。它是系统中所有事件的中央处理站。它管理所有系统中可以识别的输入设备的输入事件。另外,当设备增加和删除时,EventHub将产生相应的输入事件给系统。以下是在EventHub.cpp文件中的getEvents函数中打开设备的代码。主要调用了scanDevicesLocked(). 0569 if (mNeedToScanDevices) { 0570 mNeedToScanDevices = false; 0571 scanDevicesLocked(); 0572 mNeedToSendFinishedDeviceScan = true; 0573 } 而scanDevicesLocked()函数的代码如下: static const char *DEVICE_PATH = "/dev/input"; 0801 void EventHub:canDevicesLocked() { 0802 status_t res = scanDirLocked(DEVICE_PATH); 0803 if(res < 0) { 0804 LOGE("scan dir failed for %s\n", DEVICE_PATH); 0805 } 0806 } 接着往下调用: 1270 status_t EventHub:canDirLocked(const char *dirname) 1271 { 1272 char devname[PATH_MAX]; 1273 char *filename; 1274 DIR *dir; 1275 struct dirent *de; 1276 dir = opendir(dirname); 1277 if(dir == NULL) 1278 return -1; 1279 strcpy(devname, dirname); 1280 filename = devname + strlen(devname); 1281 *filename++ = '/'; 1282 while((de = readdir(dir))) { 1283 if(de->d_name[0] == '.' ;; 1284 (de->d_name[1] == '\0' || 1285 (de->d_name[1] == '.' ;; de->d_name[2] == '\0'))) 1286 continue; 1287 strcpy(filename, de->d_name); 1288 openDeviceLocked(devname); 1289 } 1290 closedir(dir); 1291 return 0; 1292} | |
![]() | ![]() |