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 mQueuedListener。这样,在InputMapper::sync中getListener()->notifyMotion的最终调用为:
QueuedInputListener::notifyMotion (InputReader.mQueuedInputListener->notifyMotion )。

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


你可能感兴趣的:(android,input,专题)