Android(安卓)输入系统解析 (2)
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中。
更多相关文章
- EventBus源码解析(基于Android(安卓)O)
- ARM cortex A8/9 - Android(安卓)NDK - NEON介绍以及优化
- 耳机插拔
- Android(安卓)4.4KitKat AudioFlinger 流程分析
- Android(安卓)页面跳转
- Android硬件抽象层加调试信息
- Android下载文件时对MediaScanner的调用
- Android(安卓)OpenGL ES 开发教程(6):GLSurfaceView
- MTK Log