input事件的处理

来源:互联网 发布:小财神软件 编辑:程序博客网 时间:2024/05/23 11:26

转自http://blog.csdn.net/coldsnow33/article/details/17054985

接InputReader::loopOnce()的
if (count) {
processEventsLocked(mEventBuffer, count);
}

input事件获取到就该处理了。

一 type >= EventHubInterface::FIRST_SYNTHETIC_EVENT的情况

DEVICE_ADDED和DEVICE_REMOVED已经说了,还有FINISHED_DEVICE_SCAN没说;它就是个尾巴,只有要add和remove就必须接上尾巴。这尾巴干什么的呢?
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. case EventHubInterface::FINISHED_DEVICE_SCAN:  
  2.     handleConfigurationChangedLocked(rawEvent->when);  
  3.     break;  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void InputReader::handleConfigurationChangedLocked(nsecs_t when) {  
  2.     // Reset global meta state because it depends on the list of all configured devices.  
  3.     updateGlobalMetaStateLocked();  
  4.   
  5.     // Enqueue configuration changed.  
  6.     NotifyConfigurationChangedArgs args(when);  
  7.     mQueuedListener->notifyConfigurationChanged(&args);  
  8. }  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void InputReader::updateGlobalMetaStateLocked() {  
  2.     mGlobalMetaState = 0;  
  3.   
  4.     for (size_t i = 0; i < mDevices.size(); i++) {  
  5.         InputDevice* device = mDevices.valueAt(i);  
  6.         mGlobalMetaState |= device->getMetaState();  
  7.     }  
  8. }  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. int32_t InputDevice::getMetaState() {  
  2.     int32_t result = 0;  
  3.     size_t numMappers = mMappers.size();  
  4.     for (size_t i = 0; i < numMappers; i++) {  
  5.         InputMapper* mapper = mMappers[i];  
  6.         result |= mapper->getMetaState();  
  7.     }  
  8.     return result;  
  9. }  
mMappers[]是什么?
这要从DEVICE_ADDED说起,
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. case EventHubInterface::DEVICE_ADDED:  
  2.     addDeviceLocked(rawEvent->when, rawEvent->deviceId);  
  3.     break;  
InputReader::addDeviceLocked()->createDeviceLocked()
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. InputDevice* InputReader::createDeviceLocked(int32_t deviceId,  
  2.         const InputDeviceIdentifier& identifier, uint32_t classes) {  
  3.     InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),  
  4.             identifier, classes);  
  5.   
  6.     // External devices.  
  7.     if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {  
  8.         device->setExternal(true);  
  9.     }  
  10.   
  11.     // Switch-like devices.  
  12.     if (classes & INPUT_DEVICE_CLASS_SWITCH) {  
  13.         device->addMapper(new SwitchInputMapper(device));  
  14.     }  
  15.   
  16.     // Vibrator-like devices.  
  17.     if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {  
  18.         device->addMapper(new VibratorInputMapper(device));  
  19.     }  
  20.   
  21.     // Keyboard-like devices.  
  22.     uint32_t keyboardSource = 0;  
  23.     int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;  
  24.     if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {  
  25.         keyboardSource |= AINPUT_SOURCE_KEYBOARD;  
  26.     }  
  27.     if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {  
  28.         keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;  
  29.     }  
  30.     if (classes & INPUT_DEVICE_CLASS_DPAD) {  
  31.         keyboardSource |= AINPUT_SOURCE_DPAD;  
  32.     }  
  33.     if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {  
  34.         keyboardSource |= AINPUT_SOURCE_GAMEPAD;  
  35.     }  
  36.   
  37.     if (keyboardSource != 0) {  
  38.         device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));  
  39.     }  
  40.   
  41.     // Cursor-like devices.  
  42.     if (classes & INPUT_DEVICE_CLASS_CURSOR) {  
  43.         device->addMapper(new CursorInputMapper(device));  
  44.     }  
  45.   
  46.     // Touchscreens and touchpad devices.  
  47.     if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {  
  48.         device->addMapper(new MultiTouchInputMapper(device));  
  49.     } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {  
  50.         device->addMapper(new SingleTouchInputMapper(device));  
  51.     }  
  52.   
  53.     // Joystick-like devices.  
  54.     if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {  
  55.         device->addMapper(new JoystickInputMapper(device));  
  56.     }  
  57.   
  58.     return device;  
  59. }  
很明显是根据input device->classes来添加映射的。mMappers是一个<InputMapper*>类型的Vector,如果是INPUT_DEVICE_CLASS_SWITCH开关就添加一个device->addMapper(new SwitchInputMapper(device));如果是触摸屏或者触摸板:
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. // Touchscreens and touchpad devices.  
  2. if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {  
  3.     device->addMapper(new MultiTouchInputMapper(device));  
  4. else if (classes & INPUT_DEVICE_CLASS_TOUCH) {  
  5.     device->addMapper(new SingleTouchInputMapper(device));  
每种InputMapper都有自己的init、reset、process函数。addDeviceLocked()之前我们用的device都是通用Device对象,通过createDeviceLocked()实现了Device到InputDevice的转变。看最后有个mDevices.add(deviceId, device)。好熟悉啊,openDeviceLocked()->addDeviceLocked(device)里也有mDevices.add(device->id, device),长得真像,这个是add通用Device,class EventHub的 mDevices是这个摸样的:
KeyedVector<int32_t, Device*> mDevices;
现在是在class InputReader家里了,mDevices变样了:
KeyedVector<int32_t, InputDevice*> mDevices;
Device对象是在 EventHub::openDeviceLocked()里new出,在EventHub::getEvents()、EventHub::openDeviceLocked()和EventHub::closeDeviceLocked() close device的时候delete。
InputDevice在InputReader::addDeviceLocked()里new出,在removeDeviceLocked()里delete。
回到InputDevice::getMetaState(),先假设classes & INPUT_DEVICE_CLASS_TOUCH_MT,其他情况那么多,不care它们。那么这个InputMapper就是MultiTouchInputMapper,它没有实现getMetaState()函数,那找它爸爸class TouchInputMapper,也没有,那只能找它爷爷了class InputMapper。
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. int32_t InputMapper::getMetaState() {  
  2.     return 0;  
  3. }  
看来对于 INPUT_DEVICE_CLASS_TOUCH_MT,mGlobalMetaState一直为0。mMetaState是指什么状态?只有KeyboardInputMapper设置getMetaState()函数。
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. int32_t KeyboardInputMapper::getMetaState() {  
  2.     return mMetaState;  
  3. }  
mMetaState是meta key的一些状态,如果此时是keyboard的话mGlobalMetaState就可能记录了一些按键的dow和up。
handleConfigurationChangedLocked()中还有一段:
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1.     // Enqueue configuration changed.  
  2.     NotifyConfigurationChangedArgs args(when);  
  3.   mQueuedListener->notifyConfigurationChanged(&args);  
  4. mQueuedListener是一个class QueuedInputListener的强指针。  
  5. void QueuedInputListener::notifyConfigurationChanged(  
  6.         const NotifyConfigurationChangedArgs* args) {  
  7.     mArgsQueue.push(new NotifyConfigurationChangedArgs(*args));  
  8. }  
mArgsQueue是class QueuedInputListener中的一个Vector。这样一push就把NotifyConfigurationChangedArgs类型的实例push到Vector mArgsQueue中。这种push就是在Vector 中创建一个NotifyConfigurationChangedArgs对象的副本;这样就实现了将NotifyConfigurationChangedArgs事件推送到InputReader的队列中等候处理。其实是push到InputDispatch中,为什么这样说呢?再看下:
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. InputManager::InputManager(  
  2.         const sp<EventHubInterface>& eventHub,  
  3.         const sp<InputReaderPolicyInterface>& readerPolicy,  
  4.         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {  
  5.     mDispatcher = new InputDispatcher(dispatcherPolicy);  
  6.     mReader = new InputReader(eventHub, readerPolicy, mDispatcher);  
  7.     initialize();  
  8. }  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. InputReader::InputReader(const sp<EventHubInterface>& eventHub,  
  2.         const sp<InputReaderPolicyInterface>& policy,  
  3.         const sp<InputListenerInterface>& listener) :  
  4.         mContext(this), mEventHub(eventHub), mPolicy(policy),  
  5.         mGlobalMetaState(0), mGeneration(1),  
  6.         mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),  
  7.         mConfigurationChangesToRefresh(0) {  
  8.     mQueuedListener = new QueuedInputListener(listener);  
  9.   
  10.     { // acquire lock  
  11.         AutoMutex _l(mLock);  
  12.   
  13.         refreshConfigurationLocked(0);  
  14.         updateGlobalMetaStateLocked();  
  15.     } // release lock  
  16. }  
InputReader的mQueuedListener就是用mDispatcher构建的,这就是InputReader和InputDispatch通信的方式,现在又event了,就要通知InputDispatch。

二 type < EventHubInterface::FIRST_SYNTHETIC_EVENT的情况

先找出对同一个deviceId可处理数据的长度batchSize,然后调用:
processEventsForDeviceLocked(deviceId, rawEvent, batchSize)->(device->process(rawEvents, count))
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void InputDevice::process(const RawEvent* rawEvents, size_t count) {  
  2.     // Process all of the events in order for each mapper.  
  3.     // We cannot simply ask each mapper to process them in bulk because mappers may  
  4.     // have side-effects that must be interleaved.  For example, joystick movement events and  
  5.     // gamepad button presses are handled by different mappers but they should be dispatched  
  6.     // in the order received.  
  7.     size_t numMappers = mMappers.size();  
  8.     for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {  
  9. #if DEBUG_RAW_EVENTS  
  10.         ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld",  
  11.                 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,  
  12.                 rawEvent->when);  
  13. #endif  
  14.   
  15.         if (mDropUntilNextSync) {  
  16.             if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {  
  17.                 mDropUntilNextSync = false;  
  18. #if DEBUG_RAW_EVENTS  
  19.                 ALOGD("Recovered from input event buffer overrun.");  
  20. #endif  
  21.             } else {  
  22. #if DEBUG_RAW_EVENTS  
  23.                 ALOGD("Dropped input event while waiting for next input sync.");  
  24. #endif  
  25.             }  
  26.         } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {  
  27.             ALOGI("Detected input event buffer overrun for device %s.", getName().string());  
  28.             mDropUntilNextSync = true;  
  29.             reset(rawEvent->when);  
  30.         } else {  
  31.             for (size_t i = 0; i < numMappers; i++) {  
  32.                 InputMapper* mapper = mMappers[i];  
  33.                 mapper->process(rawEvent);  
  34.             }  
  35.         }  
  36.     }  
  37. }  
for循环依次处理count个rawEvents。
(1) mDropUntilNextSync到下一次同步前的都扔掉,收到rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED时,该标记会置位,貌似底层client的循环buffer出现问题的时候会发送这个code。如果收到此code,要一直等到下一次的rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT,才能解放出来呢。InputDevice构造时,该标记是false。
(2) 刚说的rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED时,mDropUntilNextSync = true,同时执行reset(rawEvent->when)。
(3) 一般会一直走到最后一个else。
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. else {  
  2.     for (size_t i = 0; i < numMappers; i++) {  
  3.         InputMapper* mapper = mMappers[i];  
  4.         mapper->process(rawEvent);  
  5.     }  
  6. }  
假设过我们的mapper多点上报的触摸屏,所以mapper是MultiTouchInputMapper。

三 configure()函数

说process流程之前,先看看configure()函数,如何获取事件编码code,如何判断type A,还是type B。
需要刷新配置时,执行
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void InputReader::requestRefreshConfiguration(uint32_t changes) {  
  2.     AutoMutex _l(mLock);  
  3.   
  4.     if (changes) {  
  5.         bool needWake = !mConfigurationChangesToRefresh;  
  6.         mConfigurationChangesToRefresh |= changes;  
  7.   
  8.         if (needWake) {  
  9.             mEventHub->wake();  
  10.         }  
  11.     }  
  12. }  
InputReader::loopOnce()一开始
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. if (changes) {  
  2.        mConfigurationChangesToRefresh = 0;  
  3.        timeoutMillis = 0;  
  4.        refreshConfigurationLocked(changes);  
  5.    }   
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void InputReader::refreshConfigurationLocked(uint32_t changes) {  
  2.     mPolicy->getReaderConfiguration(&mConfig);  
  3.     mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);  
  4.   
  5.     if (changes) {  
  6.         ALOGI("Reconfiguring input devices.  changes=0x%08x", changes);  
  7.         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  8.   
  9.         if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {  
  10.             mEventHub->requestReopenDevices();  
  11.         } else {  
  12.             for (size_t i = 0; i < mDevices.size(); i++) {  
  13.                 InputDevice* device = mDevices.valueAt(i);  
  14.                 device->configure(now, &mConfig, changes);  
  15.             }  
  16.         }  
  17.     }  
  18. }  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {  
  2.     mSources = 0;  
  3.   
  4.     if (!isIgnored()) {  
  5.         if (!changes) { // first time only  
  6.             mContext->getEventHub()->getConfiguration(mId, &mConfiguration);  
  7.         }  
  8.   
  9.         if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {  
  10.             if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {  
  11.                 sp<KeyCharacterMap> keyboardLayout =  
  12.                         mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier.descriptor);  
  13.                 if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {  
  14.                     bumpGeneration();  
  15.                 }  
  16.             }  
  17.         }  
  18.   
  19.         if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {  
  20.             if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {  
  21.                 String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);  
  22.                 if (mAlias != alias) {  
  23.                     mAlias = alias;  
  24.                     bumpGeneration();  
  25.                 }  
  26.             }  
  27.         }  
  28.   
  29.         size_t numMappers = mMappers.size();  
  30.         for (size_t i = 0; i < numMappers; i++) {  
  31.             InputMapper* mapper = mMappers[i];  
  32.             mapper->configure(when, config, changes);  
  33.             mSources |= mapper->getSources();  
  34.         }  
  35.     }  
  36. }  
MultiTouchInputMapper没有实现config()函数,继承了爸爸的。
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void TouchInputMapper::configure(nsecs_t when,  
  2.         const InputReaderConfiguration* config, uint32_t changes) {  
  3.     InputMapper::configure(when, config, changes);  
  4.   
  5.     mConfig = *config;  
  6.   
  7.     if (!changes) { // first time only  
  8.         // Configure basic parameters.  
  9.         configureParameters();  
  10.   
  11.         // Configure common accumulators.  
  12.         mCursorScrollAccumulator.configure(getDevice());  
  13.         mTouchButtonAccumulator.configure(getDevice());  
  14.   
  15.         // Configure absolute axis information.  
  16.         configureRawPointerAxes();  
  17.   
  18.         // Prepare input device calibration.  
  19.         parseCalibration();  
  20.         resolveCalibration();  
  21.     }  
  22.   
  23.     if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {  
  24.         // Update pointer speed.  
  25.         mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);  
  26.         mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);  
  27.         mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);  
  28.     }  
  29.   
  30.     bool resetNeeded = false;  
  31.     if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO  
  32.             | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT  
  33.             | InputReaderConfiguration::CHANGE_SHOW_TOUCHES))) {  
  34.         // Configure device sources, surface dimensions, orientation and  
  35.         // scaling factors.  
  36.         configureSurface(when, &resetNeeded);  
  37.     }  
  38.   
  39.     if (changes && resetNeeded) {  
  40.         // Send reset, unless this is the first time the device has been configured,  
  41.         // in which case the reader will call reset itself after all mappers are ready.  
  42.         getDevice()->notifyReset(when);  
  43.     }  
  44. }  
configureParameters()获取不可变的配置参数。
mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN的条件为:
(1) if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)),要set INPUT_PROP_DIRECT。
(2) if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
deviceTypeString)) {
if (deviceTypeString == "touchScreen")
这是idc文件的配置。
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void MultiTouchInputMapper::configureRawPointerAxes() {  
  2.     TouchInputMapper::configureRawPointerAxes();  
  3.   
  4.     getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);  
  5.     getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);  
  6.     getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);  
  7.     getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);  
  8.     getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);  
  9.     getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);  
  10.     getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);  
  11.     getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);  
  12.     getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);  
  13.     getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);  
  14.     getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);  
  15.   
  16.     if (mRawPointerAxes.trackingId.valid  
  17.             && mRawPointerAxes.slot.valid  
  18.             && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {  
  19.         size_t slotCount = mRawPointerAxes.slot.maxValue + 1;  
  20.         if (slotCount > MAX_SLOTS) {  
  21.             ALOGW("MultiTouch Device %s reported %d slots but the framework "  
  22.                     "only supports a maximum of %d slots at this time.",  
  23.                     getDeviceName().string(), slotCount, MAX_SLOTS);  
  24.             slotCount = MAX_SLOTS;  
  25.         }  
  26.         mMultiTouchMotionAccumulator.configure(getDevice(),  
  27.                 slotCount, true /*usingSlotsProtocol*/);  
  28.     } else {  
  29.         mMultiTouchMotionAccumulator.configure(getDevice(),  
  30.                 MAX_POINTERS, false /*usingSlotsProtocol*/);  
  31.     }  
  32. }  
前面一堆,设置一下code事件编码是哪些。
(1) 如果上报ID和slot,就是B类协议上报(B类协议是一定要上报ID的,那些不上报ID,也用input_mt_slot()是怎么回事?这怎么可能?B类是一定report ID的,input_mt_slot()会设置ABS_MT_TRACKING_ID的code),slotCount的值要限制在MAX_SLOTS(32)以内。接着调用:
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void MultiTouchMotionAccumulator::configure(InputDevice* device,  
  2.         size_t slotCount, bool usingSlotsProtocol) {  
  3.     mSlotCount = slotCount;  
  4.     mUsingSlotsProtocol = usingSlotsProtocol;  
  5.     mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);  
  6.   
  7.     delete[] mSlots;  
  8.     mSlots = new Slot[slotCount];  
  9. }  
mSlots是用来保存一个mt sync(SYN_MT_REPORT)或者mt slot(ABS_MT_SLOT)事件,对应一个点。mSlotCount说明一次最多能保存多少mt sync事件。对于type B mSlotCount最大值是32, mUsingSlotsProtocol = true。
(2) 对于type A,mSlotCount最大值是16,就是16个点,mUsingSlotsProtocol = false。
configureSurface(when, &resetNeeded)来确定device mode。
(1) 根据mParameters.deviceType确定mSource和mDeviceMode。
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN  
  2.             && mParameters.hasAssociatedDisplay) {  
  3.         mSource = AINPUT_SOURCE_TOUCHSCREEN;  
  4.         mDeviceMode = DEVICE_MODE_DIRECT;  
  5.         if (hasStylus()) {  
  6.             mSource |= AINPUT_SOURCE_STYLUS;  
  7.         }  
  8. }  
(2) configureRawPointerAxes()中获取的mRawPointerAxes.x和mRawPointerAxes.y确定width and height。触摸屏需要显示,mParameters.hasAssociatedDisplay = true;而且不是外部设备。 mHWRotation表示旋转方向。如果touch分辨率的尺寸和显示的尺寸不一致,需要调整系数mXScale和mYScale。还有其他的参数调整,用到再说。

四 回来继续我们mapper的处理流程

[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void MultiTouchInputMapper::process(const RawEvent* rawEvent) {  
  2.     TouchInputMapper::process(rawEvent);  
  3.   
  4.     mMultiTouchMotionAccumulator.process(rawEvent);  
  5. }  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void TouchInputMapper::process(const RawEvent* rawEvent) {  
  2.     mCursorButtonAccumulator.process(rawEvent);  
  3.     mCursorScrollAccumulator.process(rawEvent);  
  4.     mTouchButtonAccumulator.process(rawEvent);  
  5.   
  6.     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {  
  7.         sync(rawEvent->when);  
  8.     }  
  9. }  
光标按钮作为设备键盘的处理,比如鼠标光标的左右中键、前进后退等等。
滚动光标作为轨迹处理,比如鼠标的中轮事件,REL_WHEEL表示纵向scroll事件,REL_HWHEEL表示横向scroll事件。
触摸屏按键处理,BTN_TOUCH的值指示按下和抬起,其余的code都是tool说明。
最后收到rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT进入sync()。对于type A一个sync事件包括多个mt synct(一个点),一个mt sync包括多个input event;对于type B一个sync事件包括多个mt slot(一个点),一个mt slot包括多个input event。如果不是sync事件呢?就走mMultiTouchMotionAccumulator.process(rawEvent)。
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {  
  2.     if (rawEvent->type == EV_ABS) {  
  3.         bool newSlot = false;  
  4. /*addDeviceLocked()中device->reset(when)->mapper->reset(when)->MultiTouchInputMapper::reset()->mMultiTouchMotionAccumulator.reset(getDevice())->clearSlots(),无论A类、B类mCurrentSlot都为-1。 MultiTouchInputMapper::syncTouch()的最后mMultiTouchMotionAccumulator.finishSync()只是type A的mCurrentSlot设为-1,B的呢?if (mUsingSlotsProtocol) mCurrentSlot = rawEvent->value; 
  5. */  
  6.         if (mUsingSlotsProtocol) {  
  7.             if (rawEvent->code == ABS_MT_SLOT) {  
  8.                 mCurrentSlot = rawEvent->value;//B类,是ID  
  9.                 newSlot = true;//貌似只为了打印一个warnning  
  10.             }  
  11.         } else if (mCurrentSlot < 0) {//A类  
  12.             mCurrentSlot = 0;  
  13.         }  
  14.   
  15.         if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {  
  16. #if DEBUG_POINTERS  
  17.             if (newSlot) {  
  18.                 ALOGW("MultiTouch device emitted invalid slot index %d but it "  
  19.                         "should be between 0 and %d; ignoring this slot.",  
  20.                         mCurrentSlot, mSlotCount - 1);  
  21.             }  
  22. #endif  
  23.         } else {  
  24.             Slot* slot = &mSlots[mCurrentSlot];  
  25.   
  26.             switch (rawEvent->code) {  
  27.             case ABS_MT_POSITION_X:  
  28.                 slot->mInUse = true;//mInUse标志其所在的slot是否使用  
  29.                 slot->mAbsMTPositionX = rawEvent->value;  
  30.                 break;  
  31.             case ABS_MT_POSITION_Y:  
  32.                 slot->mInUse = true;  
  33.                 slot->mAbsMTPositionY = rawEvent->value;  
  34.                 break;  
  35.             case ABS_MT_TOUCH_MAJOR:  
  36.                 slot->mInUse = true;  
  37.                 slot->mAbsMTTouchMajor = rawEvent->value;  
  38.                 break;  
  39.             case ABS_MT_TOUCH_MINOR:  
  40.                 slot->mInUse = true;  
  41.                 slot->mAbsMTTouchMinor = rawEvent->value;  
  42.                 slot->mHaveAbsMTTouchMinor = true;  
  43.                 break;  
  44.             case ABS_MT_WIDTH_MAJOR:  
  45.                 slot->mInUse = true;  
  46.                 slot->mAbsMTWidthMajor = rawEvent->value;  
  47.                 break;  
  48.             case ABS_MT_WIDTH_MINOR:  
  49.                 slot->mInUse = true;  
  50.                 slot->mAbsMTWidthMinor = rawEvent->value;  
  51.                 slot->mHaveAbsMTWidthMinor = true;  
  52.                 break;  
  53.             case ABS_MT_ORIENTATION:  
  54.                 slot->mInUse = true;  
  55.                 slot->mAbsMTOrientation = rawEvent->value;  
  56.                 break;  
  57.             case ABS_MT_TRACKING_ID:  
  58.                 if (mUsingSlotsProtocol && rawEvent->value < 0) {  
  59.                     // The slot is no longer in use but it retains its previous contents,  
  60.                     // which may be reused for subsequent touches.  
  61. /*type B不会上报SYN_MT_REPORT,是以ID为负来判断抬起的,此时标记mInUse为 false,就是标记up了,有up说明之前是down的状态,如果不是down过的,那底层driver就出问题了,没有按下就抬起的事件能存在就有点奇迹了。我们虽然标记了up,但是并没有清除slot中的其他内容,这些内容可能会被重用,所以id为-1时,需要有sync事件发出来去处理这个up,不然以后再次按下的时候,这个up事件就消失了。这样一说按下的时候也要及时发sync处理,不然就被up覆盖了。所以底层每当有点按下或抬起都会上报sync事件*/  
  62.                     slot->mInUse = false;  
  63.                 } else {  
  64.                     slot->mInUse = true;  
  65.                     slot->mAbsMTTrackingId = rawEvent->value;  
  66.                 }  
  67.                 break;  
  68.             case ABS_MT_PRESSURE:  
  69.                 slot->mInUse = true;  
  70.                 slot->mAbsMTPressure = rawEvent->value;  
  71.                 break;  
  72.             case ABS_MT_DISTANCE:  
  73.                 slot->mInUse = true;  
  74.                 slot->mAbsMTDistance = rawEvent->value;  
  75.                 break;  
  76.             case ABS_MT_TOOL_TYPE:  
  77.                 slot->mInUse = true;  
  78.                 slot->mAbsMTToolType = rawEvent->value;  
  79.                 slot->mHaveAbsMTToolType = true;  
  80.                 break;  
  81.             }  
  82.         }  
  83.     } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {  
  84.         // MultiTouch Sync: The driver has returned all data for *one* of the pointers.  
  85.         mCurrentSlot += 1;  
  86. /*对于type A只有收到mt sync的时候mCurrentSlot才加1,mt sync之前的code底层只会上报一次,上报多次就保留一次的,可见type A会把mt sync事件按照上报顺序存储在mSlots里。type B并不会上报SYN_MT_REPORT,mCurrentSlot = rawEvent->value,mCurrentSlot的取值就是上报ABS_MT_SLOT的ID,不一定顺序存储,是根据ID编号存储的,如果某个ID没有上报,对应的slot就空着。 
  87. */  
  88.     }  
  89. }  
如果事件不出意外,总会收到sync事件的。总能回到:
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. 如果事件不出意外,总会收到sync事件的。总能回到:  
  2.     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {  
  3.         sync(rawEvent->when);  
  4.   }  
它很长很长。

五 TouchInputMapper::sync()

1 mCurrentRawPointerData.clear()
hoveringIdBits 是hover事件的标识符清0,touchingIdBits是touch事件的标识符也清0,这两个事件是冲突的,有hover就没有touch。
2 syncTouch(when, &havePointerIds),havePointerIds (指示是否上报ID)为 true。
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {  
  2.     size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();//type B=32,type A=16  
  3.     size_t outCount = 0;  
  4.     BitSet32 newPointerIdBits;  
  5.   
  6.     for (size_t inIndex = 0; inIndex < inCount; inIndex++) {  
  7.         const MultiTouchMotionAccumulator::Slot* inSlot =//一个点  
  8.                 mMultiTouchMotionAccumulator.getSlot(inIndex);  
  9.         if (!inSlot->isInUse()) {//对应点已up  
  10.             continue;  
  11.         }  
  12.   
  13.         if (outCount >= MAX_POINTERS) {//最大支持16点,但是type B的slot是32?  
  14. #if DEBUG_POINTERS  
  15.             ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "  
  16.                     "ignoring the rest.",  
  17.                     getDeviceName().string(), MAX_POINTERS);  
  18. #endif  
  19.             break// too many fingers!  
  20.         }  
  21.   
  22.         RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount];  
  23.         outPointer.x = inSlot->getX();//一个点的信息  
  24.         outPointer.y = inSlot->getY();  
  25.         outPointer.pressure = inSlot->getPressure();  
  26.         outPointer.touchMajor = inSlot->getTouchMajor();  
  27.         outPointer.touchMinor = inSlot->getTouchMinor();  
  28.         outPointer.toolMajor = inSlot->getToolMajor();  
  29.         outPointer.toolMinor = inSlot->getToolMinor();  
  30.         outPointer.orientation = inSlot->getOrientation();  
  31.         outPointer.distance = inSlot->getDistance();  
  32.         outPointer.tiltX = 0;  
  33.         outPointer.tiltY = 0;  
  34.   
  35.         outPointer.toolType = inSlot->getToolType();  
  36.         if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {  
  37.             outPointer.toolType = mTouchButtonAccumulator.getToolType();  
  38.             if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {  
  39.                 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;  
  40.             }  
  41.         }  
  42. /*判断工具的,是手指或者笔。如果有上报ABS_MT_TOOL_TYPE,并且上报了合法的工具,那ok。否则mTouchButtonAccumulator.getToolType()来判断,判断不出来就是手指,默认的也是手指。 
  43. */  
  44.   
  45.         bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE  
  46.                 && (mTouchButtonAccumulator.isHovering()  
  47.                         || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));  
  48. /*神奇的hover事件来了。hover是光标模仿悬停事件,移动到一个对象上以及移除这个对象。产生hover的条件: 
  49. (1) 非AMOTION_EVENT_TOOL_TYPE_MOUSE工具; 
  50. (2) 设置上报BTN_TOUCH,但上报的值mBtnTouch是0;或者上报了pressure,其值<=0。 
  51. */  
  52.         outPointer.isHovering = isHovering;  
  53.   
  54.         // Assign pointer id using tracking id if available.  
  55.         if (*outHavePointerIds) {//如果id有效,第一次为true  
  56.             int32_t trackingId = inSlot->getTrackingId();  
  57.             int32_t id = -1;  
  58.             if (trackingId >= 0) {//上报id,有点按下的情况  
  59.                 for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {  
  60.                     uint32_t n = idBits.clearFirstMarkedBit();  
  61. /*从idBits(idBits = mPointerIdBits)中找出第一个被标记的bit,并清除该bit,返回该bit的索引。如果所有bit都没有被标记,结果是未定义的;所以idBits.isEmpty()时for退出。*/  
  62.                     if (mPointerTrackingIdMap[n] == trackingId) {  
  63.                         id = n;  
  64.                     }  
  65. /*mPointerIdBits表示点的标识符,如果mPointerTrackingIdMap[n]中有标记过trackingId的值,通过for循环能找到这个n,如果找不到id就为-1,就走下面的标记流程。 
  66. */  
  67.                 }  
  68.   
  69.                 if (id < 0 && !mPointerIdBits.isFull()) {  
  70.                     id = mPointerIdBits.markFirstUnmarkedBit();  
  71. /*从mPointerIdBits中找出第一个未标记的bit,并标记该bit,返回该bit的索引。如果所有bit都被标记,结果是未定义的。mPointerIdBits.isFull()时,就没有地方标记了。 
  72. */  
  73.                     mPointerTrackingIdMap[id] = trackingId;  
  74.                 }  
  75.             }  
  76. /*mPointerIdBits的bit为1标记的是有一个点按下;32bit系统,可以标记32点。mPointerTrackingIdMap[]与mPointerIdBits对应,设置mPointerIdBits的第id(从0开始)个bit的同时,要设置mPointerTrackingIdMap[id] = trackingId。mPointerTrackingIdMap[id]的值存储的是点的ID,通过id可以找到ID。 
  77. */  
  78.             if (id < 0) {  
  79. /*不上报ID(只有type A会不上报)会走到这里一次,或者上报ID -1时也到这里,都会有清除动作。只要是type A总会设置*outHavePointerIds = false的。 
  80. (1) type A不上报ID的按下,在syncTouch()中hover、touch、pointer的标识符都是0,所以判断按下抬起的状态不在这个函数里。 
  81. (2) type A不上报ID的抬起,如果上报mt synch和sync之外还报了别的input event,slot->mInUse = true,会记录最后一次outPointer,只是坐标为0。还可能遗留一个hover,因为outPointer.isHovering = isHovering,如果条件满足最后的isHovering被设置,以后可用。 
  82. (3) type A上报id(抬起时为-1)的抬起,也会记录最后一次outPointer和保留isHovering状态。 
  83. (4) 上报id,typeB的抬起会设置slot->mInUse = false,不会走到这里,就不会记录最后一次outPointer,也不会将之前记录的hover、touch、pointer的标识符都清0。 
  84. */  
  85.                 *outHavePointerIds = false;  
  86.                 mCurrentRawPointerData.clearIdBits();//清hover和touch表示符  
  87.                 newPointerIdBits.clear();//清点数表示符  
  88.             } else {  
  89.                 outPointer.id = id;  
  90. /*此id表示mPointerIdBits的第id个bit,通过mPointerTrackingIdMap[id]可以找到点上报来的ID*/  
  91.                 mCurrentRawPointerData.idToIndex[id] = outCount;//标记点来的顺序  
  92.                 mCurrentRawPointerData.markIdBit(id, isHovering);//设hover或touch标识  
  93.                 newPointerIdBits.markBit(id);//设置点的标识  
  94.             }  
  95.         }  
  96.   
  97.         outCount += 1;  
  98.     }  
  99.   
  100.     mCurrentRawPointerData.pointerCount = outCount;//总点数  
  101.     mPointerIdBits = newPointerIdBits;//设置点的标识符  
  102.   
  103.   mMultiTouchMotionAccumulator.finishSync();  
  104.   /*type A清slot,B不需要清,MultiTouchMotionAccumulator::process()中会处理*/  
  105. }  
syncTouch()执行后点的信息就存到了mCurrentRawPointerData中。
3 type A不报ID时,设置havePointerIds为false,走上边的打印;type A无论报不报ID抬起时的sync都走上边。type B按下和抬起,type A报ID时的按下走下边。
4 TouchInputMapper构造时mDeviceMode(DEVICE_MODE_DISABLED),configure()执行之后为mDeviceMode == DEVICE_MODE_DIRECT表示touch。
5 type A不报ID或者(无论报不报ID)up时才走assignPointerIds()。
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. void TouchInputMapper::assignPointerIds() {  
  2.     uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;  
  3.     uint32_t lastPointerCount = mLastRawPointerData.pointerCount;  
  4.   
  5.     mCurrentRawPointerData.clearIdBits();//清hover、touch标识bit,用自己的方法从新判断  
  6.   
  7.     if (currentPointerCount == 0) {//总点数为0  
  8.         // No pointers to assign.  
  9.         return;  
  10.     }  
  11.   
  12.     if (lastPointerCount == 0) {//上一点数为0,所有点都是新点  
  13.         // All pointers are new.  
  14.         for (uint32_t i = 0; i < currentPointerCount; i++) {  
  15.             uint32_t id = i;  
  16.             mCurrentRawPointerData.pointers[i].id = id;  
  17. /*type A是按点顺序存储的,type B的在上面,根据id能找到点的ID,这个不能*/  
  18.             mCurrentRawPointerData.idToIndex[id] = i;  
  19.             mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i));  
  20. /*标记一下touch或hover事件*/  
  21.         }  
  22.         return;  
  23.     }  
  24.   
  25.     if (currentPointerCount == 1 && lastPointerCount == 1  
  26.             && mCurrentRawPointerData.pointers[0].toolType  
  27.                     == mLastRawPointerData.pointers[0].toolType) {  
  28.         uint32_t id;  
  29.         if (!mCurrentRawPointerData.isHovering(0) &&  
  30.                 !mLastRawPointerData.hoveringIdBits.isEmpty()) {  
  31.             // 1 finger released and touching again. Should be safe to  
  32.             // reset to id 0.  
  33. /*上一次产生了hover,那是一个上报了BTN或者pressure的up;现在没有hover了,说明有手指按下了,也是一个新点*/  
  34.             id = 0;  
  35.         } else {  
  36.             // Only one pointer and no change in count so it must have the same id as before.  
  37. //一直是一个点  
  38.             id = mLastRawPointerData.pointers[0].id;  
  39.         }  
  40.         mCurrentRawPointerData.pointers[0].id = id;  
  41.         mCurrentRawPointerData.idToIndex[id] = 0;  
  42.         mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(0));  
  43.         return;  
  44.     }  
  45.   
  46.     // General case.  
  47.     // We build a heap of squared euclidean distances between current and last pointers  
  48.     // associated with the current and last pointer indices.  Then, we find the best  
  49.     // match (by distance) for each current pointer.  
  50.     // The pointers must have the same tool type but it is possible for them to  
  51.     // transition from hovering to touching or vice-versa while retaining the same id.  
  52.     PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];  
  53. /*通常情况 
  54. 我们构造一个存储当前点和上一个点(与当前点和上一个点索引相关的)之间euclidean距离平方值的heap,我们就可以根据距离为当前点找到最好的匹配。 
  55. 这些点必须使用同一种tool type,保持同一个id时,该tool可能使这些点从hovering转到touching,反之亦然。 
  56. */  
  57.     uint32_t heapSize = 0;  
  58.     for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;  
  59.             currentPointerIndex++) {  
  60.         for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;  
  61.                 lastPointerIndex++) {  
  62.             const RawPointerData::Pointer& currentPointer =  
  63.                     mCurrentRawPointerData.pointers[currentPointerIndex];  
  64.             const RawPointerData::Pointer& lastPointer =  
  65.                     mLastRawPointerData.pointers[lastPointerIndex];  
  66.             if (currentPointer.toolType == lastPointer.toolType) {  
  67.                 int64_t deltaX = currentPointer.x - lastPointer.x;  
  68.                 int64_t deltaY = currentPointer.y - lastPointer.y;  
  69.   
  70.                 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);  
  71.   
  72.                 // Insert new element into the heap (sift up).  
  73.                 heap[heapSize].currentPointerIndex = currentPointerIndex;  
  74.                 heap[heapSize].lastPointerIndex = lastPointerIndex;  
  75.                 heap[heapSize].distance = distance;  
  76.                 heapSize += 1;  
  77.             }     
  78.         }  
  79.     }  
  80. /*两次for循环结束后,heap中存储了每个当前点与上一次所有点的euclidean距离。 
  81. */  
  82.     // Heapify  
  83.     for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {  
  84.         startIndex -= 1;         
  85.         for (uint32_t parentIndex = startIndex; ;) {  
  86.             uint32_t childIndex = parentIndex * 2 + 1;  
  87.             if (childIndex >= heapSize) {  
  88.                 break;  
  89.             }  
  90.   
  91.             if (childIndex + 1 < heapSize  
  92.                     && heap[childIndex + 1].distance < heap[childIndex].distance) {  
  93.                 childIndex += 1;  
  94.             }  
  95.   
  96.             if (heap[parentIndex].distance <= heap[childIndex].distance) {  
  97.                 break;  
  98.             }  
  99.   
  100.             swap(heap[parentIndex], heap[childIndex]);  
  101.             parentIndex = childIndex;  
  102.         }  
  103.     }  
  104. /*这是个堆排序的过程,堆本身是一个二叉树,类似于 
  105.                 0 
  106.               /    \ 
  107.                1     2 
  108.               / \   / \ 
  109.              3  4   5  6 
  110.             / \    / \ 
  111.          7  8 
  112. code中需要的是最小堆的性质,如果不满足就调整。从最后一个可以作为根的结点开始。例如heapSize 为9,先把heap[3]结点为根的分支,调整为最小堆;然后调整heap[2]结点为根的分支;最后调整以heap[0]结点为根的分支,就是整个树,先将heap[0]与heap[1]、heap[2]中值小的比较,如果heap[0]最小,那相安无事;如果heap[0]不最小,那就调整为最小堆;假设heap[0]与heap[2]swap了,那需要重新调整heap[2]的分支了。最后形成的树是根结点值最小,左右结点不确定。 
  113. */  
  114. #if DEBUG_POINTER_ASSIGNMENT  
  115.     ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);  
  116.     for (size_t i = 0; i < heapSize; i++) {  
  117.         ALOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",  
  118.                 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,  
  119.                 heap[i].distance);  
  120.     }  
  121. #endif  
  122.   
  123.     // Pull matches out by increasing order of distance.  
  124.     // To avoid reassigning pointers that have already been matched, the loop keeps track  
  125.     // of which last and current pointers have been matched using the matchedXXXBits variables.  
  126.   // It also tracks the used pointer id bits.  
  127.   /*按照距离增加的顺序取出匹配项。为了避免重新分配已经匹配的指针,循环保持跟踪表示上一个和当前点已经匹配的matchedXXXBits变量,还跟踪已经使用点id的对应bit位。 
  128.   */  
  129.     BitSet32 matchedLastBits(0);  
  130.     BitSet32 matchedCurrentBits(0);  
  131.     BitSet32 usedIdBits(0);  
  132.     bool first = true;  
  133.     for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {  
  134.         while (heapSize > 0) {  
  135.             if (first) {  
  136.                 // The first time through the loop, we just consume the root element of  
  137.                 // the heap (the one with smallest distance).  
  138. /*通过第一次循环,我们要消耗掉heap的根结点,因为这颗树中唯一可以判断大小的就是它,它是距离最小的一个结点。 
  139. */  
  140.                 first = false;  
  141.             } else {  
  142.                 // Previous iterations consumed the root element of the heap.  
  143.                 // Pop root element off of the heap (sift down).  
  144. /*之前的迭代消耗了heap的根结点,弹出heap的根结点,进行sift down(向下筛选调整),每次取堆顶端的数,然后重新构造堆,如此迭代,直到所有的数据都取出。 
  145. */  
  146.                 heap[0] = heap[heapSize];//填充被取走后的heap[0]  
  147. //重新构造堆  
  148.                 for (uint32_t parentIndex = 0; ;) {  
  149.                     uint32_t childIndex = parentIndex * 2 + 1;  
  150.                     if (childIndex >= heapSize) {  
  151.                         break;  
  152.                     }  
  153.   
  154.                     if (childIndex + 1 < heapSize  
  155.                             && heap[childIndex + 1].distance < heap[childIndex].distance) {  
  156.                         childIndex += 1;  
  157.                     }  
  158.   
  159.                     if (heap[parentIndex].distance <= heap[childIndex].distance) {  
  160.                         break;  
  161.                     }  
  162.   
  163.                     swap(heap[parentIndex], heap[childIndex]);  
  164.                     parentIndex = childIndex;  
  165.                 }  
  166.   
  167. #if DEBUG_POINTER_ASSIGNMENT  
  168.                 ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);  
  169.                 for (size_t i = 0; i < heapSize; i++) {  
  170.                     ALOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",  
  171.                             i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,  
  172.                             heap[i].distance);  
  173.                 }  
  174. #endif  
  175.             }  
  176.   
  177.             heapSize -= 1;  
  178. /*每次都取堆顶的最小值*/  
  179.             uint32_t currentPointerIndex = heap[0].currentPointerIndex;  
  180.             if (matchedCurrentBits.hasBit(currentPointerIndex)) continue// already matched  
  181.   
  182.             uint32_t lastPointerIndex = heap[0].lastPointerIndex;  
  183.             if (matchedLastBits.hasBit(lastPointerIndex)) continue// already matched  
  184.   
  185.             matchedCurrentBits.markBit(currentPointerIndex);  
  186.             matchedLastBits.markBit(lastPointerIndex);  
  187.   
  188.             uint32_t id = mLastRawPointerData.pointers[lastPointerIndex].id;  
  189.             mCurrentRawPointerData.pointers[currentPointerIndex].id = id;  
  190. /*last点和current点匹配上了,current点的ID就找到了*/  
  191.             mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;  
  192. /*idToIndex[id]里的值就是标记点来的顺序*/  
  193.             mCurrentRawPointerData.markIdBit(id,  
  194.                     mCurrentRawPointerData.isHovering(currentPointerIndex));  
  195.             usedIdBits.markBit(id);//标记已经使用点id的对应bit位  
  196.   
  197. #if DEBUG_POINTER_ASSIGNMENT  
  198.             ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",  
  199.                     lastPointerIndex, currentPointerIndex, id, heap[0].distance);  
  200. #endif  
  201.             break;  
  202.         }  
  203.     }  
  204. /*内存while就是控制sift down(向下筛选调整),每次取堆顶端的数,然后重新构造堆;外层for就是控制迭代次数,直到所有的数据都取出。 
  205. */  
  206.   // Assign fresh ids to pointers that were not matched in the process.  
  207.   /*如果last点数多,那么至此所有点都匹配上了;但是如果last点少,current中还有未匹配的点呢,需要为这些新点分配一下ids 
  208.   */  
  209.     for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {  
  210.         uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();  
  211.         uint32_t id = usedIdBits.markFirstUnmarkedBit();  
  212.   
  213.         mCurrentRawPointerData.pointers[currentPointerIndex].id = id;  
  214.         mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;  
  215.         mCurrentRawPointerData.markIdBit(id,  
  216.                 mCurrentRawPointerData.isHovering(currentPointerIndex));  
  217.   
  218. #if DEBUG_POINTER_ASSIGNMENT  
  219.         ALOGD("assignPointerIds - assigned: cur=%d, id=%d",  
  220.                 currentPointerIndex, id);  
  221. #endif  
  222.     }  
  223. }  
能进入这个函数,说明没有上报ID,是type A;如果上报ID,在syncTouch()中就把这些工作做了,就可以用上报的ID标识各个点了,很容易判断down和up。没有上报ID,就需要用一些算法来匹配当前点与上一点,从而找到软件上的id,最终判断出down和up。
需要说明的是:type A正常不报ID的按下,走这里没有问题,也不会产生hover事件。但是type A抬起的时候,是有说法的。
(1) 只要上报了BTN或者pressure,就会产生hover事件,所以最后都不会产生touch事件;对于单点保持,可能是上次产生了hover,如果产生了hover也只能是last点数为1,因为hover是上报up,上报up的时候只上报一点的信息附加一个mt sync和sync,此种情况当做新点处理,id为0;也可能是单点移动,此种情况保持id不变。
(2) 不上报BTN,也不上报pressure,也不上报ID;up时不会产生hover,也能正常抬起,因为syncTouch()中inSlot->isInUse()为false,最后的current点数为0。
(3) 不上报BTN,也不上报pressure,但是只上报ID -1,附加一个mt sync和sync,syncTouch()中inSlot->isInUse()为true,此时current点数为1,同时设置*outHavePointerIds = false,进入assignPointerIds()时,就一直有一个(0,0)点在那,永远找不到up。只要不是只报input_mt_sync(ts->input_dev)的就都会有问题的。不报ID的type A syncTouch()就出来了点的基本信息和点数。
对于上报ID的情况,点的提取是在syncTouch()中完成的,从底层上报点的ABS_MT_TRACKING_ID,mPointerTrackingIdMap[n] = trackingId,只用了一次,如果第二次上来的点和第一次的有重复,就根据trackingId找到id。一直使用的id是和hoveringIdBits相对应的,也是和mPointerIdBits相对应的。要求底层上报id是按顺序的,如果第一次点的上报ID为:
0、1、2、3
第二次如果第2点抬起,要求点的ID为:
0、1、3
然后再上报一个2为-1的ID
如果第二点抬起后为:
0、1、2
就找不到是哪个点抬起了。
ABS_MT_TRACKING_ID就是点出来的顺序,从0开始的话就与一直使用的id一致;从1开始也可以,不能与id一一对应而已。
type中 input_mt_slot(struct input_dev *dev, int slot)里的slot才是点的ID。type A上报ID一定是标记好点出来的顺序,就是上面说的顺序。
6 cookPointerData()进行校正处理,包括原始坐标的转换,旋转,touchMajor和toolMajor的size校正。
[cpp] view plain copy print?
  1. mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits;  
  2. mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits;  
7 分发
dispatchHoverExit(when, policyFlags);
分发hover exit事件,指针没有down,但是位于某个窗口或视图范围内。前提是mSentHoverEnter = true,并且上一次产生了hover,当前hover消失。
mSentHoverEnter是标识有hover enter事件,指针没有down,但是进入了某个窗口或视图范围内。是在dispatchHoverEnterAndMove(when, policyFlags)中设置的。前提是上一次没有hover,当前产生了hover。
[cpp] view plain copy print?
  1. void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {  
  2.     BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;  
  3.     BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;  
  4.     int32_t metaState = getContext()->getGlobalMetaState();  
  5.     int32_t buttonState = mCurrentButtonState;  
  6.   
  7.     if (currentIdBits == lastIdBits) {  
  8.         if (!currentIdBits.isEmpty()) {  
  9.             // No pointer id changes so this is a move event.  
  10.             // The listener takes care of batching moves so we don't have to deal with that here.  
  11. /*没有指针id改变,所以这是一个移动事件。监视器负责批处理移动事件,我们不需要处理*/  
  12.             dispatchMotion(when, policyFlags, mSource,  
  13.                     AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,  
  14.                     AMOTION_EVENT_EDGE_FLAG_NONE,  
  15.                     mCurrentCookedPointerData.pointerProperties,  
  16.                     mCurrentCookedPointerData.pointerCoords,  
  17.                     mCurrentCookedPointerData.idToIndex,  
  18.                     currentIdBits, -1,  
  19.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  20.         }  
  21.     } else {  
  22.         // There may be pointers going up and pointers going down and pointers moving  
  23.         // all at the same time.  
  24.         BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);  
  25.         BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);  
  26.         BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);  
  27.         BitSet32 dispatchedIdBits(lastIdBits.value);  
  28.   
  29.         // Update last coordinates of pointers that have moved so that we observe the new  
  30.         // pointer positions at the same time as other pointers that have just gone up.  
  31.         bool moveNeeded = updateMovedPointers(  
  32.                 mCurrentCookedPointerData.pointerProperties,  
  33.                 mCurrentCookedPointerData.pointerCoords,  
  34.                 mCurrentCookedPointerData.idToIndex,  
  35.                 mLastCookedPointerData.pointerProperties,  
  36.                 mLastCookedPointerData.pointerCoords,  
  37.                 mLastCookedPointerData.idToIndex,  
  38.                 moveIdBits);  
  39.         if (buttonState != mLastButtonState) {  
  40.             moveNeeded = true;  
  41.         }  
  42.   
  43.         // Dispatch pointer up events.  
  44.         while (!upIdBits.isEmpty()) {  
  45.             uint32_t upId = upIdBits.clearFirstMarkedBit();  
  46.   
  47.             dispatchMotion(when, policyFlags, mSource,  
  48.                     AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,  
  49.                     mLastCookedPointerData.pointerProperties,  
  50.                     mLastCookedPointerData.pointerCoords,  
  51.                     mLastCookedPointerData.idToIndex,  
  52.                     dispatchedIdBits, upId,  
  53.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  54.             dispatchedIdBits.clearBit(upId);  
  55.         }  
  56.   
  57.         // Dispatch move events if any of the remaining pointers moved from their old locations.  
  58.         // Although applications receive new locations as part of individual pointer up  
  59.         // events, they do not generally handle them except when presented in a move event.  
  60.         if (moveNeeded) {  
  61.             ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);  
  62.             dispatchMotion(when, policyFlags, mSource,  
  63.                     AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,  
  64.                     mCurrentCookedPointerData.pointerProperties,  
  65.                     mCurrentCookedPointerData.pointerCoords,  
  66.                     mCurrentCookedPointerData.idToIndex,  
  67.                     dispatchedIdBits, -1,  
  68.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  69.         }  
  70.   
  71.         // Dispatch pointer down events using the new pointer locations.  
  72.         while (!downIdBits.isEmpty()) {  
  73.             uint32_t downId = downIdBits.clearFirstMarkedBit();  
  74.             dispatchedIdBits.markBit(downId);  
  75.   
  76.             if (dispatchedIdBits.count() == 1) {  
  77.                 // First pointer is going down.  Set down time.  
  78.                 mDownTime = when;  
  79.             }  
  80.   
  81.             dispatchMotion(when, policyFlags, mSource,  
  82.                     AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,  
  83.                     mCurrentCookedPointerData.pointerProperties,  
  84.                     mCurrentCookedPointerData.pointerCoords,  
  85.                     mCurrentCookedPointerData.idToIndex,  
  86.                     dispatchedIdBits, downId,  
  87.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  88.         }  
  89.     }  
  90. }  
dispatchTouches()分出来move、down和up事件,调用dispatchMotion()来分发处理。
[cpp] view plain copy print?
  1. void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,  
  2.         int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,  
  3.         const PointerProperties* properties, const PointerCoords* coords,  
  4.         const uint32_t* idToIndex, BitSet32 idBits,  
  5.         int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {  
  6.     PointerCoords pointerCoords[MAX_POINTERS];  
  7.     PointerProperties pointerProperties[MAX_POINTERS];  
  8.     uint32_t pointerCount = 0;  
  9.     while (!idBits.isEmpty()) {  
  10.         uint32_t id = idBits.clearFirstMarkedBit();  
  11.         uint32_t index = idToIndex[id];  
  12.         pointerProperties[pointerCount].copyFrom(properties[index]);//id信息  
  13.         pointerCoords[pointerCount].copyFrom(coords[index]);//值信息  
  14.   
  15.         if (changedId >= 0 && id == uint32_t(changedId)) {  
  16.             action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;  
  17.         }  
  18. /*action中的bits代表一个down或者up的指针索引,我们把实际的指针索引就存在<< AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT的位置,后面用的时候>>AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT就取出了这个索引*/  
  19.         pointerCount += 1;  
  20.     }  
  21.   
  22.     ALOG_ASSERT(pointerCount != 0);  
  23.   
  24.     if (changedId >= 0 && pointerCount == 1) {  
  25.         // Replace initial down and final up action.  
  26.         // We can compare the action without masking off the changed pointer index  
  27.         // because we know the index is 0.  
  28. /*替换最初的down和最终的up。 
  29. 我们可以比较没有屏蔽掉改变指针索引的action,因为我们知道index是0(id不一定是0)。 
  30. */  
  31.         if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {  
  32.             action = AMOTION_EVENT_ACTION_DOWN;  
  33.         } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {  
  34.             action = AMOTION_EVENT_ACTION_UP;  
  35.         } else {  
  36.             // Can't happen.  
  37.             ALOG_ASSERT(false);  
  38.         }  
  39.     }  
  40.   
  41.     NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,  
  42.             action, flags, metaState, buttonState, edgeFlags,  
  43.             mViewport.displayId, pointerCount, pointerProperties, pointerCoords,  
  44.             xPrecision, yPrecision, downTime);  
  45.   
  46.     // resize touch coords for (dual_display && freescale_disabled)  
  47.     // rw.vout.scale: off/freescale_disabled, on/freescale_enabled  
  48.     char prop_dual[PROPERTY_VALUE_MAX];  
  49.     if (!mPadmouseStatus && property_get("ro.vout.dualdisplay2", prop_dual, "false")  
  50.         && (strcmp(prop_dual, "true") == 0)  
  51.         && (action == AMOTION_EVENT_ACTION_DOWN  
  52.             || action == AMOTION_EVENT_ACTION_UP  
  53.             || action == AMOTION_EVENT_ACTION_MOVE)) {  
  54.            
  55.         bool  resize_touch = false;          
  56.   
  57.         if (strncmp(g_dmode_str, "panel", 5) != 0) {  
  58.             char prop[PROPERTY_VALUE_MAX];  
  59.             if (property_get("rw.vout.scale", prop, "on")  
  60.                 && strcmp(prop, "off") == 0) {  
  61.                 resize_touch = true;  
  62.             }                      
  63.         }  
  64.           
  65.         if (resize_touch) {  
  66.             int x = 0, y = 0, w = 0, h = 0;  
  67.             if(sscanf(g_daxis_str, "%d %d %d %d", &x,&y,&w,&h) > 0) {  
  68.                 int ww = w, hh = h;  
  69.                 if (strncmp(g_dmode_str, "1080p", 5) == 0) {  
  70.                     ww = 1920;  
  71.                     hh = 1080;  
  72.                 } else if (strncmp(g_dmode_str, "720p", 4) == 0) {  
  73.                     ww = 1280;  
  74.                     hh = 720;                  
  75.                 } else if (strncmp(g_dmode_str, "480p", 4) == 0) {  
  76.                     ww = 720;  
  77.                     hh = 480;                     
  78.                 }   
  79.                  
  80.                 if (ww >= w) x = (ww - w) / 2;  
  81.                 if (hh >= h) y = (hh - h) / 2;  
  82.                  
  83.                 for (uint32_t i = 0; i < args.pointerCount; i++) {  
  84.                     float coords_x = args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X);  
  85.                     float coords_y = args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y);  
  86.                     if (ww >= w && hh >= h) {   //1024*600 < 1280*720  
  87.                         coords_x = coords_x*(w + 2*x)/w;  
  88.                         coords_y = coords_y*(h + 2*y)/h;  
  89.                         coords_x = (coords_x - x)*(w + 2*x)/w;  
  90.                         coords_y = (coords_y - y)*(h + 2*y)/h;  
  91.                         coords_x = coords_x*w/(w + 2*x);  
  92.                         coords_y = coords_y*h/(h + 2*y);  
  93.                     } else if (ww >= w && hh < h) {   //1024*768 > 1280*720  
  94.                         coords_x = coords_x*(w + 2*x)/w;  
  95.                         coords_y = coords_y*hh/h;  
  96.                         coords_x = (coords_x - x)*(w + 2*x)/w;  
  97.                         coords_y = (coords_y - 0)*hh/h;  
  98.                         coords_x = coords_x*w/(w + 2*x);  
  99.                         coords_y = coords_y*h/hh;  
  100.                     } else {                    //1024*600 > 720*480  
  101.                         coords_x = coords_x*ww/w;  
  102.                         coords_y = coords_y*hh/h;  
  103.                         coords_x = (coords_x - 0)*ww/w;  
  104.                         coords_y = (coords_y - 0)*hh/h;  
  105.                         coords_x = coords_x*w/ww;  
  106.                         coords_y = coords_y*h/hh;  
  107.                     }  
  108.                     args.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, coords_x);  
  109.                     args.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, coords_y);  
  110.                 }                       
  111.             }     
  112.         }      
  113.     }          
  114.   getListener()->notifyMotion(&args);  
  115.   //至此各event已经分发,并且通知inputDispatch。  
  116. }  




0 0
原创粉丝点击