Android 4.0 触摸屏消息(一大写的一)

26 篇文章 0 订阅
5 篇文章 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部分的读取先暂时不做介绍。

      这样我们就能够完成对触摸屏的设置。这些我们在前面的文章中描述过。http://blog.csdn.net/codectq/article/details/7478936

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 }

      这时需要底层的文件系统将设备打开并且读取设备中的数据。但是读取的数据并不能够被上层的应用程序直接使用而是需要经过cook处理。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值