Android 触屏

日期: 2013年09月20日 标签: 硬件

input android层重要模块

fromwork/base/service/input/eventhub.c

它是系统中所有事件的中央处理站。它管理所有系统中可以识别的输入设备的输入事件,此外,当设备增加或删除时,EventHub将产生相应的输入事件给系统。EventHub通过getEvents函数,给系统提供一个输入事件流。它也支持查询输入设备当前的状态(如哪些键当前被按下)。而且EventHub还跟踪每个输入调入的能力,比如输入设备的类别,输入设备支持哪些按键。

fromwork/base/service/input/inputreader.c

InputReader从EventHub中读取原始事件数据(RawEvent),并由各个InputMapper处理之后输入对应的input listener.InputReader拥有一个InputMapper集合。它做的大部分工作在InputReader线程中完成,但是InputReader可以接受任意线程的查询。为了可管理性,InputReader使用一个简单的Mutex来保护它的状态。InputReader拥有一个EventHub对象,但这个对象不是它创建的,而是在创建InputReader时作为参数传入的。

fromwork/base/service/input/inputmanager.c

InputManager使用两个线程:

1)InputReaderThread叫做"InputReader"线程,它负责读取并预处理RawEvent,applies policy并且把消息送入DispatcherThead管理的队列中。

2)InputDispatcherThread叫做"InputDispatcher"线程,它在队列上等待新的输入事件,并且异步地把这些事件分发给应用程序。InputReaderThread类与InputDispatcherThread类不共享内部状态,所有的通信都是单向的,从InputReaderThread到InputDispatcherThread。两个类可以通过InputDispatchPolicy进行交互。InputManager类从不与Java交互,而InputDispatchPolicy负责执行所有与系统的外部交互,包括调用DVM业务。

inputmamager 创建流程

1)在android_server_InputManager_nativeInit中创建NativeInputManager对象,并保存到gNativeInputManager中;

2)在创建NativeInputManager对象时,它会创建EventHub对象<且创建是其成员mNeedToScanDevices的值为true>,然后把刚创建的EventHub对象作为参数创建InputManager对象;

3)在创建InputManager对象时,创建InputReader对象,然后把它作为参数创建InputReaderThread;创建InputDispatcher对象,然后把它作为参数创建InputDispatcherThread对象;(注:以上两个线程对象都有自己的threadLoop函数,它将在Thread::threadLoop中被调用,这个Thread::threadLoop是线程入口函数,线程在Thread::run中被真正地创建)

4.1)创建InputReader对象

4.1.1)把EventHub、readerPolicy<实质为NativeInputManager对象>和创建的InputDispatcher对象作为参数创建InputReader对象:mReader = new InputReader(eventHub, readerPolicy, mDispatcher);

4.1.2)在创建InputReader时, 保存EventHub对象到mEventHub中,并创建QueuedInputListener对象并保存在mQueuedListener中

4.2)创建InputDispatcher对象

4.2.1)把传入的参数dispatcherPolicy<实质为NativeInputManager对象>作为参数创建InputDispatcher对象:mDispatcher = new InputDispatcher(dispatcherPolicy);

4.2.1)在创建InputDispatcher时,创建了一个looper对象:mLooper = new Looper(false);

设备操作流程

事件结构

    struct RawEvent {  
    nsecs_t when;        //事件发生的时间  
    int32_t deviceId;    //产生此事件的设备,比如发送FINISHED_DEVICE_SCAN,不需要填此项  
    int32_t type;        //事件类型(如:DEVICE_ADDED,DEVICE_REMOVED,FINISHED_DEVICE_SCAN)  
    int32_t scanCode;    // 
    int32_t keyCode; 
    int32_t value; 
    uint32_t flags; 
}; 

事件读取流程

Thread::_threadLoop->

   InputReaderThread::threadLoop->

      InputReader::loopOnce->

           EventHub::getEvents->

打开设备

在EventHub::getEvents中,当mNeedToScanDevices为true时<当创建EventHub对象时,它就为true>,它将从/dev/input目录下查找所有设备,并进行打开,获取其相关属性,最后加入mDevices列表中。

EventHub::scanDevicesLocked->

   EventHub::scanDirLocked("/dev/input")->

     EventHub::openDeviceLocked

开打设备事件

打开事件输入设备,在用户态调用open,则在kernel态中调用evdev_open函数,evdev_open处理流程如下:

1)首先从参数inode中获取在evdev_table中的索引,从而获取对应的evdev对象

2)创建evdev_client对象,创建此对象时同时为其buffer成员分配对应的内存

3)把新创建evdev_client对象添加到client_list链表中

4)把client保存在file的private_data中

5)调用evdev_open_device->input_open_device->input_dev.open函数打开设备。

inputreader读取事件

Thread::_threadLoop->

 InputReaderThread::threadLoop->

      InputReader::loopOnce->

           EventHub::getEvents->

在InputReader::loopOnce中,当调用EventHub->getEvents获取到RawEvent之后, 调用InputReader::processEventsLocked来处理这些事件,然后调用 mQueuedListener->flush()把这些队列中的事件发送到Listener。

processEventsLocked

在InputReader::processEventsLocked主要分两步处理:

1)处理来自于事件驱动设备的事件(processEventsForDeviceLocked)

2)处理设备增加、删除和修改事件

按照程序执行流程,应该是先有设备,然后才会有设备事件,所以先分析设备增加。 其代码如下:

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {
    int32_t type = rawEvent->type;
    size_t batchSize = 1;
    if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
        int32_t deviceId = rawEvent->deviceId;
        while (batchSize < count) {
            if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
                    || rawEvent[batchSize].deviceId != deviceId) {
                break;
            }
            batchSize += 1;
        }
#if DEBUG_RAW_EVENTS
        ALOGD("BatchSize: %d Count: %d", batchSize, count);
 #endif
        processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
    } else {
        switch (rawEvent->type) {
        case EventHubInterface::DEVICE_ADDED:
            addDeviceLocked(rawEvent->when, rawEvent->deviceId);
            break;
        case EventHubInterface::DEVICE_REMOVED:
            removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
            break;
        case EventHubInterface::FINISHED_DEVICE_SCAN:
            handleConfigurationChangedLocked(rawEvent->when);
            break;
        default:
            ALOG_ASSERT(false); // can't happen
            break;
        }
    }
    count -= batchSize;
    rawEvent += batchSize;
}
}

未完待续

http://www.blogjava.net/MEYE/articles/367928.html http://blog.csdn.net/myarrow/article/details/7254651


<-->