3. InputReader

在frameworks/base/services/input/InputReader.cpp中InputReader类成员函数loopOnce将调用EventHub类成员函数getEvents。

?
1 2 3 4 5 6 7 8 9 void InputReader::loopOnce() { ... size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); ... if (count) { processEventsLocked(mEventBuffer, count); } ... }

processEventsLocked进一步调用processEventsForDeviceLocked,而processEventsForDeviceLocked调用InputDevice类成员函数process来处理获得的输入事件。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void InputReader::processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count) { ssize_t deviceIndex = mDevices.indexOfKey(deviceId); if (deviceIndex < 0) { LOGW( "Discarding event for unknown deviceId %d." , deviceId); return ; } InputDevice* device = mDevices.valueAt(deviceIndex); if (device->isIgnored()) { //LOGD("Discarding event for ignored deviceId %d.", deviceId); return ; } device->process(rawEvents, count); }
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 void InputDevice::process( const RawEvent* rawEvents, size_t count) { // Process all of the events in order for each mapper. // We cannot simply ask each mapper to process them in bulk because mappers may // have side-effects that must be interleaved. For example, joystick movement events and // gamepad button presses are handled by different mappers but they should be dispatched // in the order received. size_t numMappers = mMappers.size(); for ( const RawEvent* rawEvent = rawEvents; count--; rawEvent++) { if (mDropUntilNextSync) { if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) { mDropUntilNextSync = false ; } } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_DROPPED) { LOGI( "Detected input event buffer overrun for device %s." , mName.string()); mDropUntilNextSync = true ; reset(rawEvent->when); } else { for ( size_t i = 0; i < numMappers; i++) { InputMapper* mapper = mMappers[i]; mapper->process(rawEvent); } } } }

4. InputMapper

从InputReader.h中的定义可知,InputMapper是一个抽象类。事实上,每个InputDevice在创建时(InputReader::createDeviceLocked)都会为此设备增加一个或多个Mapper,每个Mappr会根据设备类别的不同来分配一个相对应的InputMapper继承类对象。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 InputDevice* InputReader::createDeviceLocked(int32_t deviceId, const String8& name, uint32_t classes) { InputDevice* device = new InputDevice(&mContext, deviceId, name, classes); // External devices. if (classes & INPUT_DEVICE_CLASS_EXTERNAL) { device->setExternal( true ); } // Switch-like devices. if (classes & INPUT_DEVICE_CLASS_SWITCH) { device->addMapper( new SwitchInputMapper(device)); } .... if (keyboardSource != 0) { device->addMapper( new KeyboardInputMapper(device, keyboardSource, keyboardType)); } // Cursor-like devices. if (classes & INPUT_DEVICE_CLASS_CURSOR) { device->addMapper( new CursorInputMapper(device)); } // Touchscreens and touchpad devices. if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) { device->addMapper( new MultiTouchInputMapper(device)); } else if (classes & INPUT_DEVICE_CLASS_TOUCH) { device->addMapper( new SingleTouchInputMapper(device)); } // Joystick-like devices. if (classes & INPUT_DEVICE_CLASS_JOYSTICK) { device->addMapper( new JoystickInputMapper(device)); } return device; }

以单点触摸类别设备为例,其Mapper对输入事件的处理为:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void SingleTouchInputMapper::process( const RawEvent* rawEvent) { TouchInputMapper::process(rawEvent); mSingleTouchMotionAccumulator.process(rawEvent); } void TouchInputMapper::process( const RawEvent* rawEvent) { mCursorButtonAccumulator.process(rawEvent); mCursorScrollAccumulator.process(rawEvent); mTouchButtonAccumulator.process(rawEvent); if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) { sync(rawEvent->when); } }

其中,以下语句均是将输入事件信息转存至类成员变量中。

  • mCursorButtonAccumulator.process(rawEvent);
  • mCursorScrollAccumulator.process(rawEvent);
  • mTouchButtonAccumulator.process(rawEvent);
  • mSingleTouchMotionAccumulator.process(rawEvent);

看来输入事件的处理关键在TouchInputMapper::sync。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 void TouchInputMapper::sync(nsecs_t when) { ... if (mDeviceMode == DEVICE_MODE_DISABLED) { // Drop all input if the device is disabled. mCurrentRawPointerData.clear(); mCurrentButtonState = 0; } else { ... // Cook pointer data. This call populates the mCurrentCookedPointerData structure // with cooked pointer data that has the same ids and indices as the raw data. // The following code can use either the raw or cooked data, as needed. cookPointerData(); // Dispatch the touches either directly or by translation through a pointer on screen. if (mDeviceMode == DEVICE_MODE_POINTER) { ... dispatchPointerUsage(when, policyFlags, pointerUsage); } else { ... dispatchHoverExit(when, policyFlags); dispatchTouches(when, policyFlags); dispatchHoverEnterAndMove(when, policyFlags); } ... } ... }

cookPointerData将原始的输入事件(坐标)转变为屏幕坐标,而以dispatch开头的这几个函数最终将输入事件分发出去,下面以dispatchPointerUsage为例加以说明。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage) { if (pointerUsage != mPointerUsage) { abortPointerUsage(when, policyFlags); mPointerUsage = pointerUsage; } switch (mPointerUsage) { case POINTER_USAGE_GESTURES: dispatchPointerGestures(when, policyFlags, false /*isTimeout*/ ); break ; case POINTER_USAGE_STYLUS: dispatchPointerStylus(when, policyFlags); break ; case POINTER_USAGE_MOUSE: dispatchPointerMouse(when, policyFlags); break ; default : break ; } }
?
1 2 3 4 void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) { ... dispatchPointerSimple(when, policyFlags, down, hovering); }
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, bool down, bool hovering) { ... if (mPointerSimple.down && !down) { mPointerSimple.down = false ; // Send up. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); getListener()->notifyMotion(&args); } if (mPointerSimple.hovering && !hovering) { mPointerSimple.hovering = false ; // Send hover exit. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); getListener()->notifyMotion(&args); } if (down) { if (!mPointerSimple.down) { mPointerSimple.down = true ; mPointerSimple.downTime = when; // Send down. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); getListener()->notifyMotion(&args); } // Send move. NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, mPointerSimple.downTime); getListener()->notifyMotion(&args); } ... }

很明显,调用getListener()->notifyMotion来分发事件。下面来跟踪下getListener()返回的具体对象。

?
1 2 3 4 5 6 7 8 9 10 class InputMapper { public : ... inline InputListenerInterface* getListener() { return mContext->getListener(); } ... protected : InputReaderContext* mContext; ... }
?
1 2 3 InputMapper::InputMapper(InputDevice* device) : mDevice(device), mContext(device->getContext()) { }

getListener在InputMapper基类中定义,其返回的对象为mContext->getListener()。由其构造函数可知,InputMapper.mContext即InputDevice.mContext ( InputDevice::getContext函数返回)。InputDevice.mContext在其构造函数中初始化。

?
1 2 3 4 5 InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name, uint32_t classes) : mContext(context), mId(id), mName(name), mClasses(classes), mSources(0), mIsExternal( false ), mDropUntilNextSync( false ) { }

在InputReader::createDeviceLocked函数中,分配InputDevice时传给InputDevice构造函数的context参数为InputReader.mContext的引用。这样,InputMapper::getListener返回的其实为InputReader的ContextImpl类成员变量mContext。

?
1 2 3 InputListenerInterface* InputReader::ContextImpl::getListener() { return mReader->mQueuedListener.get(); }

mQueuedInputListener的定义为: sp<QueuedInputListener> mQueuedListener。这样,在InputMapper::sync中getListener()->notifyMotion的最终调用为:
QueuedInputListener::notifyMotion (InputReader.mQueuedInputListener->notifyMotion )。

QueuedInputListener类在InputListener.h和InputListener.cpp中定义和实现,其notify系列成员函数只是将传入的参数复制一份并存入数组成员变量mArgsQueue中。


更多相关文章

  1. EventBus源码解析(基于Android(安卓)O)
  2. ARM cortex A8/9 - Android(安卓)NDK - NEON介绍以及优化
  3. 耳机插拔
  4. Android(安卓)4.4KitKat AudioFlinger 流程分析
  5. Android(安卓)页面跳转
  6. Android硬件抽象层加调试信息
  7. Android下载文件时对MediaScanner的调用
  8. Android(安卓)OpenGL ES 开发教程(6):GLSurfaceView
  9. MTK Log

随机推荐

  1. Java8 Lambda 表达式和流操作如何让你的
  2. 程序员小猪队友行为大赏
  3. 没用过这些IDEA插件?怪不得写代码头疼
  4. 最近 5 年 133 个 Java 面试问题列表(上)
  5. 看完这篇,别人的开源项目结构应该能看懂了
  6. 做完小程序项目、老板给我加了6k薪资~
  7. Java 8 Lambda 表达式和流操作如何让你的
  8. Java 日志记录的 5 条规则
  9. 该如何以正确的姿势插入SVG Sprites?
  10. 关于 ArrayList 的 5 道面试题