展会信息港展会大全

Android 4.0触摸屏消息(writing)
来源:互联网   发布日期:2015-09-29 10:39:01   浏览:2069次  

导读: “消息”一词最早出现于《易经》:“日中则昃,月盈则食,天地盈虚,与时消息。“意思是说,太阳到了中午就要逐渐西斜,月亮圆了就逐渐亏缺,天地间的事物,或丰盈或虚弱,都随着时间的推移而变化,有时...

“消息”一词最早出现于《易经》:“日中则昃,月盈则食,天地盈虚,与时消息。“意思是说,太阳到了中午就要逐渐西斜,月亮圆了就逐渐亏缺,天地间的事物,或丰盈或虚弱,都随着时间的推移而变化,有时消减,有时滋长。由此可见,中国古代就把客观世界的变化,把它们的发生、发展和结局,把它们的枯荣、聚散、沉涪升降、兴衰、动静、得失等等变化中的事实称之为”消息“。----------摘自度娘。

因此,在此处我们所要学习的消息也是有这样的一种产生,发展和结束的过程。而产生就是指当硬件接受到人的触摸的情况之下,通过中断将消息上报,从而我们能够通过上层的线程得到这个消息,而具体是如何处理的都将通过线程内部或者线程间的调用完成,最后通过分发线程将消息分发出去供消费者去消耗。

在深入学习之前我们先要思考如下几个问题:

1 消息是如何让系统得到的?

2 消息是如何被系统读取和处理的?

3 应用程序开发者是如何利用消息的?

1首先kernel中我们会使用下面的函数来上报事件。(linux/input.h)

设置:

1227unsigned long evbit[BITS_TO_LONGS(EV_CNT)];

1228unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];

1229unsigned long relbit[BITS_TO_LONGS(REL_CNT)];

1230unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];

上报:

1474 static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)

1475 {

1476input_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 {

1481input_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 {

1486input_event(dev, EV_ABS, code, value);

1487 }

其中调用的input_event函数如下:

347 void input_event(struct input_dev *dev,

348unsigned int type, unsigned int code, int value)

349 {

350unsigned long flags;

351

352if (is_event_supported(type, dev->evbit, EV_MAX)) {

353

354spin_lock_irqsave(&dev->event_lock, flags);

355add_input_randomness(type, code, value);

356input_handle_event(dev, type, code, value);

357spin_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,

78unsigned int type, unsigned int code, int value)

79 {

80struct input_handler *handler;

81struct input_handle *handle;

82

83rcu_read_lock();

84

85handle = rcu_dereference(dev->grab);

86if (handle)

87handle->handler->event(handle, type, code, value);

88else {

89bool filtered = false;

90

91list_for_each_entry_rcu(handle, &dev->h_list, d_node) {

92if (!handle->open)

93continue;

94

95handler = handle->handler;

96if (!handler->filter) {

97if (filtered)

98break;

99

100handler->event(handle, type, code, value);

101

102} else if (handler->filter(handle, type, code, value))

103filtered = true;

104}

105}

106

107rcu_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,

60struct input_event *event)

61 {

62/* Interrupts are disabled, just acquire the lock. */

63spin_lock(&client->buffer_lock);

64

65wake_lock_timeout(&client->wake_lock, 5 * HZ);

66client->buffer[client->head++] = *event;

67client->head &= client->bufsize - 1;

68

69if (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*/

74client->tail = (client->head - 2) & (client->bufsize - 1);

75

76client->buffer[client->tail].time = event->time;

77client->buffer[client->tail].type = EV_SYN;

78client->buffer[client->tail].code = SYN_DROPPED;

79client->buffer[client->tail].value = 0;

80

81client->packet_head = client->tail;

82}

83

84if (event->type == EV_SYN && event->code == SYN_REPORT) {

85client->packet_head = client->head;

86kill_fasync(&client->fasync, SIGIO, POLL_IN);

87}

88

89spin_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::scanDevicesLocked() {

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::scanDirLocked(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

}

摘自 曹太强的专栏

赞助本站

人工智能实验室

相关热词: android开发 教程

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港