上编分析了InputReader线程和InputDispatcher线程启动过程后,InputReader和InputDispatcher线程可以运行起来了,那么InputReader和InputDispatcher线程是如何工作?首先分析InputReader线程。

InputReader线程启动后,是从InputReader的loopOnce函数开始

void InputReader::loopOnce() {  size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);  processEventsLocked(mEventBuffer, count);  mQueuedListener->flush();}

把loopOnce分3大块来分析,已在代码中注明

size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

调用EventHub.cpp中的

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {    for (;;) {        if (mNeedToReopenDevices) {            mNeedToReopenDevices = false;            closeAllDevicesLocked();            mNeedToScanDevices = true;            break;         }    if (mNeedToScanDevices) {          mNeedToScanDevices=true        mNeedToScanDevices = false;        scanDevicesLocked();              mNeedToSendFinishedDeviceScan = true;    }  while (mPendingEventIndex < mPendingEventCount) {       const struct epoll_event& eventItem =          mPendingEventItems[mPendingEventIndex++];      if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {            if (eventItem.events & EPOLLIN) {              mPendingINotify = true;           }          continue;      }      if (eventItem.data.u32 == EPOLL_ID_WAKE) {          if (eventItem.events & EPOLLIN) {              ALOGV("awoken after wake()");              awoken = true;      }      ssize_t deviceIndex =    mDevices.indexOfKey(eventItem.data.u32);      Device* device = mDevices.valueAt(deviceIndex);      if (eventItem.events & EPOLLIN) {           int32_t readSize = read(device->fd, readBuffer,                  sizeof(struct input_event) * capacity);              int32_t deviceId = device->id ==   mBuiltInKeyboardId ? 0 : device->id;       }                     int  pollResult=epoll_wait(mEpollFd,mPendingEventItems,EPOLL_MAX_EVENTS, timeoutMillis);    return event - buffer;    }

进入 for (;;)后,首先调用 scanDevicesLocked(); 是调用EventHub.cpp中的scanDevicesLocked:

void EventHub::scanDevicesLocked() {    status_t res = scanDirLocked(DEVICE_PATH);}

scanDevicesLocked函数中调用了EventHub.java中的scanDirLocked

status_t EventHub::scanDirLocked(const char *dirname){    dir = opendir(dirname);    while((de = readdir(dir))) {        openDeviceLocked(devname);    }    closedir(dir);    return 0;}

opendir打开/dev/input目录,用while((de = readdir(dir)))一一读出/dev/input目录下设备节点,然后调用EventHub.cpp中的openDeviceLocked

status_t EventHub::openDeviceLocked{    int fd = open(devicePath, O_RDWR | O_CLOEXEC);    if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1)     // Get device driver version.    if(ioctl(fd, EVIOCGVERSION, &driverVersion))     // Get device identifier.    if(ioctl(fd, EVIOCGID, &inputId))     identifier.bus       = inputId.bustype;    identifier.product = inputId.product;    identifier.vendor  = inputId.vendor;    identifier.version  = inputId.version;    int32_t deviceId = mNextDeviceId++;    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);    loadConfigurationLocked(device); //idc    // Figure out the kinds of events the device reports.    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);    bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC))            || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),                    sizeof_bit_array(KEY_MAX + 1));    bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),                    sizeof_bit_array(BTN_MOUSE))            || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),                    sizeof_bit_array(BTN_DIGI));    if (haveKeyboardKeys || haveGamepadButtons) {        device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;    }    // Check whether this device supports the vibrator.    if (test_bit(FF_RUMBLE, device->ffBitmask)) {        device->classes |= INPUT_DEVICE_CLASS_VIBRATOR;    }    status_t keyMapStatus = NAME_NOT_FOUND;    if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {        // Load the keymap for the device.        keyMapStatus = loadKeyMapLocked(device); //key    }     // Register with epoll.    struct epoll_event eventItem;    memset(&eventItem, 0, sizeof(eventItem));    eventItem.events = mUsingEpollWakeup ? EPOLLIN : EPOLLIN | EPOLLWAKEUP;    eventItem.data.u32 = deviceId;    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {        ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);        delete device;        return -1;    }    addDeviceLocked(device);    return 0;}

open打开/dev/input/目录下XX个节点,读取出这个设备的有用信息。比如设备版本号多少,是什么总线,产口id等等信息。然后创建一个new Device();存放fd, deviceId, devicePath, identifier信息。接下来就是调用 loadConfigurationLocked(device); //idc函数,如果是触摸屏,根据Input Driver中的名字找到相应的名字的idc文件,如果不是触摸屏,此函数没有什么作用。然后检查是哪一类设备,进行相应的设置。比如按键keyMapStatus = loadKeyMapLocked(device);完成相应的设备初始化后,调用epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)加入了epoll中,进行数据监听。最后调用addDeviceLocked(device);函数。接下来分析addDeviceLocked函数,即是调用EventHub.cpp中的addDeviceLocked函数:

void EventHub::addDeviceLocked(Device* device) {    mDevices.add(device->id, device);    device->next = mOpeningDevices;    mOpeningDevices = device;}

把Device加入mDevices中。经过分析,清楚了scanDevicesLocked就是打开/dev/input/*下所有设备,读出相关的信息,创建一个Device存放相关信息,并检查类型设置,然后把所有设备节点的描述符加入epoll中,最后把Device加入mDevices中。
回到getEvents中scanDevicesLocked跑完后epoll_wait监听设备节点的数据,读到数据后进入while (mPendingEventIndex < mPendingEventCount) 中,然后从const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];中一一取出数据进行判断,从 Device* device = mDevices.valueAt(deviceIndex);中取出一个Device,然后把 int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;存在RawEvent中的deviceId中。
完成后返回到loopOnce中,接下来就是loopOnce中
processEventsLocked函数调用了InputReader.cpp中processEventsLocked

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count){    for (const RawEvent* rawEvent = rawEvents; count;) {            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;            }        }}

如果 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) 不是输入事件,执行switch (rawEvent->type) ,很清楚知道是关于设备添加、删除等操作。重点就是if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) 中processEventsForDeviceLocked函数,调用InputReader.cpp中processEventsForDeviceLocked

void InputReader::processEventsForDeviceLocked(int32_t deviceId,        const RawEvent* rawEvents, size_t count) {    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);    InputDevice* device = mDevices.valueAt(deviceIndex);        return;    }    device->process(rawEvents, count);}

根据deviceId从mDevices中打出InputDevice,然后调用InputDevice中process。这个InputDevice中process是哪一个?上面分析scanDevicesLocked中知道,相应类中就的有相对应的keyMap,比如是按键类,那么是调用了InputReader.cpp中的KeyboardInputMapper::process

void KeyboardInputMapper::process(const RawEvent* rawEvent) {    switch (rawEvent->type) {    case EV_KEY: {            processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);    }  }

调用了InputReader.cpp中KeyboardInputMapper::processKey

void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);    getListener()->notifyKey(&args);}

把keyCode、keyCode等的数据把包成一个args,最后调用getListener()->notifyKey(&args);
getListener()->notifyKey(&args);根据前面分析《 Android 5.0输入系统分析之InputReader和InputDispatcher线程启动过程》的mReader = new InputReader(eventHub, readerPolicy, mDispatcher);其别就是InputDispatcher。所以是调用了notifyKey:

void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {    mArgsQueue.push(new NotifyKeyArgs(*args));}

创建一个NotifyKeyArgs加入mArgsQueue中。然后回到了loopOnce函数,最后调用了
mQueuedListener->flush();,那么就是调用flush

void QueuedInputListener::flush() {     size_t count = mArgsQueue.size();    for (size_t i = 0; i < count; i++) {        NotifyArgs* args = mArgsQueue[i];        args->notify(mInnerListener);        delete args;    }    mArgsQueue.clear();}

从mArgsQueue取出NotifyArgs,然后调用了NotifyArgs中的notify。就是

void NotifyKeyArgs::notify(const sp& listener) const {    listener->notifyKey(this);}

然后调用了InputDispatcher.cpp中的notifyKey

void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {    KeyEvent event;    event.initialize(args->deviceId, args->source, args->action,            flags, keyCode, args->scanCode, metaState, 0,            args->downTime, args->eventTime);    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);     int32_t repeatCount = 0;     KeyEntry* newEntry = new KeyEntry(args->eventTime,             args->deviceId, args->source, policyFlags,             args->action, flags, keyCode, args->scanCode,             metaState, repeatCount, args->downTime);     needWake = enqueueInboundEventLocked(newEntry);     if (needWake) {        mLooper->wake();    }}

把数据 封成一个KeyEvent,调用了mPolicy->interceptKeyBeforeQueueing(&event, /byref/ policyFlags); 那么mPolicy又是谁?在notifyKey()函数中会新建一个KeyEvent对象并进行初始化,然后调用mPolicy的interceptKeyBeforeQueueing(mPolicy就是NativeInputManagers)

void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,        uint32_t& policyFlags) {            wmActions = env->CallIntMethod(mServiceObj,                   gServiceClassInfo.interceptKeyBeforeQueueing,                    keyEventObj, policyFlags);         handleInterceptActions(wmActions, when, /*byref*/ policyFlags); }调用了PhoneWindowManager.java中的interceptKeyBeforeQueueing函数对KEYCODE_VOLUME_DOWN:KeyEvent.KEYCODE_VOLUME_UP:KeyEvent.KEYCODE_VOLUME_MUTE等系统按键处理,然后调handleInterceptActions函数void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,        uint32_t& policyFlags) {    if (wmActions & WM_ACTION_PASS_TO_USER) {        policyFlags |= POLICY_FLAG_PASS_TO_USER;    } }

把policyFlags |= POLICY_FLAG_PASS_TO_USER;代表传给用户的。
回到notifyKey中,创建一个KeyEntry,把NotifyKeyArgs的数据初始化了KeyEntry。然后把KeyEntry放入到enqueueInboundEventLocked中。

bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {        mInboundQueue.enqueueAtTail(entry);}

把KeyEntry放入mInboundQueue队例头。数据放好后,mLooper->wake();唤醒InputDispatcher线程。InputReader线程到此分析完。

更多相关文章

  1. Android(安卓)RemoteCallbackList类
  2. android如何完全退出应用程序
  3. Android培训班(68)dex文件打开流程
  4. Android两种相机的调用方式
  5. Unity3d与Android的相互调用
  6. 关于android WebViewClient 的方法解释
  7. android 事件传递机制
  8. Android进程通信-AIDL
  9. android 解锁,锁屏流程

随机推荐

  1. Android HttpURLConnection Accept-Encod
  2. Android 获取网络图片方法
  3. android 字符串转换成JSON对象
  4. Android开发:文本实现两端对齐
  5. ANDROID开发,如何更改android的project ta
  6. 在TextView上显示图片信息
  7. android 自定义返回按钮
  8. Android - Toast自定义显示时间,以及时长
  9. Android /system/build.prop 文件
  10. android surfaceView控制视频显示大小