Android4.1 InputManagerService 流程

来源:互联网 发布:水洗唛打印软件 编辑:程序博客网 时间:2024/06/08 05:12
1. mInputManager = new InputManagerService(context, mInputMonitor);

   在WMS的构造函数中进行初始化, mInputMonitor 继承InputManagerService.Callbacks,传给InputMangerService中的mCallbacks,WMS中的Context给mContext;

   在InputManagerService的构造函数中,主要是初始化了变量,最后调用了Native的方法

[java] view plaincopyprint?
  1. public InputManagerService(Context context, Callbacks callbacks) {  
  2.     this.mContext = context;  
  3.     this.mCallbacks = callbacks;  
  4.     this.mHandler = new InputManagerHandler();  
  5.   
  6.     Slog.i(TAG, "Initializing input manager");  
  7.     mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());  
  8. }  
    public InputManagerService(Context context, Callbacks callbacks) {        this.mContext = context;        this.mCallbacks = callbacks;        this.mHandler = new InputManagerHandler();        Slog.i(TAG, "Initializing input manager");        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());    }


2. nativeInit (frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp)


[cpp] view plaincopyprint?
  1. static jint nativeInit(JNIEnv* env, jclass clazz,  
  2.         jobject serviceObj, jobject contextObj, jobject messageQueueObj) {  
  3.     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);  
  4.     NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,  
  5.             messageQueue->getLooper());  
  6.     im->incStrong(serviceObj);  
  7.     return reinterpret_cast<jint>(im);  
  8. }  
static jint nativeInit(JNIEnv* env, jclass clazz,        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,            messageQueue->getLooper());    im->incStrong(serviceObj);    return reinterpret_cast<jint>(im);}

   在JNI的nativeInit中,初始化了NativeInputManager,把IMS里面的inputManagerHandle中的Looper传给了NativeInputManager


[cpp] view plaincopyprint?
  1. NativeInputManager::NativeInputManager(jobject contextObj,  
  2.         jobject serviceObj, const sp<Looper>& looper) :  
  3.         mLooper(looper) {  
  4.     ... ...  
  5.   
  6.     sp<EventHub> eventHub = new EventHub();  
  7.     mInputManager = new InputManager(eventHub, thisthis);  
NativeInputManager::NativeInputManager(jobject contextObj,        jobject serviceObj, const sp<Looper>& looper) :        mLooper(looper) {    ... ...    sp<EventHub> eventHub = new EventHub();    mInputManager = new InputManager(eventHub, this, this);
    在NativeInputManager的构造中,主要就是new出了一个EventHub, 然后作为构造参数给IputManager,最终最为一个参数传给InputReader。 并且和InputManagerHander共用同一个MessageQueue.
   这里面的readerPolicy和dispatcherPolicy实际上就是NativeInputManager对象,后面会用到。

[cpp] view plaincopyprint?
  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. }  
InputManager::InputManager(        const sp<EventHubInterface>& eventHub,        const sp<InputReaderPolicyInterface>& readerPolicy,        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {    mDispatcher = new InputDispatcher(dispatcherPolicy);    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);    initialize();}

[cpp] view plaincopyprint?
  1. void InputManager::initialize() {  
  2.     mReaderThread = new InputReaderThread(mReader);  
  3.     mDispatcherThread = new InputDispatcherThread(mDispatcher);  
  4. }  
void InputManager::initialize() {    mReaderThread = new InputReaderThread(mReader);    mDispatcherThread = new InputDispatcherThread(mDispatcher);}

     InputManager的构造函数中主要创建了InputReader 和 InputDispatcher对象并且保存在了mReader和mDispatcher中,InputDispatcher类是负责把键盘消息分发给当前激活的Activity窗口的,而InputReader类则是通过EventHub类来实现读取键盘事件的,后面我们会进一步分析。创建了这两个对象后,还要调用initialize函数来执行其它的初始化操作。

    initialize()这个函数创建了一个InputReaderThread线程实例和一个InputDispatcherThread线程实例,并且分别保存在成员变量mReaderThread和mDispatcherThread中。这里的InputReader实列mReader就是通过这里的InputReaderThread线程实列mReaderThread来读取键盘事件的,而InputDispatcher实例mDispatcher则是通过这里的InputDispatcherThread线程实例mDisptacherThread来分发键盘消息的。

 

3. mInputManager.start()

    InputManagerService 初始化完成之后,WMS就会去调用mInputManager.start() 来开始真正的检测键盘和touch事件。

   

[java] view plaincopyprint?
  1. public void start() {  
  2.     Slog.i(TAG, "Starting input manager");  
  3.     nativeStart(mPtr);  
  4.     ... ...  
  5. }  
    public void start() {        Slog.i(TAG, "Starting input manager");        nativeStart(mPtr);        ... ...    }
     InputManagerServcie.start只是直接去调用Native的start方法。

[cpp] view plaincopyprint?
  1. static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) {  
  2.     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);  
  3.   
  4.     status_t result = im->getInputManager()->start();  
  5.     if (result) {  
  6.         jniThrowRuntimeException(env, "Input manager could not be started.");  
  7.     }  
  8. }  
static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) {    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);    status_t result = im->getInputManager()->start();    if (result) {        jniThrowRuntimeException(env, "Input manager could not be started.");    }}

      nativeStart通过NativeInputManager 来获取 InputManager,之后直接真正干事的地方InputManager.start();

[cpp] view plaincopyprint?
  1. status_t InputManager::start() {  
  2.     status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);  
  3.   
  4.     result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);  
  5.   
  6.     return OK;  
  7. }  
status_t InputManager::start() {    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);    return OK;}

    这个函数主要是启动一个DispatcherThread线程和 ReaderThread线程用来读取和分发touch事件,这里的mDispatcherThread和mReaderThread就是我们之前在InputManager创建的两个线程。 调用run函数就会进入threadLoop函数中去,只要threadLoop返回的是true,函数threadoop就会一直被循环调用。于是这两个线程就起到了循环读取事件和分发事件的作用。

    所以我们直接进入到两个线程的threadLoop去查看一下是如何运行的。


4.  InputReaderThread::threadLoop() 

[cpp] view plaincopyprint?
  1. bool InputReaderThread::threadLoop() {  
  2.     mReader->loopOnce();  
  3.     return true;  
  4. }  
bool InputReaderThread::threadLoop() {    mReader->loopOnce();    return true;}
     InputReaderThread::threadLoop中通过调用mReader->loopOnce()来做每一次循环。 mReader是我们之前传进来的InputReader。

[cpp] view plaincopyprint?
  1. void InputReader::loopOnce() {  
  2.   
  3.     size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);  
  4.   
  5.     { // acquire lock   
  6.         AutoMutex _l(mLock);  
  7.         mReaderIsAliveCondition.broadcast();  
  8.   
  9.         if (count) {  
  10.             processEventsLocked(mEventBuffer, count);  
  11.         }  
  12.   
  13.         if (mNextTimeout != LLONG_MAX) {  
  14.             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  15.             if (now >= mNextTimeout) {  
  16.                 mNextTimeout = LLONG_MAX;  
  17.                 timeoutExpiredLocked(now);  
  18.             }  
  19.         }  
  20.   
  21.         if (oldGeneration != mGeneration) {  
  22.             inputDevicesChanged = true;  
  23.             getInputDevicesLocked(inputDevices);  
  24.         }  
  25.     } // release lock   
  26.   
  27.     // Send out a message that the describes the changed input devices.  
  28.     if (inputDevicesChanged) {  
  29.         mPolicy->notifyInputDevicesChanged(inputDevices);  
  30.     }  
  31.   
  32.     mQueuedListener->flush();  
  33. }  
void InputReader::loopOnce() {    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);    { // acquire lock        AutoMutex _l(mLock);        mReaderIsAliveCondition.broadcast();        if (count) {            processEventsLocked(mEventBuffer, count);        }        if (mNextTimeout != LLONG_MAX) {            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);            if (now >= mNextTimeout) {                mNextTimeout = LLONG_MAX;                timeoutExpiredLocked(now);            }        }        if (oldGeneration != mGeneration) {            inputDevicesChanged = true;            getInputDevicesLocked(inputDevices);        }    } // release lock    // Send out a message that the describes the changed input devices.    if (inputDevicesChanged) {        mPolicy->notifyInputDevicesChanged(inputDevices);    }    mQueuedListener->flush();}
   在这个函数中主要有两个操作,通过InputEent去getEents,然后processEventsLocked. getEent会去检测是否有Eent发生,如果就把Eents放到mEventBuffer中并且返回Event的个数,如果count是>0的数,说明是有Input发生的,然后交给processEventsLocked去处理。

 

[cpp] view plaincopyprint?
  1. void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {  
  2.     for (const RawEvent* rawEvent = rawEvents; count;) {  
  3.         int32_t type = rawEvent->type;  
  4.         size_t batchSize = 1;  
  5.         if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {  
  6.             int32_t deviceId = rawEvent->deviceId;  
  7.             while (batchSize < count) {  
  8.                 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT  
  9.                         || rawEvent[batchSize].deviceId != deviceId) {  
  10.                     break;  
  11.                 }  
  12.                 batchSize += 1;  
  13.             }  
  14. #if DEBUG_RAW_EVENTS   
  15.             ALOGD("BatchSize: %d Count: %d", batchSize, count);  
  16. #endif   
  17.             processEventsForDeviceLocked(deviceId, rawEvent, batchSize);  
  18.         } else {  
  19.             switch (rawEvent->type) {  
  20.             case EventHubInterface::DEVICE_ADDED:  
  21.                 addDeviceLocked(rawEvent->when, rawEvent->deviceId);  
  22.                 break;  
  23.             case EventHubInterface::DEVICE_REMOVED:  
  24.                 removeDeviceLocked(rawEvent->when, rawEvent->deviceId);  
  25.                 break;  
  26.             case EventHubInterface::FINISHED_DEVICE_SCAN:  
  27.                 handleConfigurationChangedLocked(rawEvent->when);  
  28.                 break;  
  29.             default:  
  30.                 ALOG_ASSERT(false); // can't happen  
  31.                 break;  
  32.             }  
  33.         }  
  34.         count -= batchSize;  
  35.         rawEvent += batchSize;  
  36.     }  
  37. }  
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {    for (const RawEvent* rawEvent = rawEvents; count;) {        int32_t type = rawEvent->type;        size_t batchSize = 1;        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {            int32_t deviceId = rawEvent->deviceId;            while (batchSize < count) {                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT                        || rawEvent[batchSize].deviceId != deviceId) {                    break;                }                batchSize += 1;            }#if DEBUG_RAW_EVENTS            ALOGD("BatchSize: %d Count: %d", batchSize, count);#endif            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;            }        }        count -= batchSize;        rawEvent += batchSize;    }}

   当有touch或者键盘事件发生时,rawEvent->type都有一个固定的值,这是一个宏定义,具体可以参考bionic/libc/kernel/common/linux/input.h文件。
  type < EventHubInterface::FIRST_SYNTHETIC_EVENT则是说明此次传上来的event type不是device add,remove或者scan的操作,是一个真的touch event。调用processEventsForDeviceLocked去接着处理事件。

[cpp] view plaincopyprint?
  1. struct RawEvent {  
  2.     nsecs_t when;  
  3.     int32_t deviceId;  
  4.     int32_t type;  
  5.     int32_t code;  
  6.     int32_t value;  
  7. };  
struct RawEvent {    nsecs_t when;    int32_t deviceId;    int32_t type;    int32_t code;    int32_t value;};

RawEent的结构体。

InputReader::processEventsForDeviceLocked

[html] view plaincopyprint?
  1. void InputReader::processEventsForDeviceLocked(int32_t deviceId,  
  2.         const RawEvent* rawEvents, size_t count) {  
  3.     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);  
  4.   
  5.     InputDevice* device = mDevices.valueAt(deviceIndex);  
  6.     if (device->isIgnored()) {  
  7.         //ALOGD("Discarding event for ignored deviceId %d.", deviceId);  
  8.         return;  
  9.     }  
  10.   
  11.     device->process(rawEvents, count);  
  12. }  
void InputReader::processEventsForDeviceLocked(int32_t deviceId,        const RawEvent* rawEvents, size_t count) {    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);    InputDevice* device = mDevices.valueAt(deviceIndex);    if (device->isIgnored()) {        //ALOGD("Discarding event for ignored deviceId %d.", deviceId);        return;    }    device->process(rawEvents, count);}
    mDevices是一个Vector类型的集合变量,将deviceId和不同的device作为键值进行保存。通过传进来的deviceId值,就可一找到对应需要处理输入事件的device,之后调用device->process来用指定的device去处理事件。 Input device早在之前就通过 InputReader::addDeviceLocked 把自己加到了mDevices中。    


[html] view plaincopyprint?
  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.   
  10.         if (mDropUntilNextSync) {  
  11.             if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {  
  12.                 mDropUntilNextSync = false;  
  13.   
  14.             } else {  
  15.   
  16.             }  
  17.         } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {  
  18.             ALOGI("Detected input event buffer overrun for device %s.", getName().string());  
  19.             mDropUntilNextSync = true;  
  20.             reset(rawEvent->when);  
  21.         } else {  
  22.             for (size_t i = 0; i < numMappers; i++) {  
  23.                 InputMapper* mapper = mMappers[i];  
  24.                 mapper->process(rawEvent);  
  25.             }  
  26.         }  
  27.     }  
  28. }  
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->code == SYN_REPORT) {                mDropUntilNextSync = false;            } else {            }        } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {            ALOGI("Detected input event buffer overrun for device %s.", getName().string());            mDropUntilNextSync = true;            reset(rawEvent->when);        } else {            for (size_t i = 0; i < numMappers; i++) {                InputMapper* mapper = mMappers[i];                mapper->process(rawEvent);            }        }    }}

 这里的mMappers保存了一系列输入设备事件处理象,例如负责处理键盘事件的KeyboardKeyMapper对象、负责处理轨迹球事件的TrackballInputMapper对象以及负责处理触摸屏事件的TouchInputMapper对象, 它们是在InputReader类的成员函数createDeviceLocked中创建的。

 这边假设只是一个单击屏幕的事件,于是就会用TouchInputMapper::process

[html] view plaincopyprint?
  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. }  
void TouchInputMapper::process(const RawEvent* rawEvent) {    mCursorButtonAccumulator.process(rawEvent);    mCursorScrollAccumulator.process(rawEvent);    mTouchButtonAccumulator.process(rawEvent);    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {        sync(rawEvent->when);    }}

这个函数中先让三个Accumulator去保存此次rawEent的一系列特性参数, 之后就会走到sync函数中(不知到rawEvent->type和rawEvent->code具体代表什么意思)

[html] view plaincopyprint?
  1. void TouchInputMapper::sync(nsecs_t when) {  
  2.     // Sync button state.  
  3.     mCurrentButtonState = mTouchButtonAccumulator.getButtonState()  
  4.             | mCursorButtonAccumulator.getButtonState();  
  5.   
  6.     // Sync scroll state.  
  7.     mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();  
  8.     mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();  
  9.     mCursorScrollAccumulator.finishSync();  
  10.   
  11.     // Sync touch state.  
  12.     bool havePointerIds = true;  
  13.     mCurrentRawPointerData.clear();  
  14.     syncTouch(when, &havePointerIds);  
  15.   
  16.   
  17.     if (mDeviceMode == DEVICE_MODE_DISABLED) {  
  18.         // Drop all input if the device is disabled.  
  19.         mCurrentRawPointerData.clear();  
  20.         mCurrentButtonState = 0;  
  21.     } else {  
  22.         // Preprocess pointer data.  
  23.         if (!havePointerIds) {  
  24.             assignPointerIds();  
  25.         }  
  26.   
  27.         // Handle policy on initial down or hover events.  
  28.         uint32_t policyFlags = 0;  
  29.         bool initialDown = mLastRawPointerData.pointerCount == 0  
  30.                 && mCurrentRawPointerData.pointerCount != 0;  
  31.         bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;  
  32.         if (initialDown || buttonsPressed) {  
  33.             // If this is a touch screen, hide the pointer on an initial down.  
  34.             if (mDeviceMode == DEVICE_MODE_DIRECT) {  
  35.                 getContext()->fadePointer();  
  36.             }  
  37.   
  38.             // Initial downs on external touch devices should wake the device.  
  39.             // We don't do this for internal touch screens to prevent them from waking  
  40.             // up in your pocket.  
  41.             // TODO: Use the input device configuration to control this behavior more finely.  
  42.             if (getDevice()->isExternal()) {  
  43.                 policyFlags |= POLICY_FLAG_WAKE_DROPPED;  
  44.             }  
  45.         }  
  46.   
  47.         // Synthesize key down from raw buttons if needed.  
  48.         synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,  
  49.                 policyFlags, mLastButtonState, mCurrentButtonState);  
  50.   
  51.         // Consume raw off-screen touches before cooking pointer data.  
  52.         // If touches are consumed, subsequent code will not receive any pointer data.  
  53.         if (<SPAN style="COLOR: rgb(255,0,0)">consumeRawTouches(when, policyFlags)</SPAN>) {  
  54.             mCurrentRawPointerData.clear();  
  55.         }  
  56.   
  57.         // Cook pointer data.  This call populates the mCurrentCookedPointerData structure  
  58.         // with cooked pointer data that has the same ids and indices as the raw data.  
  59.         // The following code can use either the raw or cooked data, as needed.  
  60.         cookPointerData();  
  61.   
  62.         // Dispatch the touches either directly or by translation through a pointer on screen.  
  63.         if (mDeviceMode == DEVICE_MODE_POINTER) {  
  64.             for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {  
  65.                 uint32_t id = idBits.clearFirstMarkedBit();  
  66.                 const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);  
  67.                 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS  
  68.                         || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {  
  69.                     mCurrentStylusIdBits.markBit(id);  
  70.                 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER  
  71.                         || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {  
  72.                     mCurrentFingerIdBits.markBit(id);  
  73.                 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {  
  74.                     mCurrentMouseIdBits.markBit(id);  
  75.                 }  
  76.             }  
  77.             for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) {  
  78.                 uint32_t id = idBits.clearFirstMarkedBit();  
  79.                 const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);  
  80.                 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS  
  81.                         || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {  
  82.                     mCurrentStylusIdBits.markBit(id);  
  83.                 }  
  84.             }  
  85.   
  86.             // Stylus takes precedence over all tools, then mouse, then finger.  
  87.             PointerUsage pointerUsage = mPointerUsage;  
  88.             if (!mCurrentStylusIdBits.isEmpty()) {  
  89.                 mCurrentMouseIdBits.clear();  
  90.                 mCurrentFingerIdBits.clear();  
  91.                 pointerUsage = POINTER_USAGE_STYLUS;  
  92.             } else if (!mCurrentMouseIdBits.isEmpty()) {  
  93.                 mCurrentFingerIdBits.clear();  
  94.                 pointerUsage = POINTER_USAGE_MOUSE;  
  95.             } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) {  
  96.                 pointerUsage = POINTER_USAGE_GESTURES;  
  97.             }  
  98.   
  99.             dispatchPointerUsage(when, policyFlags, pointerUsage);  
  100.         } else {  
  101.             if (mDeviceMode == DEVICE_MODE_DIRECT  
  102.                     && mConfig.showTouches && mPointerController != NULL) {  
  103.                 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);  
  104.                 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);  
  105.   
  106.                 mPointerController->setButtonState(mCurrentButtonState);  
  107.                 mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,  
  108.                         mCurrentCookedPointerData.idToIndex,  
  109.                         mCurrentCookedPointerData.touchingIdBits);  
  110.             }  
  111.   
  112. <SPAN style="COLOR: rgb(255,0,0)">            dispatchHoverExit(when, policyFlags);  
  113.             dispatchTouches(when, policyFlags);  
  114.             dispatchHoverEnterAndMove(when, policyFlags);</SPAN>  
  115.         }  
  116.   
  117.         // Synthesize key up from raw buttons if needed.  
  118.         synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,  
  119.                 policyFlags, mLastButtonState, mCurrentButtonState);  
  120.     }  
  121.   
  122.     // Copy current touch to last touch in preparation for the next cycle.  
  123.     mLastRawPointerData.copyFrom(mCurrentRawPointerData);  
  124.     mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);  
  125.     mLastButtonState = mCurrentButtonState;  
  126.     mLastFingerIdBits = mCurrentFingerIdBits;  
  127.     mLastStylusIdBits = mCurrentStylusIdBits;  
  128.     mLastMouseIdBits = mCurrentMouseIdBits;  
  129.   
  130.     // Clear some transient state.  
  131.     mCurrentRawVScroll = 0;  
  132.     mCurrentRawHScroll = 0;  
  133. }  
void TouchInputMapper::sync(nsecs_t when) {    // Sync button state.    mCurrentButtonState = mTouchButtonAccumulator.getButtonState()            | mCursorButtonAccumulator.getButtonState();    // Sync scroll state.    mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();    mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();    mCursorScrollAccumulator.finishSync();    // Sync touch state.    bool havePointerIds = true;    mCurrentRawPointerData.clear();    syncTouch(when, &havePointerIds);    if (mDeviceMode == DEVICE_MODE_DISABLED) {        // Drop all input if the device is disabled.        mCurrentRawPointerData.clear();        mCurrentButtonState = 0;    } else {        // Preprocess pointer data.        if (!havePointerIds) {            assignPointerIds();        }        // Handle policy on initial down or hover events.        uint32_t policyFlags = 0;        bool initialDown = mLastRawPointerData.pointerCount == 0                && mCurrentRawPointerData.pointerCount != 0;        bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;        if (initialDown || buttonsPressed) {            // If this is a touch screen, hide the pointer on an initial down.            if (mDeviceMode == DEVICE_MODE_DIRECT) {                getContext()->fadePointer();            }            // Initial downs on external touch devices should wake the device.            // We don't do this for internal touch screens to prevent them from waking            // up in your pocket.            // TODO: Use the input device configuration to control this behavior more finely.            if (getDevice()->isExternal()) {                policyFlags |= POLICY_FLAG_WAKE_DROPPED;            }        }        // Synthesize key down from raw buttons if needed.        synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,                policyFlags, mLastButtonState, mCurrentButtonState);        // Consume raw off-screen touches before cooking pointer data.        // If touches are consumed, subsequent code will not receive any pointer data.        if (consumeRawTouches(when, policyFlags)) {            mCurrentRawPointerData.clear();        }        // 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) {            for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {                uint32_t id = idBits.clearFirstMarkedBit();                const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);                if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {                    mCurrentStylusIdBits.markBit(id);                } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {                    mCurrentFingerIdBits.markBit(id);                } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {                    mCurrentMouseIdBits.markBit(id);                }            }            for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) {                uint32_t id = idBits.clearFirstMarkedBit();                const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);                if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {                    mCurrentStylusIdBits.markBit(id);                }            }            // Stylus takes precedence over all tools, then mouse, then finger.            PointerUsage pointerUsage = mPointerUsage;            if (!mCurrentStylusIdBits.isEmpty()) {                mCurrentMouseIdBits.clear();                mCurrentFingerIdBits.clear();                pointerUsage = POINTER_USAGE_STYLUS;            } else if (!mCurrentMouseIdBits.isEmpty()) {                mCurrentFingerIdBits.clear();                pointerUsage = POINTER_USAGE_MOUSE;            } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) {                pointerUsage = POINTER_USAGE_GESTURES;            }            dispatchPointerUsage(when, policyFlags, pointerUsage);        } else {            if (mDeviceMode == DEVICE_MODE_DIRECT                    && mConfig.showTouches && mPointerController != NULL) {                mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);                mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);                mPointerController->setButtonState(mCurrentButtonState);                mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,                        mCurrentCookedPointerData.idToIndex,                        mCurrentCookedPointerData.touchingIdBits);            }            dispatchHoverExit(when, policyFlags);            dispatchTouches(when, policyFlags);            dispatchHoverEnterAndMove(when, policyFlags);        }        // Synthesize key up from raw buttons if needed.        synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,                policyFlags, mLastButtonState, mCurrentButtonState);    }    // Copy current touch to last touch in preparation for the next cycle.    mLastRawPointerData.copyFrom(mCurrentRawPointerData);    mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);    mLastButtonState = mCurrentButtonState;    mLastFingerIdBits = mCurrentFingerIdBits;    mLastStylusIdBits = mCurrentStylusIdBits;    mLastMouseIdBits = mCurrentMouseIdBits;    // Clear some transient state.    mCurrentRawVScroll = 0;    mCurrentRawHScroll = 0;}

     如果这是单击事件,会走到mDeviceMode == DEVICE_MODE_DIRECT这个判断中,这里面已经开始去dispatchEvent了。

    总要是这三句话,我没有跟下去看,dispatchTouches(when, policyFlags);


[cpp] view plaincopyprint?
  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.             dispatchMotion(when, policyFlags, mSource,  
  12.                     AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,  
  13.                     AMOTION_EVENT_EDGE_FLAG_NONE,  
  14.                     mCurrentCookedPointerData.pointerProperties,  
  15.                     mCurrentCookedPointerData.pointerCoords,  
  16.                     mCurrentCookedPointerData.idToIndex,  
  17.                     currentIdBits, -1,  
  18.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  19.         }  
  20.     } else {  
  21.         // There may be pointers going up and pointers going down and pointers moving  
  22.         // all at the same time.   
  23.         BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);  
  24.         BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);  
  25.         BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);  
  26.         BitSet32 dispatchedIdBits(lastIdBits.value);  
  27.   
  28.         // Update last coordinates of pointers that have moved so that we observe the new  
  29.         // pointer positions at the same time as other pointers that have just gone up.  
  30.         bool moveNeeded = updateMovedPointers(  
  31.                 mCurrentCookedPointerData.pointerProperties,  
  32.                 mCurrentCookedPointerData.pointerCoords,  
  33.                 mCurrentCookedPointerData.idToIndex,  
  34.                 mLastCookedPointerData.pointerProperties,  
  35.                 mLastCookedPointerData.pointerCoords,  
  36.                 mLastCookedPointerData.idToIndex,  
  37.                 moveIdBits);  
  38.         if (buttonState != mLastButtonState) {  
  39.             moveNeeded = true;  
  40.         }  
  41.   
  42.         // Dispatch pointer up events.   
  43.         while (!upIdBits.isEmpty()) {  
  44.             uint32_t upId = upIdBits.clearFirstMarkedBit();  
  45.   
  46.             dispatchMotion(when, policyFlags, mSource,  
  47.                     AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,  
  48.                     mLastCookedPointerData.pointerProperties,  
  49.                     mLastCookedPointerData.pointerCoords,  
  50.                     mLastCookedPointerData.idToIndex,  
  51.                     dispatchedIdBits, upId,  
  52.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  53.             dispatchedIdBits.clearBit(upId);  
  54.         }  
  55.   
  56.         // Dispatch move events if any of the remaining pointers moved from their old locations.  
  57.         // Although applications receive new locations as part of individual pointer up  
  58.         // events, they do not generally handle them except when presented in a move event.  
  59.         if (moveNeeded) {  
  60.             ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);  
  61.             dispatchMotion(when, policyFlags, mSource,  
  62.                     AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,  
  63.                     mCurrentCookedPointerData.pointerProperties,  
  64.                     mCurrentCookedPointerData.pointerCoords,  
  65.                     mCurrentCookedPointerData.idToIndex,  
  66.                     dispatchedIdBits, -1,  
  67.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  68.         }  
  69.   
  70.         // Dispatch pointer down events using the new pointer locations.  
  71.         while (!downIdBits.isEmpty()) {  
  72.             uint32_t downId = downIdBits.clearFirstMarkedBit();  
  73.             dispatchedIdBits.markBit(downId);  
  74.   
  75.             if (dispatchedIdBits.count() == 1) {  
  76.                 // First pointer is going down.  Set down time.  
  77.                 mDownTime = when;  
  78.             }  
  79.   
  80. <SPAN style="COLOR: rgb(255,0,0)">            dispatchMotion(when, policyFlags, mSource,  
  81.                     AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,  
  82.                     mCurrentCookedPointerData.pointerProperties,  
  83.                     mCurrentCookedPointerData.pointerCoords,  
  84.                     mCurrentCookedPointerData.idToIndex,  
  85.                     dispatchedIdBits, downId,  
  86.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);</SPAN>  
  87.         }  
  88.     }  
void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {    BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;    BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;    int32_t metaState = getContext()->getGlobalMetaState();    int32_t buttonState = mCurrentButtonState;    if (currentIdBits == lastIdBits) {        if (!currentIdBits.isEmpty()) {            // No pointer id changes so this is a move event.            // The listener takes care of batching moves so we don't have to deal with that here.            dispatchMotion(when, policyFlags, mSource,                    AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,                    AMOTION_EVENT_EDGE_FLAG_NONE,                    mCurrentCookedPointerData.pointerProperties,                    mCurrentCookedPointerData.pointerCoords,                    mCurrentCookedPointerData.idToIndex,                    currentIdBits, -1,                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);        }    } else {        // There may be pointers going up and pointers going down and pointers moving        // all at the same time.        BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);        BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);        BitSet32 dispatchedIdBits(lastIdBits.value);        // Update last coordinates of pointers that have moved so that we observe the new        // pointer positions at the same time as other pointers that have just gone up.        bool moveNeeded = updateMovedPointers(                mCurrentCookedPointerData.pointerProperties,                mCurrentCookedPointerData.pointerCoords,                mCurrentCookedPointerData.idToIndex,                mLastCookedPointerData.pointerProperties,                mLastCookedPointerData.pointerCoords,                mLastCookedPointerData.idToIndex,                moveIdBits);        if (buttonState != mLastButtonState) {            moveNeeded = true;        }        // Dispatch pointer up events.        while (!upIdBits.isEmpty()) {            uint32_t upId = upIdBits.clearFirstMarkedBit();            dispatchMotion(when, policyFlags, mSource,                    AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,                    mLastCookedPointerData.pointerProperties,                    mLastCookedPointerData.pointerCoords,                    mLastCookedPointerData.idToIndex,                    dispatchedIdBits, upId,                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);            dispatchedIdBits.clearBit(upId);        }        // Dispatch move events if any of the remaining pointers moved from their old locations.        // Although applications receive new locations as part of individual pointer up        // events, they do not generally handle them except when presented in a move event.        if (moveNeeded) {            ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);            dispatchMotion(when, policyFlags, mSource,                    AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,                    mCurrentCookedPointerData.pointerProperties,                    mCurrentCookedPointerData.pointerCoords,                    mCurrentCookedPointerData.idToIndex,                    dispatchedIdBits, -1,                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);        }        // Dispatch pointer down events using the new pointer locations.        while (!downIdBits.isEmpty()) {            uint32_t downId = downIdBits.clearFirstMarkedBit();            dispatchedIdBits.markBit(downId);            if (dispatchedIdBits.count() == 1) {                // First pointer is going down.  Set down time.                mDownTime = when;            }            dispatchMotion(when, policyFlags, mSource,                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,                    mCurrentCookedPointerData.pointerProperties,                    mCurrentCookedPointerData.pointerCoords,                    mCurrentCookedPointerData.idToIndex,                    dispatchedIdBits, downId,                    mOrientedXPrecision, mOrientedYPrecision, mDownTime);        }    }

在dispatchTouches中,主要通过dispatchMotion去回调Listener,

[cpp] view plaincopyprint?
  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]);  
  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.   
  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.         if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {  
  29.             action = AMOTION_EVENT_ACTION_DOWN;  
  30.         } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {  
  31.             action = AMOTION_EVENT_ACTION_UP;  
  32.         } else {  
  33.             // Can't happen.   
  34.             ALOG_ASSERT(false);  
  35.         }  
  36.     }  
  37.   
  38.     NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,  
  39.             action, flags, metaState, buttonState, edgeFlags,  
  40.             pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime);  
  41.     getListener()->notifyMotion(&args);  
void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,        int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,        const PointerProperties* properties, const PointerCoords* coords,        const uint32_t* idToIndex, BitSet32 idBits,        int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {    PointerCoords pointerCoords[MAX_POINTERS];    PointerProperties pointerProperties[MAX_POINTERS];    uint32_t pointerCount = 0;    while (!idBits.isEmpty()) {        uint32_t id = idBits.clearFirstMarkedBit();        uint32_t index = idToIndex[id];        pointerProperties[pointerCount].copyFrom(properties[index]);        pointerCoords[pointerCount].copyFrom(coords[index]);        if (changedId >= 0 && id == uint32_t(changedId)) {            action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;        }        pointerCount += 1;    }    ALOG_ASSERT(pointerCount != 0);    if (changedId >= 0 && pointerCount == 1) {        // Replace initial down and final up action.        // We can compare the action without masking off the changed pointer index        // because we know the index is 0.        if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {            action = AMOTION_EVENT_ACTION_DOWN;        } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {            action = AMOTION_EVENT_ACTION_UP;        } else {            // Can't happen.            ALOG_ASSERT(false);        }    }    NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,            action, flags, metaState, buttonState, edgeFlags,            pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime);    getListener()->notifyMotion(&args);

getListener()返回的实际上就是InputerDipatcher对象,

[cpp] view plaincopyprint?
  1. inline InputListenerInterface* getListener() { return mContext->getListener(); }  
  2. 去直接调用ContextImpl::getListener()   
  3. ......  
  4. InputListenerInterface* InputReader::ContextImpl::getListener() {  
  5.     return mReader->mQueuedListener.get();  
  6. }  
  7. 而mQueuedListener在InputReader的构造中传进来的,这就是InputDispater,我们可以去查看什么时候创建InputReader的,上文也提到过。  
inline InputListenerInterface* getListener() { return mContext->getListener(); }去直接调用ContextImpl::getListener() ......InputListenerInterface* InputReader::ContextImpl::getListener() {    return mReader->mQueuedListener.get();}而mQueuedListener在InputReader的构造中传进来的,这就是InputDispater,我们可以去查看什么时候创建InputReader的,上文也提到过。
[cpp] view plaincopyprint?
  1. ......  
  2. InputReader::InputReader(const sp<EventHubInterface>& eventHub,  
  3.         const sp<InputReaderPolicyInterface>& policy,  
  4.         const sp<InputListenerInterface>& listener) :  
  5.         mContext(this), mEventHub(eventHub), mPolicy(policy),  
  6.         mGlobalMetaState(0), mGeneration(1),  
  7.         mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),  
  8.         mConfigurationChangesToRefresh(0) {  
  9.     mQueuedListener = new QueuedInputListener(listener);  
......InputReader::InputReader(const sp<EventHubInterface>& eventHub,        const sp<InputReaderPolicyInterface>& policy,        const sp<InputListenerInterface>& listener) :        mContext(this), mEventHub(eventHub), mPolicy(policy),        mGlobalMetaState(0), mGeneration(1),        mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),        mConfigurationChangesToRefresh(0) {    mQueuedListener = new QueuedInputListener(listener);

因此我们接着就去看InputDispatcher::notifyMotion

[cpp] view plaincopyprint?
  1. void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {  
  2. #if DEBUG_INBOUND_EVENT_DETAILS   
  3.   
  4.   
  5.     uint32_t policyFlags = args->policyFlags;  
  6.     policyFlags |= POLICY_FLAG_TRUSTED;  
  7. <SPAN style="COLOR: rgb(255,0,0)">    mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);</SPAN>  
  8.   
  9.     bool needWake;  
  10.     { // acquire lock   
  11.         mLock.lock();  
  12.   
  13.         if (mInputFilterEnabled) {  
  14.             mLock.unlock();  
  15.   
  16.             MotionEvent event;  
  17.             event.initialize(args->deviceId, args->source, args->action, args->flags,  
  18.                     args->edgeFlags, args->metaState, args->buttonState, 0, 0,  
  19.                     args->xPrecision, args->yPrecision,  
  20.                     args->downTime, args->eventTime,  
  21.                     args->pointerCount, args->pointerProperties, args->pointerCoords);  
  22.   
  23.             policyFlags |= POLICY_FLAG_FILTERED;  
  24.             if (!<SPAN style="COLOR: rgb(255,0,0)">mPolicy->filterInputEvent(&event, policyFlags)</SPAN>) {  
  25.                 return// event was consumed by the filter  
  26.             }  
  27.   
  28.             mLock.lock();  
  29.         }  
  30.   
  31.         // Just enqueue a new motion event.  
  32.         MotionEntry* newEntry = new MotionEntry(args->eventTime,  
  33.                 args->deviceId, args->source, policyFlags,  
  34.                 args->action, args->flags, args->metaState, args->buttonState,  
  35.                 args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,  
  36.                 args->pointerCount, args->pointerProperties, args->pointerCoords);  
  37.   
  38. <SPAN style="COLOR: rgb(255,0,0)">        needWake = enqueueInboundEventLocked(newEntry);</SPAN>  
  39.         mLock.unlock();  
  40.     } // release lock   
  41.   
  42.     if (needWake) {  
  43.         mLooper->wake();  
  44.     }  
  45. }  
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {#if DEBUG_INBOUND_EVENT_DETAILS    uint32_t policyFlags = args->policyFlags;    policyFlags |= POLICY_FLAG_TRUSTED;    mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);    bool needWake;    { // acquire lock        mLock.lock();        if (mInputFilterEnabled) {            mLock.unlock();            MotionEvent event;            event.initialize(args->deviceId, args->source, args->action, args->flags,                    args->edgeFlags, args->metaState, args->buttonState, 0, 0,                    args->xPrecision, args->yPrecision,                    args->downTime, args->eventTime,                    args->pointerCount, args->pointerProperties, args->pointerCoords);            policyFlags |= POLICY_FLAG_FILTERED;            if (!mPolicy->filterInputEvent(&event, policyFlags)) {                return; // event was consumed by the filter            }            mLock.lock();        }        // Just enqueue a new motion event.        MotionEntry* newEntry = new MotionEntry(args->eventTime,                args->deviceId, args->source, policyFlags,                args->action, args->flags, args->metaState, args->buttonState,                args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,                args->pointerCount, args->pointerProperties, args->pointerCoords);        needWake = enqueueInboundEventLocked(newEntry);        mLock.unlock();    } // release lock    if (needWake) {        mLooper->wake();    }}

   在NotifyMotion中首先回去调用mPolicy->interceptMotionBeforeQueueing 通过查询policy判断此次事件是否要传给User端,如果需要则通过policyFlags |= POLICY_FLAG_PASS_TO_USER;就加个Flag。里面的其他 策略暂时不清楚。这里的mPolicy实际上就是NativeInputManager对象,NativeInputManager继承了InputDispatcherPolicyInterface和InputReaderPolicyInterface。

[cpp] view plaincopyprint?
  1. void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {  
  2. <SPAN style="COLOR: rgb(255,0,0)">    // Policy:  
  3.     // - Ignore untrusted events and pass them along.  
  4.     // - No special filtering for injected events required at this time.  
  5.     // - Filter normal events based on screen state.  
  6.     // - For normal events brighten (but do not wake) the screen if currently dim.</SPAN>  
  7.     if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {  
  8.         if (isScreenOn()) {  
  9.             policyFlags |= POLICY_FLAG_PASS_TO_USER;  
  10.   
  11.             if (!isScreenBright()) {  
  12.                 policyFlags |= POLICY_FLAG_BRIGHT_HERE;  
  13.             }  
  14.         } else {  
  15.             JNIEnv* env = jniEnv();  
  16.             jint wmActions = env->CallIntMethod(mCallbacksObj,  
  17.                         gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,  
  18.                         policyFlags);  
  19.             if (checkAndClearExceptionFromCallback(env,  
  20.                     "interceptMotionBeforeQueueingWhenScreenOff")) {  
  21.                 wmActions = 0;  
  22.             }  
  23.   
  24.             policyFlags |= POLICY_FLAG_WOKE_HERE | POLICY_FLAG_BRIGHT_HERE;  
  25.             handleInterceptActions(wmActions, when, /*byref*/ policyFlags);  
  26.         }  
  27.     } else {  
  28.         policyFlags |= POLICY_FLAG_PASS_TO_USER;  
  29.     }  
  30. }  
void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {    // Policy:    // - Ignore untrusted events and pass them along.    // - No special filtering for injected events required at this time.    // - Filter normal events based on screen state.    // - For normal events brighten (but do not wake) the screen if currently dim.    if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {        if (isScreenOn()) {            policyFlags |= POLICY_FLAG_PASS_TO_USER;            if (!isScreenBright()) {                policyFlags |= POLICY_FLAG_BRIGHT_HERE;            }        } else {            JNIEnv* env = jniEnv();            jint wmActions = env->CallIntMethod(mCallbacksObj,                        gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,                        policyFlags);            if (checkAndClearExceptionFromCallback(env,                    "interceptMotionBeforeQueueingWhenScreenOff")) {                wmActions = 0;            }            policyFlags |= POLICY_FLAG_WOKE_HERE | POLICY_FLAG_BRIGHT_HERE;            handleInterceptActions(wmActions, when, /*byref*/ policyFlags);        }    } else {        policyFlags |= POLICY_FLAG_PASS_TO_USER;    }}
之后就会走到mPolicy->filterInputEvent(&event, policyFlags), 看看此次event要不要呗filter掉,我们这边是MotionEvent,return ture说明不会被filter,所以继续走下去就到
enqueueInboundEventLocked中。

[cpp] view plaincopyprint?
  1. bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {  
  2.     bool needWake = mInboundQueue.isEmpty();  
  3. <SPAN style="COLOR: #ff0000">    mInboundQueue.enqueueAtTail(entry);  
  4.     traceInboundQueueLengthLocked();</SPAN>  
  5.   
  6.     switch (entry->type) {  
  7.     case EventEntry::TYPE_KEY: {  
  8.       ......  
  9.     }  
  10.   
  11.     case EventEntry::TYPE_MOTION: {  
  12.           
  13.         MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);  
  14.         if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN  
  15.                 && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)  
  16.                 && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY  
  17.                 && mInputTargetWaitApplicationHandle != NULL) {  
  18.             int32_t x = int32_t(motionEntry->pointerCoords[0].  
  19.                     getAxisValue(AMOTION_EVENT_AXIS_X));  
  20.             int32_t y = int32_t(motionEntry->pointerCoords[0].  
  21.                     getAxisValue(AMOTION_EVENT_AXIS_Y));  
  22. <SPAN style="COLOR: rgb(255,0,0)">            sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(x, y);</SPAN>  
  23.             if (touchedWindowHandle != NULL  
  24.                     && touchedWindowHandle->inputApplicationHandle  
  25.                             != mInputTargetWaitApplicationHandle) {  
  26.                 // User touched a different application than the one we are waiting on.  
  27.                 // Flag the event, and start pruning the input queue.  
  28. <SPAN style="COLOR: rgb(255,0,0)">                mNextUnblockedEvent = motionEntry;  
  29.                 needWake = true;</SPAN>  
  30.             }  
  31.         }  
  32.         break;  
  33.     }  
  34.     }  
  35.   
  36.     return needWake;  
  37. }  
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {    bool needWake = mInboundQueue.isEmpty();    mInboundQueue.enqueueAtTail(entry);    traceInboundQueueLengthLocked();    switch (entry->type) {    case EventEntry::TYPE_KEY: {      ......    }    case EventEntry::TYPE_MOTION: {                MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);        if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN                && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)                && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY                && mInputTargetWaitApplicationHandle != NULL) {            int32_t x = int32_t(motionEntry->pointerCoords[0].                    getAxisValue(AMOTION_EVENT_AXIS_X));            int32_t y = int32_t(motionEntry->pointerCoords[0].                    getAxisValue(AMOTION_EVENT_AXIS_Y));            sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(x, y);            if (touchedWindowHandle != NULL                    && touchedWindowHandle->inputApplicationHandle                            != mInputTargetWaitApplicationHandle) {                // User touched a different application than the one we are waiting on.                // Flag the event, and start pruning the input queue.                mNextUnblockedEvent = motionEntry;                needWake = true;            }        }        break;    }    }    return needWake;}

 在这个函数中会先把这个Event加到mInboundQueue中,然后去findTouchedWindowAtLock找到我们在Screen上面点击的是哪个Window,如果找到了对象的handle就把mNextUnblockedEvent = motionEntry;  mNextUnblockedEvent 会在InputDispatcher的循环处理中被作为下一个要处理的Event。

之后返回needWake = true 给notifyMotion,就会触发mLooper->wake(); 通过一连串复杂的管道通信,最后会恢复dispatchOnce继续运行


[cpp] view plaincopyprint?
  1. void InputDispatcher::dispatchOnce() {  
  2.     nsecs_t nextWakeupTime = LONG_LONG_MAX;  
  3.     { // acquire lock   
  4.         AutoMutex _l(mLock);  
  5.   <SPAN style="COLOR: rgb(255,0,0)">      dispatchOnceInnerLocked(&nextWakeupTime);</SPAN>  
  6.   
  7.         if (runCommandsLockedInterruptible()) {  
  8.             nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately  
  9.         }  
  10.     } // release lock   
  11.   
  12.     // Wait for callback or timeout or wake.  (make sure we round up, not down)  
  13.     nsecs_t currentTime = now();  
  14.     int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);  
  15.     <SPAN style="COLOR: rgb(255,0,0)">mLooper->pollOnce(timeoutMillis);</SPAN>  
  16. }  
void InputDispatcher::dispatchOnce() {    nsecs_t nextWakeupTime = LONG_LONG_MAX;    { // acquire lock        AutoMutex _l(mLock);        dispatchOnceInnerLocked(&nextWakeupTime);        if (runCommandsLockedInterruptible()) {            nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately        }    } // release lock    // Wait for callback or timeout or wake.  (make sure we round up, not down)    nsecs_t currentTime = now();    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);    mLooper->pollOnce(timeoutMillis);}

dispatchOnce()也是直接调用dispatchOnceInnerLocked去完成具体的事物。


[cpp] view plaincopyprint?
  1. void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {  
  2.     nsecs_t currentTime = now();  
  3.   
  4.     // Optimize latency of app switches.   
  5.     // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has  
  6.     // been pressed.  When it expires, we preempt dispatch and drop all other pending events.  
  7.     bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;  
  8.     if (mAppSwitchDueTime < *nextWakeupTime) {  
  9.         *nextWakeupTime = mAppSwitchDueTime;  
  10.     }  
  11.   
  12.     // Ready to start a new event.   
  13.     // If we don't already have a pending event, go grab one.  
  14.     if (! mPendingEvent) {  
  15.         if (mInboundQueue.isEmpty()) {  
  16.             if (isAppSwitchDue) {  
  17.                 // The inbound queue is empty so the app switch key we were waiting  
  18.                 // for will never arrive.  Stop waiting for it.  
  19.                 resetPendingAppSwitchLocked(false);  
  20.                 isAppSwitchDue = false;  
  21.             }  
  22.   
  23.             // Synthesize a key repeat if appropriate.  
  24.             if (mKeyRepeatState.lastKeyEntry) {  
  25.                 if (currentTime >= mKeyRepeatState.nextRepeatTime) {  
  26.                     mPendingEvent = synthesizeKeyRepeatLocked(currentTime);  
  27.                 } else {  
  28.                     if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {  
  29.                         *nextWakeupTime = mKeyRepeatState.nextRepeatTime;  
  30.                     }  
  31.                 }  
  32.             }  
  33.   
  34.             // Nothing to do if there is no pending event.  
  35.             if (!mPendingEvent) {  
  36.                 return;  
  37.             }  
  38.         } else {  
  39.             // Inbound queue has at least one entry.  
  40. <SPAN style="COLOR: #ff0000">            mPendingEvent = mInboundQueue.dequeueAtHead();  
  41.             traceInboundQueueLengthLocked();</SPAN>  
  42.         }  
  43.   
  44.         // Poke user activity for this event.  
  45.         if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {  
  46.             pokeUserActivityLocked(mPendingEvent);  
  47.         }  
  48.   
  49.         // Get ready to dispatch the event.  
  50.         resetANRTimeoutsLocked();  
  51.     }  
  52.   
  53.     // Now we have an event to dispatch.  
  54.     // All events are eventually dequeued and processed this way, even if we intend to drop them.  
  55.   
  56.   
  57.     switch (mPendingEvent->type) {  
  58.     case EventEntry::TYPE_CONFIGURATION_CHANGED: {  
  59.       .......  
  60.     }  
  61.   
  62.     case EventEntry::TYPE_DEVICE_RESET: {  
  63.       ......  
  64.     }  
  65.   
  66.     case EventEntry::TYPE_KEY: {  
  67.       .......  
  68.     }  
  69.   
  70.     case EventEntry::TYPE_MOTION: {  
  71.         MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);  
  72.         if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {  
  73.             dropReason = DROP_REASON_APP_SWITCH;  
  74.         }  
  75.         if (dropReason == DROP_REASON_NOT_DROPPED  
  76.                 && isStaleEventLocked(currentTime, typedEntry)) {  
  77.             dropReason = DROP_REASON_STALE;  
  78.         }  
  79.         if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {  
  80.             dropReason = DROP_REASON_BLOCKED;  
  81.         }  
  82. <SPAN style="COLOR: #ff0000">        done = dispatchMotionLocked(currentTime, typedEntry,  
  83.                 &dropReason, nextWakeupTime);</SPAN>  
  84.         break;  
  85.     }  
  86.   
  87.     if (done) {  
  88.         if (dropReason != DROP_REASON_NOT_DROPPED) {  
  89.             dropInboundEventLocked(mPendingEvent, dropReason);  
  90.         }  
  91.   
  92.         releasePendingEventLocked();  
  93.         *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately  
  94.     }  
  95. }  
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {    nsecs_t currentTime = now();    // Optimize latency of app switches.    // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has    // been pressed.  When it expires, we preempt dispatch and drop all other pending events.    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;    if (mAppSwitchDueTime < *nextWakeupTime) {        *nextWakeupTime = mAppSwitchDueTime;    }    // Ready to start a new event.    // If we don't already have a pending event, go grab one.    if (! mPendingEvent) {        if (mInboundQueue.isEmpty()) {            if (isAppSwitchDue) {                // The inbound queue is empty so the app switch key we were waiting                // for will never arrive.  Stop waiting for it.                resetPendingAppSwitchLocked(false);                isAppSwitchDue = false;            }            // Synthesize a key repeat if appropriate.            if (mKeyRepeatState.lastKeyEntry) {                if (currentTime >= mKeyRepeatState.nextRepeatTime) {                    mPendingEvent = synthesizeKeyRepeatLocked(currentTime);                } else {                    if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {                        *nextWakeupTime = mKeyRepeatState.nextRepeatTime;                    }                }            }            // Nothing to do if there is no pending event.            if (!mPendingEvent) {                return;            }        } else {            // Inbound queue has at least one entry.            mPendingEvent = mInboundQueue.dequeueAtHead();            traceInboundQueueLengthLocked();        }        // Poke user activity for this event.        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {            pokeUserActivityLocked(mPendingEvent);        }        // Get ready to dispatch the event.        resetANRTimeoutsLocked();    }    // Now we have an event to dispatch.    // All events are eventually dequeued and processed this way, even if we intend to drop them.    switch (mPendingEvent->type) {    case EventEntry::TYPE_CONFIGURATION_CHANGED: {      .......    }    case EventEntry::TYPE_DEVICE_RESET: {      ......    }    case EventEntry::TYPE_KEY: {      .......    }    case EventEntry::TYPE_MOTION: {        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {            dropReason = DROP_REASON_APP_SWITCH;        }        if (dropReason == DROP_REASON_NOT_DROPPED                && isStaleEventLocked(currentTime, typedEntry)) {            dropReason = DROP_REASON_STALE;        }        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {            dropReason = DROP_REASON_BLOCKED;        }        done = dispatchMotionLocked(currentTime, typedEntry,                &dropReason, nextWakeupTime);        break;    }    if (done) {        if (dropReason != DROP_REASON_NOT_DROPPED) {            dropInboundEventLocked(mPendingEvent, dropReason);        }        releasePendingEventLocked();        *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately    }}
这个函数中,先通过mPendingEvent = mInboundQueue.dequeueAtHead();去取得当前InboundQueue的Head event付给mPengdingEvent. 然后根据mPendingEvent->type的类型去判断Event的类型,我们这边是TYPE_MOTION, 之后就调用对应的dispatch函数。


[cpp] view plaincopyprint?
  1. bool InputDispatcher::dispatchMotionLocked(  
  2.         nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {  
  3.   
  4.     // Clean up if dropping the event.   
  5.     if (*dropReason != DROP_REASON_NOT_DROPPED) {  
  6.         setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY  
  7.                 ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);  
  8.         return true;  
  9.     }  
  10.   
  11.     bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;  
  12.   
  13.     // Identify targets.   
  14.     Vector<InputTarget> inputTargets;  
  15.   
  16.     bool conflictingPointerActions = false;  
  17.     int32_t injectionResult;  
  18.     if (isPointerEvent) {  
  19. <SPAN style="COLOR: #ff0000">        // Pointer event.  (eg. touchscreen)  
  20.         injectionResult = findTouchedWindowTargetsLocked(currentTime,  
  21.                 entry, inputTargets, nextWakeupTime, &conflictingPointerActions);</SPAN>  
  22.     } else {  
  23.         // Non touch event.  (eg. trackball)  
  24.          ......  
  25.     }  
  26.   
  27.     ALOGD("injectionResult = %d !!!!!!!!!!!!!!!!!", injectionResult);  
  28.     if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {  
  29.         return false;  
  30.     }  
  31.   
  32. <SPAN style="COLOR: #ff0000">    setInjectionResultLocked(entry, injectionResult);  
  33.     if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {  
  34.         return true;  
  35.     }</SPAN>  
  36.   
  37. <SPAN style="COLOR: #ff0000">    addMonitoringTargetsLocked(inputTargets);</SPAN>  
  38.   
  39.     // Dispatch the motion.   
  40.     if (conflictingPointerActions) {  
  41.         CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,  
  42.                 "conflicting pointer actions");  
  43.         synthesizeCancelationEventsForAllConnectionsLocked(options);  
  44.     }  
  45.     dispatchEventLocked(currentTime, entry, inputTargets);  
  46.     return true;  
  47. }  
bool InputDispatcher::dispatchMotionLocked(        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {    // Clean up if dropping the event.    if (*dropReason != DROP_REASON_NOT_DROPPED) {        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);        return true;    }    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;    // Identify targets.    Vector<InputTarget> inputTargets;    bool conflictingPointerActions = false;    int32_t injectionResult;    if (isPointerEvent) {        // Pointer event.  (eg. touchscreen)        injectionResult = findTouchedWindowTargetsLocked(currentTime,                entry, inputTargets, nextWakeupTime, &conflictingPointerActions);    } else {        // Non touch event.  (eg. trackball)         ......    }    ALOGD("injectionResult = %d !!!!!!!!!!!!!!!!!", injectionResult);    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {        return false;    }    setInjectionResultLocked(entry, injectionResult);    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {        return true;    }    addMonitoringTargetsLocked(inputTargets);    // Dispatch the motion.    if (conflictingPointerActions) {        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,                "conflicting pointer actions");        synthesizeCancelationEventsForAllConnectionsLocked(options);    }    dispatchEventLocked(currentTime, entry, inputTargets);    return true;}


[cpp] view plaincopyprint?
  1. int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,  
  2.         const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,  
  3.         bool* outConflictingPointerActions) {  
  4.     enum InjectionPermission {  
  5.         INJECTION_PERMISSION_UNKNOWN,  
  6.         INJECTION_PERMISSION_GRANTED,  
  7.         INJECTION_PERMISSION_DENIED  
  8.     };  
  9.   
  10.     nsecs_t startTime = now();  
  11.     .......  
  12.     // Success!  Output targets.   
  13.     injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;  
  14.   
  15.     for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {  
  16.         const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);  
  17.         addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,  
  18.                 touchedWindow.pointerIds, inputTargets);  
  19.     }  
  20.   
  21.     // Drop the outside or hover touch windows since we will not care about them  
  22.     // in the next iteration.   
  23.     mTempTouchState.filterNonAsIsTouchWindows();  
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,        const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,        bool* outConflictingPointerActions) {    enum InjectionPermission {        INJECTION_PERMISSION_UNKNOWN,        INJECTION_PERMISSION_GRANTED,        INJECTION_PERMISSION_DENIED    };    nsecs_t startTime = now();    .......    // Success!  Output targets.    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {        const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,                touchedWindow.pointerIds, inputTargets);    }    // Drop the outside or hover touch windows since we will not care about them    // in the next iteration.    mTempTouchState.filterNonAsIsTouchWindows();


    addWindowTargetLocked 将找到的找到的Window放到InputTargets中,在后面dispatchEvent的时候会从InputTargets中去查找。

[cpp] view plaincopyprint?
  1. void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,  
  2.         int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) {  
  3.     inputTargets.push();  
  4.   
  5.     const InputWindowInfo* windowInfo = windowHandle->getInfo();  
  6.     InputTarget& target = inputTargets.editTop();  
  7.     target.inputChannel = windowInfo->inputChannel;  
  8.     target.flags = targetFlags;  
  9.     target.xOffset = - windowInfo->frameLeft;  
  10.     target.yOffset = - windowInfo->frameTop;  
  11.     target.scaleFactor = windowInfo->scaleFactor;  
  12.     target.pointerIds = pointerIds;  
  13. }  
void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,        int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) {    inputTargets.push();    const InputWindowInfo* windowInfo = windowHandle->getInfo();    InputTarget& target = inputTargets.editTop();    target.inputChannel = windowInfo->inputChannel;    target.flags = targetFlags;    target.xOffset = - windowInfo->frameLeft;    target.yOffset = - windowInfo->frameTop;    target.scaleFactor = windowInfo->scaleFactor;    target.pointerIds = pointerIds;}


[cpp] view plaincopyprint?
  1. void InputDispatcher::addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets) {  
  2.     for (size_t i = 0; i < mMonitoringChannels.size(); i++) {  
  3.         inputTargets.push();  
  4.   
  5.         InputTarget& target = inputTargets.editTop();  
  6.         target.inputChannel = mMonitoringChannels[i];  
  7.         target.flags = InputTarget::FLAG_DISPATCH_AS_IS;  
  8.         target.xOffset = 0;  
  9.         target.yOffset = 0;  
  10.         target.pointerIds.clear();  
  11.         target.scaleFactor = 1.0f;  
  12.     }  
  13. }  
void InputDispatcher::addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets) {    for (size_t i = 0; i < mMonitoringChannels.size(); i++) {        inputTargets.push();        InputTarget& target = inputTargets.editTop();        target.inputChannel = mMonitoringChannels[i];        target.flags = InputTarget::FLAG_DISPATCH_AS_IS;        target.xOffset = 0;        target.yOffset = 0;        target.pointerIds.clear();        target.scaleFactor = 1.0f;    }}


[cpp] view plaincopyprint?
  1. void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,  
  2.         EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {  
  3. #if DEBUG_DISPATCH_CYCLE   
  4.     ALOGD("dispatchEventToCurrentInputTargets");  
  5. #endif   
  6.   
  7.     ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true  
  8.   
  9.     pokeUserActivityLocked(eventEntry);  
  10.   
  11.     for (size_t i = 0; i < inputTargets.size(); i++) {  
  12.         const InputTarget& inputTarget = inputTargets.itemAt(i);  
  13.   
  14.         ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);  
  15.         if (connectionIndex >= 0) {  
  16.             sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);  
  17. <SPAN style="COLOR: #ff0000">            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);</SPAN>  
  18.         } else {  
  19. #if DEBUG_FOCUS   
  20.             ALOGD("Dropping event delivery to target with channel '%s' because it "  
  21.                     "is no longer registered with the input dispatcher.",  
  22.                     inputTarget.inputChannel->getName().string());  
  23. #endif   
  24.         }  
  25.     }  
  26. }  
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,        EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {#if DEBUG_DISPATCH_CYCLE    ALOGD("dispatchEventToCurrentInputTargets");#endif    ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true    pokeUserActivityLocked(eventEntry);    for (size_t i = 0; i < inputTargets.size(); i++) {        const InputTarget& inputTarget = inputTargets.itemAt(i);        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);        if (connectionIndex >= 0) {            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);        } else {#if DEBUG_FOCUS            ALOGD("Dropping event delivery to target with channel '%s' because it "                    "is no longer registered with the input dispatcher.",                    inputTarget.inputChannel->getName().string());#endif        }    }}

这个函数的实现也比较简单,前面我们已经把当前需要接受键盘事件的Activity窗口添加到mCurrentInputTargets中去了,因此,这里就分别把它们取出来,然后调用prepareDispatchCycleLocked函数把键盘事件分发给它们处理。

        关于InputChannel和Connection之间的关系,我转了老罗博客中的一段话:前面我们在分析应用程序注册键盘消息接收通道的过程时,在Step 18中(InputDispatcher.registerInputChannel),把Server端的InputChannel封装成了一个Connection,然后以这个InputChannel中的Receive Pipe Fd作为键值把这个Connection对象保存在mConnectionsByReceiveFd中。这里,既然我们已经通过mCurrentInputTargets得到了表示当前需要接收键盘事件的Activity窗口的InputTarget对象,而且这个InputTarget对象的inputChannel就表示当初在InputDispatcher中注册的Server端InputChannel,因此,这里就可以把这个Connection对象取出来,最后调用prepareDispatchCycleLocked函数来进一步处理。


[cpp] view plaincopyprint?
  1. void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,  
  2.         const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {  
  3.   
  4.     // Skip this event if the connection status is not normal.  
  5.     // We don't want to enqueue additional outbound events if the connection is broken.  
  6.     if (connection->status != Connection::STATUS_NORMAL) {  
  7.         return;  
  8.     }  
  9.   
  10.     // Split a motion event if needed.   
  11.     if (inputTarget->flags & InputTarget::FLAG_SPLIT) {  
  12.         ALOG_ASSERT(eventEntry->type == EventEntry::TYPE_MOTION);  
  13.   
  14.         MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);  
  15.         if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {  
  16.             MotionEntry* splitMotionEntry = splitMotionEvent(  
  17.                     originalMotionEntry, inputTarget->pointerIds);  
  18.             if (!splitMotionEntry) {  
  19.                 return// split event was dropped  
  20.             }  
  21. <SPAN style="COLOR: #ff0000">  
  22.             enqueueDispatchEntriesLocked(currentTime, connection,  
  23.                     splitMotionEntry, inputTarget);</SPAN>  
  24.             splitMotionEntry->release();  
  25.             return;  
  26.         }  
  27.     }  
  28.   
  29.     // Not splitting.  Enqueue dispatch entries for the event as is.  
  30. <SPAN style="COLOR: #ff0000">    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);</SPAN>  
  31. }  
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {    // Skip this event if the connection status is not normal.    // We don't want to enqueue additional outbound events if the connection is broken.    if (connection->status != Connection::STATUS_NORMAL) {        return;    }    // Split a motion event if needed.    if (inputTarget->flags & InputTarget::FLAG_SPLIT) {        ALOG_ASSERT(eventEntry->type == EventEntry::TYPE_MOTION);        MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);        if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {            MotionEntry* splitMotionEntry = splitMotionEvent(                    originalMotionEntry, inputTarget->pointerIds);            if (!splitMotionEntry) {                return; // split event was dropped            }            enqueueDispatchEntriesLocked(currentTime, connection,                    splitMotionEntry, inputTarget);            splitMotionEntry->release();            return;        }    }    // Not splitting.  Enqueue dispatch entries for the event as is.    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);}


[cpp] view plaincopyprint?
  1. void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,  
  2.         const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {  
  3.     bool wasEmpty = connection->outboundQueue.isEmpty();  
  4.   
  5.     // Enqueue dispatch entries for the requested modes.  
  6.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  7.             InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);  
  8.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  9.             InputTarget::FLAG_DISPATCH_AS_OUTSIDE);  
  10.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  11.             InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);  
  12.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  13.             InputTarget::FLAG_DISPATCH_AS_IS);  
  14.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  15.             InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);  
  16.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  17.             InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);  
  18.   
  19.     // If the outbound queue was previously empty, start the dispatch cycle going.  
  20.     if (wasEmpty && !connection->outboundQueue.isEmpty()) {  
  21.         <SPAN style="COLOR: #ff0000">startDispatchCycleLocked(currentTime, connection);</SPAN>  
  22.     }  
  23. }  
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {    bool wasEmpty = connection->outboundQueue.isEmpty();    // Enqueue dispatch entries for the requested modes.    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_OUTSIDE);    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_IS);    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,            InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);    // If the outbound queue was previously empty, start the dispatch cycle going.    if (wasEmpty && !connection->outboundQueue.isEmpty()) {        startDispatchCycleLocked(currentTime, connection);    }}


在开始处理Touch事件之前,这个函数会检查一下传进来的参数connection中的outboundQueue事件队列是否为空,如果不为空,就要看看当前要处理的事件和outboundQueue队列中的最后一个事件是不是同一个motion事件,如果是的话,并且从上面传进来的resumeWithAppendedMotionSample参数为true,这时候就要以流水线的方式来处理这些motion事件了。

         接下来,就会把当前的键盘事件封装成一个DispatchEntry对象,然后添加到connection对象的outboundQueue队列中去,表示当前键盘事件是一个待处理的键盘事件。    

         当connection中的outboundQueue事件队列不为空,即wasEmpty为false时,说明当前这个Activity窗口正在处键盘事件了,因此,就不需要调用startDispatchCycleLocked来启动Activity窗口来处理这个事件了,因为一旦这个Activity窗口正在处键盘事件,它就会一直处理下去,直到它里的connection对象的outboundQueue为空为止。当connection中的outboundQueue事件队列为空时,就需要调用startDispatchCycleLocked来通知这个Activity窗口来执行键盘事件处理的流程了。

[cpp] view plaincopyprint?
  1. void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,  
  2.         const sp<Connection>& connection) {  
  3. #if DEBUG_DISPATCH_CYCLE   
  4.     ALOGD("channel '%s' ~ startDispatchCycle",  
  5.             connection->getInputChannelName());  
  6. #endif   
  7.   
  8.     while (connection->status == Connection::STATUS_NORMAL  
  9.             && !connection->outboundQueue.isEmpty()) {  
  10.         DispatchEntry* dispatchEntry = connection->outboundQueue.head;  
  11.         dispatchEntry->deliveryTime = currentTime;  
  12.   
  13.         // Publish the event.   
  14.         status_t status;  
  15.         EventEntry* eventEntry = dispatchEntry->eventEntry;  
  16.         switch (eventEntry->type) {  
  17.         case EventEntry::TYPE_KEY: {  
  18.          .......  
  19.         }  
  20.   
  21.         case EventEntry::TYPE_MOTION: {  
  22.             MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);  
  23.   
  24.             PointerCoords scaledCoords[MAX_POINTERS];  
  25.             const PointerCoords* usingCoords = motionEntry->pointerCoords;  
  26.   
  27.             // Set the X and Y offset depending on the input source.  
  28.             float xOffset, yOffset, scaleFactor;  
  29.             if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)  
  30.                     && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {  
  31.                 scaleFactor = dispatchEntry->scaleFactor;  
  32.                 xOffset = dispatchEntry->xOffset * scaleFactor;  
  33.                 yOffset = dispatchEntry->yOffset * scaleFactor;  
  34.                 if (scaleFactor != 1.0f) {  
  35.                     for (size_t i = 0; i < motionEntry->pointerCount; i++) {  
  36.                         scaledCoords[i] = motionEntry->pointerCoords[i];  
  37.                         scaledCoords[i].scale(scaleFactor);  
  38.                     }  
  39.                     usingCoords = scaledCoords;  
  40.                 }  
  41.             } else {  
  42.                 xOffset = 0.0f;  
  43.                 yOffset = 0.0f;  
  44.                 scaleFactor = 1.0f;  
  45.   
  46.                 // We don't want the dispatch target to know.  
  47.                 if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {  
  48.                     for (size_t i = 0; i < motionEntry->pointerCount; i++) {  
  49.                         scaledCoords[i].clear();  
  50.                     }  
  51.                     usingCoords = scaledCoords;  
  52.                 }  
  53.             }  
  54.   
  55.             // Publish the motion event.  
  56. <SPAN style="COLOR: #ff0000">            status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,  
  57.                     motionEntry->deviceId, motionEntry->source,  
  58.                     dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,  
  59.                     motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,  
  60.                     xOffset, yOffset,  
  61.                     motionEntry->xPrecision, motionEntry->yPrecision,  
  62.                     motionEntry->downTime, motionEntry->eventTime,  
  63.                     motionEntry->pointerCount, motionEntry->pointerProperties,  
  64.                     usingCoords);</SPAN>  
  65.             break;  
  66.         }  
  67.           ......  
  68.         }  
  69.   
  70.         // Check the result.   
  71.         if (status) {  
  72.             if (status == WOULD_BLOCK) {  
  73.                 if (connection->waitQueue.isEmpty()) {  
  74.                     ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "  
  75.                             "This is unexpected because the wait queue is empty, so the pipe "  
  76.                             "should be empty and we shouldn't have any problems writing an "  
  77.                             "event to it, status=%d", connection->getInputChannelName(), status);  
  78.                     abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);  
  79.                 } else {  
  80.                     // Pipe is full and we are waiting for the app to finish process some events  
  81.                     // before sending more events to it.  
  82. #if DEBUG_DISPATCH_CYCLE   
  83.                     ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "  
  84.                             "waiting for the application to catch up",  
  85.                             connection->getInputChannelName());  
  86. #endif   
  87.                     connection->inputPublisherBlocked = true;  
  88.                 }  
  89.             } else {  
  90.                 ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "  
  91.                         "status=%d", connection->getInputChannelName(), status);  
  92.                 abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);  
  93.             }  
  94.             return;  
  95.         }  
  96.   
  97.         // Re-enqueue the event on the wait queue.  
  98.         connection->outboundQueue.dequeue(dispatchEntry);  
  99.         traceOutboundQueueLengthLocked(connection);  
  100.         connection->waitQueue.enqueueAtTail(dispatchEntry);  
  101.         traceWaitQueueLengthLocked(connection);  
  102.     }  
  103. }  
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,        const sp<Connection>& connection) {#if DEBUG_DISPATCH_CYCLE    ALOGD("channel '%s' ~ startDispatchCycle",            connection->getInputChannelName());#endif    while (connection->status == Connection::STATUS_NORMAL            && !connection->outboundQueue.isEmpty()) {        DispatchEntry* dispatchEntry = connection->outboundQueue.head;        dispatchEntry->deliveryTime = currentTime;        // Publish the event.        status_t status;        EventEntry* eventEntry = dispatchEntry->eventEntry;        switch (eventEntry->type) {        case EventEntry::TYPE_KEY: {         .......        }        case EventEntry::TYPE_MOTION: {            MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);            PointerCoords scaledCoords[MAX_POINTERS];            const PointerCoords* usingCoords = motionEntry->pointerCoords;            // Set the X and Y offset depending on the input source.            float xOffset, yOffset, scaleFactor;            if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)                    && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {                scaleFactor = dispatchEntry->scaleFactor;                xOffset = dispatchEntry->xOffset * scaleFactor;                yOffset = dispatchEntry->yOffset * scaleFactor;                if (scaleFactor != 1.0f) {                    for (size_t i = 0; i < motionEntry->pointerCount; i++) {                        scaledCoords[i] = motionEntry->pointerCoords[i];                        scaledCoords[i].scale(scaleFactor);                    }                    usingCoords = scaledCoords;                }            } else {                xOffset = 0.0f;                yOffset = 0.0f;                scaleFactor = 1.0f;                // We don't want the dispatch target to know.                if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {                    for (size_t i = 0; i < motionEntry->pointerCount; i++) {                        scaledCoords[i].clear();                    }                    usingCoords = scaledCoords;                }            }            // Publish the motion event.            status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,                    motionEntry->deviceId, motionEntry->source,                    dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,                    motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,                    xOffset, yOffset,                    motionEntry->xPrecision, motionEntry->yPrecision,                    motionEntry->downTime, motionEntry->eventTime,                    motionEntry->pointerCount, motionEntry->pointerProperties,                    usingCoords);            break;        }          ......        }        // Check the result.        if (status) {            if (status == WOULD_BLOCK) {                if (connection->waitQueue.isEmpty()) {                    ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "                            "This is unexpected because the wait queue is empty, so the pipe "                            "should be empty and we shouldn't have any problems writing an "                            "event to it, status=%d", connection->getInputChannelName(), status);                    abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);                } else {                    // Pipe is full and we are waiting for the app to finish process some events                    // before sending more events to it.#if DEBUG_DISPATCH_CYCLE                    ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "                            "waiting for the application to catch up",                            connection->getInputChannelName());#endif                    connection->inputPublisherBlocked = true;                }            } else {                ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "                        "status=%d", connection->getInputChannelName(), status);                abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);            }            return;        }        // Re-enqueue the event on the wait queue.        connection->outboundQueue.dequeue(dispatchEntry);        traceOutboundQueueLengthLocked(connection);        connection->waitQueue.enqueueAtTail(dispatchEntry);        traceWaitQueueLengthLocked(connection);    }}

转自老罗的博客: 这个函数主要围绕传进来的Connection对象做两件事情,一是从它的outboundQueue队列中取出当前需要处理的键盘事件,然后把这个事件记录在它的内部对象inputPublisher中,二是通过它的内部对象inputPublisher通知它所关联的Activity窗口,现在有键盘事件需要处理了。第一件事情是通过调用它的InputPublisher对象的publishKeyEvent函数来完成的,而第二件事情是通过调用它的InputPublisher对象的sendDispatchSignal来完成的。我们先来看InputPublisher的成员函数publishKeyEvent的实现,然后再回来分析它的另外一个成员函数sendDispatchSignal的实现。

      这里所谓的发送信号通知,其实是通过向其内部一个管道的写端写入一个字符来实现的。前面我们分析应用程序注册键盘消息接收通道的过程时,在Step 21中(NativeInputQueue.registerInputChannel),它把一个InputChannel注册到应用程序主线程中的Looper对象中,然后应用程序的主线程就通过这个Looper对象睡眠等待在这个InputChannel中的前向管道中有新的内容可读了,这里的mSendPipeFd就是对应这个前向管道的写端。现在既然向这个前向管道的写端写入新的内容了,于是,应用程序的主线程就被唤醒了。

   InputPublisher 和 InputConsumer都在InputTransport.cpp中,在connection类中就有一个InputPublisher类型的变量。一个用于发布,一个用于接收。

[cpp] view plaincopyprint?
  1. <SPAN style="COLOR: #333333">int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {  
  2.     if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {  
  3.         ALOGE("channel '%s' ~ Publisher closed input channel or an error occurred.  "  
  4.                 "events=0x%x", getInputChannelName(), events);  
  5.         return 0; // remove the callback  
  6.     }  
  7.   
  8.     if (!(events & ALOOPER_EVENT_INPUT)) {  
  9.         ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "  
  10.                 "events=0x%x", getInputChannelName(), events);  
  11.         return 1;  
  12.     }  
  13.   
  14.     JNIEnv* env = AndroidRuntime::getJNIEnv();  
  15. </SPAN><SPAN style="COLOR: #ff0000">    status_t status = consumeEvents(env, false /*consumeBatches*/, -1);</SPAN><SPAN style="COLOR: #333333">  
  16.     mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");  
  17.     return status == OK || status == NO_MEMORY ? 1 : 0;  
  18. }  
  19. </SPAN>  
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {        ALOGE("channel '%s' ~ Publisher closed input channel or an error occurred.  "                "events=0x%x", getInputChannelName(), events);        return 0; // remove the callback    }    if (!(events & ALOOPER_EVENT_INPUT)) {        ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "                "events=0x%x", getInputChannelName(), events);        return 1;    }    JNIEnv* env = AndroidRuntime::getJNIEnv();    status_t status = consumeEvents(env, false /*consumeBatches*/, -1);    mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");    return status == OK || status == NO_MEMORY ? 1 : 0;}



[cpp] view plaincopyprint?
  1. status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,  
  2.         bool consumeBatches, nsecs_t frameTime) {  
  3.   
  4.     bool skipCallbacks = false;  
  5.     for (;;) {  
  6.         uint32_t seq;  
  7.         InputEvent* inputEvent;  
  8. <SPAN style="COLOR: #ff0000">        status_t status = mInputConsumer.consume(&mInputEventFactory,  
  9.                 consumeBatches, frameTime, &seq, &inputEvent);</SPAN>  
  10.         if (status) {  
  11.             if (status == WOULD_BLOCK) {  
  12.                 if (!skipCallbacks && !mBatchedInputEventPending  
  13.                         && mInputConsumer.hasPendingBatch()) {  
  14.                     // There is a pending batch.  Come back later.  
  15.                     mBatchedInputEventPending = true;  
  16.                     env->CallVoidMethod(mReceiverObjGlobal,  
  17.                             gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);  
  18.                 }  
  19.                 return OK;  
  20.             }  
  21.             return status;  
  22.         }  
  23.   
  24.         if (!skipCallbacks) {  
  25.             jobject inputEventObj;  
  26.             switch (inputEvent->getType()) {  
  27.             case AINPUT_EVENT_TYPE_KEY:  
  28.   
  29.             case AINPUT_EVENT_TYPE_MOTION:  
  30. #if DEBUG_DISPATCH_CYCLE   
  31.                 ALOGD("channel '%s' ~ Received motion event.", getInputChannelName());  
  32. #endif   
  33. <SPAN style="COLOR: #ff0000">                inputEventObj = android_view_MotionEvent_obtainAsCopy(env,  
  34.                         static_cast<MotionEvent*>(inputEvent));</SPAN>  
  35.                 break;  
  36.             }  
  37.             if (inputEventObj) {  
  38. <SPAN style="COLOR: #ff0000">                env->CallVoidMethod(mReceiverObjGlobal,  
  39.                         gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);</SPAN>  
  40.             } else {  
  41.             <SPAN style="FONT-FAMILY: Arial">}</SPAN>  
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,        bool consumeBatches, nsecs_t frameTime) {    bool skipCallbacks = false;    for (;;) {        uint32_t seq;        InputEvent* inputEvent;        status_t status = mInputConsumer.consume(&mInputEventFactory,                consumeBatches, frameTime, &seq, &inputEvent);        if (status) {            if (status == WOULD_BLOCK) {                if (!skipCallbacks && !mBatchedInputEventPending                        && mInputConsumer.hasPendingBatch()) {                    // There is a pending batch.  Come back later.                    mBatchedInputEventPending = true;                    env->CallVoidMethod(mReceiverObjGlobal,                            gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);                }                return OK;            }            return status;        }        if (!skipCallbacks) {            jobject inputEventObj;            switch (inputEvent->getType()) {            case AINPUT_EVENT_TYPE_KEY:            case AINPUT_EVENT_TYPE_MOTION:#if DEBUG_DISPATCH_CYCLE                ALOGD("channel '%s' ~ Received motion event.", getInputChannelName());#endif                inputEventObj = android_view_MotionEvent_obtainAsCopy(env,                        static_cast<MotionEvent*>(inputEvent));                break;            }            if (inputEventObj) {                env->CallVoidMethod(mReceiverObjGlobal,                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);            } else {            }


最后通过一个JNI转到调用InputEventReceiver.dispatchInputEvent 

[cpp] view plaincopyprint?
  1. // Called from native code.   
  2.    @SuppressWarnings("unused")  
  3.    private void dispatchInputEvent(int seq, InputEvent event) {  
  4.        mSeqMap.put(event.getSequenceNumber(), seq);  
  5.        onInputEvent(event);  
  6.    }  
 // Called from native code.    @SuppressWarnings("unused")    private void dispatchInputEvent(int seq, InputEvent event) {        mSeqMap.put(event.getSequenceNumber(), seq);        onInputEvent(event);    }

WindowInputEventReceiver继承自InputEventReceiver,onInputEvent实际上就是在 WindowInputEventReceiver中进行调用, WindowInputEventReceiver在ViewRootImpl中。


[cpp] view plaincopyprint?
  1. void enqueueInputEvent(InputEvent event,  
  2.         InputEventReceiver receiver, int flags, boolean processImmediately) {  
  3.     QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);  
  4.   
  5.     // Always enqueue the input event in order, regardless of its time stamp.  
  6.     // We do this because the application or the IME may inject key events  
  7.     // in response to touch events and we want to ensure that the injected keys  
  8.     // are processed in the order they were received and we cannot trust that  
  9.     // the time stamp of injected events are monotonic.  
  10.     QueuedInputEvent last = mFirstPendingInputEvent;  
  11.     if (last == null) {  
  12.         mFirstPendingInputEvent = q;  
  13.     } else {  
  14.         while (last.mNext != null) {  
  15.             last = last.mNext;  
  16.         }  
  17.         last.mNext = q;  
  18.     }  
  19.   
  20. N style="COLOR: #ff0000">        if (processImmediately) {  
  21.         doProcessInputEvents();  
  22.     } else {  
  23.         scheduleProcessInputEvents();  
  24.     }</SPAN>  
  25. }  
    void enqueueInputEvent(InputEvent event,            InputEventReceiver receiver, int flags, boolean processImmediately) {        QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);        // Always enqueue the input event in order, regardless of its time stamp.        // We do this because the application or the IME may inject key events        // in response to touch events and we want to ensure that the injected keys        // are processed in the order they were received and we cannot trust that        // the time stamp of injected events are monotonic.        QueuedInputEvent last = mFirstPendingInputEvent;        if (last == null) {            mFirstPendingInputEvent = q;        } else {            while (last.mNext != null) {                last = last.mNext;            }            last.mNext = q;        }        if (processImmediately) {            doProcessInputEvents();        } else {            scheduleProcessInputEvents();        }    }

如果是要立刻处理这个Eent事件就会调用doProcessInputEvents(), 如果不是的话,就调用scheduleProcessInputEvents(), 把这个event放到主线程的Loop里面,然后由ViewRootHandle来处理。

[cpp] view plaincopyprint?
  1.     void doProcessInputEvents() {  
  2.         while (mCurrentInputEvent == null && mFirstPendingInputEvent != null) {  
  3.             QueuedInputEvent q = mFirstPendingInputEvent;  
  4.             mFirstPendingInputEvent = q.mNext;  
  5.             q.mNext = null;  
  6.             mCurrentInputEvent = q;  
  7. <SPAN style="COLOR: #ff0000">            deliverInputEvent(q);</SPAN>  
  8.         }  
    void doProcessInputEvents() {        while (mCurrentInputEvent == null && mFirstPendingInputEvent != null) {            QueuedInputEvent q = mFirstPendingInputEvent;            mFirstPendingInputEvent = q.mNext;            q.mNext = null;            mCurrentInputEvent = q;            deliverInputEvent(q);        }


[cpp] view plaincopyprint?
  1.     private void deliverPointerEvent(QueuedInputEvent q) {  
  2.     Log.d(TAG, "deliverPointerEvent ######################");  
  3.         final MotionEvent event = (MotionEvent)q.mEvent;  
  4.         final boolean isTouchEvent = event.isTouchEvent();  
  5.         if (mInputEventConsistencyVerifier != null) {  
  6.             if (isTouchEvent) {  
  7.                 mInputEventConsistencyVerifier.onTouchEvent(event, 0);  
  8.             } else {  
  9.                 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);  
  10.             }  
  11.         }  
  12.   
  13.         // If there is no view, then the event will not be handled.  
  14.         if (mView == null || !mAdded) {  
  15.             finishInputEvent(q, false);  
  16.             return;  
  17.         }  
  18.   
  19.         // Translate the pointer event for compatibility, if needed.  
  20.         if (mTranslator != null) {  
  21.             mTranslator.translateEventInScreenToAppWindow(event);  
  22.         }  
  23.   
  24.         // Enter touch mode on down or scroll.  
  25.         final int action = event.getAction();  
  26. <SPAN style="COLOR: #ff0000">        if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {  
  27.             ensureTouchMode(true);  
  28.         }</SPAN>  
  29.   
  30.         // Offset the scroll position.   
  31.         if (mCurScrollY != 0) {  
  32.             event.offsetLocation(0, mCurScrollY);  
  33.         }  
  34.         if (MEASURE_LATENCY) {  
  35.             lt.sample("A Dispatching PointerEvents", System.nanoTime() - event.getEventTimeNano());  
  36.         }  
  37.   
  38.         // Remember the touch position for possible drag-initiation.  
  39.         if (isTouchEvent) {  
  40.             mLastTouchPoint.x = event.getRawX();  
  41.             mLastTouchPoint.y = event.getRawY();  
  42.         }  
  43.   
  44. <SPAN style="COLOR: #ff0000">        // Dispatch touch to view hierarchy.  
  45.         boolean handled = mView.dispatchPointerEvent(event);</SPAN>  
  46.         if (MEASURE_LATENCY) {  
  47.             lt.sample("B Dispatched PointerEvents ", System.nanoTime() - event.getEventTimeNano());  
  48.         }  
  49.         if (handled) {  
  50.             finishInputEvent(q, true);  
  51.             return;  
  52.         }  
  53.   
  54.         // Pointer event was unhandled.   
  55.         <SPAN style="COLOR: #ff0000">finishInputEvent(q, false);</SPAN>  
  56.     }  
    private void deliverPointerEvent(QueuedInputEvent q) {Log.d(TAG, "deliverPointerEvent ######################");        final MotionEvent event = (MotionEvent)q.mEvent;        final boolean isTouchEvent = event.isTouchEvent();        if (mInputEventConsistencyVerifier != null) {            if (isTouchEvent) {                mInputEventConsistencyVerifier.onTouchEvent(event, 0);            } else {                mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);            }        }        // If there is no view, then the event will not be handled.        if (mView == null || !mAdded) {            finishInputEvent(q, false);            return;        }        // Translate the pointer event for compatibility, if needed.        if (mTranslator != null) {            mTranslator.translateEventInScreenToAppWindow(event);        }        // Enter touch mode on down or scroll.        final int action = event.getAction();        if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {            ensureTouchMode(true);        }        // Offset the scroll position.        if (mCurScrollY != 0) {            event.offsetLocation(0, mCurScrollY);        }        if (MEASURE_LATENCY) {            lt.sample("A Dispatching PointerEvents", System.nanoTime() - event.getEventTimeNano());        }        // Remember the touch position for possible drag-initiation.        if (isTouchEvent) {            mLastTouchPoint.x = event.getRawX();            mLastTouchPoint.y = event.getRawY();        }        // Dispatch touch to view hierarchy.        boolean handled = mView.dispatchPointerEvent(event);        if (MEASURE_LATENCY) {            lt.sample("B Dispatched PointerEvents ", System.nanoTime() - event.getEventTimeNano());        }        if (handled) {            finishInputEvent(q, true);            return;        }        // Pointer event was unhandled.        finishInputEvent(q, false);    }

在deliverPointerEvent中会通过mView去做真正的dispatch的工作,

[java] view plaincopyprint?
  1. public final boolean dispatchPointerEvent(MotionEvent event) {  
  2.     if (event.isTouchEvent()) {  
  3.         return dispatchTouchEvent(event);  
  4.     } else {  
  5.         return dispatchGenericMotionEvent(event);  
  6.     }  
  7. }  
    public final boolean dispatchPointerEvent(MotionEvent event) {        if (event.isTouchEvent()) {            return dispatchTouchEvent(event);        } else {            return dispatchGenericMotionEvent(event);        }    }

[java] view plaincopyprint?
  1. public boolean dispatchTouchEvent(MotionEvent event) {  
  2.        if (mInputEventConsistencyVerifier != null) {  
  3.            mInputEventConsistencyVerifier.onTouchEvent(event, 0);  
  4.        }  
  5.   
  6.        if (onFilterTouchEventForSecurity(event)) {  
  7.            //noinspection SimplifiableIfStatement  
  8.            ListenerInfo li = mListenerInfo;  
  9.            if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED  
  10.                    && li.mOnTouchListener.onTouch(this, event)) {  
  11.                return true;  
  12.            }  
  13.   
  14.            if (onTouchEvent(event)) {  
  15.                return true;  
  16.            }  
  17.        }  
  18.   
  19.        if (mInputEventConsistencyVerifier != null) {  
  20.            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);  
  21.        }  
  22.        return false;  
  23.    }  
 public boolean dispatchTouchEvent(MotionEvent event) {        if (mInputEventConsistencyVerifier != null) {            mInputEventConsistencyVerifier.onTouchEvent(event, 0);        }        if (onFilterTouchEventForSecurity(event)) {            //noinspection SimplifiableIfStatement            ListenerInfo li = mListenerInfo;            if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED                    && li.mOnTouchListener.onTouch(this, event)) {                return true;            }            if (onTouchEvent(event)) {                return true;            }        }        if (mInputEventConsistencyVerifier != null) {            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);        }        return false;    }


当mView.dispatchPointerEvent完成之后会返回一个handled值,代表是否被接受处理了, 然后去调 finishInputEvent (ViewRootImpl.java); 

[cpp] view plaincopyprint?
  1. private void finishInputEvent(QueuedInputEvent q, boolean handled) {  
  2.     if (q != mCurrentInputEvent) {  
  3.         throw new IllegalStateException("finished input event out of order");  
  4.     }  
  5.   
  6.     if (q.mReceiver != null) {  
  7. N style="COLOR: #ff0000">            q.mReceiver.finishInputEvent(q.mEvent, handled);</SPAN>  
  8.     } else {  
  9.         q.mEvent.recycleIfNeededAfterDispatch();  
  10.     }  
  11.   
  12.     recycleQueuedInputEvent(q);  
  13.   
  14.     mCurrentInputEvent = null;  
  15.     if (mFirstPendingInputEvent != null) {  
  16.         scheduleProcessInputEvents();  
  17.     }  
  18. }  
    private void finishInputEvent(QueuedInputEvent q, boolean handled) {        if (q != mCurrentInputEvent) {            throw new IllegalStateException("finished input event out of order");        }        if (q.mReceiver != null) {            q.mReceiver.finishInputEvent(q.mEvent, handled);        } else {            q.mEvent.recycleIfNeededAfterDispatch();        }        recycleQueuedInputEvent(q);        mCurrentInputEvent = null;        if (mFirstPendingInputEvent != null) {            scheduleProcessInputEvents();        }    }

调到 InputEventReceiver.java ----> finishInputEvent

[cpp] view plaincopyprint?
  1. public final void finishInputEvent(InputEvent event, boolean handled) {  
  2.     if (event == null) {  
  3.         throw new IllegalArgumentException("event must not be null");  
  4.     }  
  5.     if (mReceiverPtr == 0) {  
  6.         Log.w(TAG, "Attempted to finish an input event but the input event "  
  7.                 + "receiver has already been disposed.");  
  8.     } else {  
  9.         int index = mSeqMap.indexOfKey(event.getSequenceNumber());  
  10.         if (index < 0) {  
  11.             Log.w(TAG, "Attempted to finish an input event that is not in progress.");  
  12.         } else {  
  13.             int seq = mSeqMap.valueAt(index);  
  14.             mSeqMap.removeAt(index);  
  15.             <SPAN style="COLOR: #ff0000">nativeFinishInputEvent(mReceiverPtr, seq, handled);</SPAN>  
  16.         }  
  17.     }  
  18.     event.recycleIfNeededAfterDispatch();  
  19. }  
    public final void finishInputEvent(InputEvent event, boolean handled) {        if (event == null) {            throw new IllegalArgumentException("event must not be null");        }        if (mReceiverPtr == 0) {            Log.w(TAG, "Attempted to finish an input event but the input event "                    + "receiver has already been disposed.");        } else {            int index = mSeqMap.indexOfKey(event.getSequenceNumber());            if (index < 0) {                Log.w(TAG, "Attempted to finish an input event that is not in progress.");            } else {                int seq = mSeqMap.valueAt(index);                mSeqMap.removeAt(index);                nativeFinishInputEvent(mReceiverPtr, seq, handled);            }        }        event.recycleIfNeededAfterDispatch();    }

去调用Navetive的函数nativeFinishInputEvent

[cpp] view plaincopyprint?
  1. status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {  
  2. #if DEBUG_DISPATCH_CYCLE   
  3.     ALOGD("channel '%s' ~ Finished input event.", getInputChannelName());  
  4. #endif   
  5.   
  6. <SPAN style="COLOR: #ff0000">    status_t status = mInputConsumer.sendFinishedSignal(seq, handled);</SPAN>  
  7.     if (status) {  
  8.         ALOGW("Failed to send finished signal on channel '%s'.  status=%d",  
  9.                 getInputChannelName(), status);  
  10.     }  
  11.     return status;  
  12. }  
status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {#if DEBUG_DISPATCH_CYCLE    ALOGD("channel '%s' ~ Finished input event.", getInputChannelName());#endif    status_t status = mInputConsumer.sendFinishedSignal(seq, handled);    if (status) {        ALOGW("Failed to send finished signal on channel '%s'.  status=%d",                getInputChannelName(), status);    }    return status;}


[cpp] view plaincopyprint?
  1. status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {  
  2. #if DEBUG_TRANSPORT_ACTIONS   
  3.     ALOGD("channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s",  
  4.             mChannel->getName().string(), seq, handled ? "true" : "false");  
  5. #endif   
  6.   
  7.     if (!seq) {  
  8.         ALOGE("Attempted to send a finished signal with sequence number 0.");  
  9.         return BAD_VALUE;  
  10.     }  
  11.   
  12.     // Send finished signals for the batch sequence chain first.  
  13.     size_t seqChainCount = mSeqChains.size();  
  14.     if (seqChainCount) {  
  15.         uint32_t currentSeq = seq;  
  16.         uint32_t chainSeqs[seqChainCount];  
  17.         size_t chainIndex = 0;  
  18.         for (size_t i = seqChainCount; i-- > 0; ) {  
  19.              const SeqChain& seqChain = mSeqChains.itemAt(i);  
  20.              if (seqChain.seq == currentSeq) {  
  21.                  currentSeq = seqChain.chain;  
  22.                  chainSeqs[chainIndex++] = currentSeq;  
  23.                  mSeqChains.removeAt(i);  
  24.              }  
  25.         }  
  26.         status_t status = OK;  
  27.         while (!status && chainIndex-- > 0) {  
  28.             status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);  
  29.         }  
  30.         if (status) {  
  31.             // An error occurred so at least one signal was not sent, reconstruct the chain.  
  32.             do {  
  33.                 SeqChain seqChain;  
  34.                 seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;  
  35.                 seqChain.chain = chainSeqs[chainIndex];  
  36.                 mSeqChains.push(seqChain);  
  37.             } while (chainIndex-- > 0);  
  38.             return status;  
  39.         }  
  40.     }  
  41.   
  42.     // Send finished signal for the last message in the batch.  
  43.     return sendUnchainedFinishedSignal(seq, handled);  
  44. }  
status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {#if DEBUG_TRANSPORT_ACTIONS    ALOGD("channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s",            mChannel->getName().string(), seq, handled ? "true" : "false");#endif    if (!seq) {        ALOGE("Attempted to send a finished signal with sequence number 0.");        return BAD_VALUE;    }    // Send finished signals for the batch sequence chain first.    size_t seqChainCount = mSeqChains.size();    if (seqChainCount) {        uint32_t currentSeq = seq;        uint32_t chainSeqs[seqChainCount];        size_t chainIndex = 0;        for (size_t i = seqChainCount; i-- > 0; ) {             const SeqChain& seqChain = mSeqChains.itemAt(i);             if (seqChain.seq == currentSeq) {                 currentSeq = seqChain.chain;                 chainSeqs[chainIndex++] = currentSeq;                 mSeqChains.removeAt(i);             }        }        status_t status = OK;        while (!status && chainIndex-- > 0) {            status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);        }        if (status) {            // An error occurred so at least one signal was not sent, reconstruct the chain.            do {                SeqChain seqChain;                seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;                seqChain.chain = chainSeqs[chainIndex];                mSeqChains.push(seqChain);            } while (chainIndex-- > 0);            return status;        }    }    // Send finished signal for the last message in the batch.    return sendUnchainedFinishedSignal(seq, handled);}

最后应该由InputPublisher::receiveFinishedSignal,回去接收这个信号处理。

[cpp] view plaincopyprint?
  1. status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) {  
  2. #if DEBUG_TRANSPORT_ACTIONS   
  3.     ALOGD("channel '%s' publisher ~ receiveFinishedSignal",  
  4.             mChannel->getName().string());  
  5. #endif   
  6.   
  7.     InputMessage msg;  
  8.     status_t result = mChannel->receiveMessage(&msg);  
  9.     if (result) {  
  10.         *outSeq = 0;  
  11.         *outHandled = false;  
  12.         return result;  
  13.     }  
  14.     if (msg.header.type != InputMessage::TYPE_FINISHED) {  
  15.         ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer",  
  16.                 mChannel->getName().string(), msg.header.type);  
  17.         return UNKNOWN_ERROR;  
  18.     }  
  19.     *outSeq = msg.body.finished.seq;  
  20.     *outHandled = msg.body.finished.handled;  
  21.     return OK;  
  22. }  
status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) {#if DEBUG_TRANSPORT_ACTIONS    ALOGD("channel '%s' publisher ~ receiveFinishedSignal",            mChannel->getName().string());#endif    InputMessage msg;    status_t result = mChannel->receiveMessage(&msg);    if (result) {        *outSeq = 0;        *outHandled = false;        return result;    }    if (msg.header.type != InputMessage::TYPE_FINISHED) {        ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer",                mChannel->getName().string(), msg.header.type);        return UNKNOWN_ERROR;    }    *outSeq = msg.body.finished.seq;    *outHandled = msg.body.finished.handled;    return OK;}


InputDispatcher::handleReceiveCallback 里面有一个循环会去调用receiveFinishedSignal, 并且block在那里,等receiveFinishedSignal有返回值。



        在前面分析应用程序注册键盘消息接收通道过程的Step 21中,我们也说过,当应用程序的主线程因为这个InputChannel中的前向管道的写端唤醒时,InputDispatcher的成员函数handleReceiveCallback就会被回调,因此,接下来,应用程序的主线程就会被唤醒,然后执行InputDispatcher的成员函数handleReceiveCallback。


[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 14px">int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {  
  2.     InputDispatcher* d = static_cast<InputDispatcher*>(data);  
  3.     { // acquire lock   
  4.         AutoMutex _l(d->mLock);  
  5.        ALOGD(" InputDispatcher::handleReceiveCallback !!!!!!!!!!!!!!!~~~~~~~~");  
  6.         ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);  
  7.         if (connectionIndex < 0) {  
  8.             ALOGE("Received spurious receive callback for unknown input channel.  "  
  9.                     "fd=%d, events=0x%x", fd, events);  
  10.             return 0; // remove the callback  
  11.         }  
  12.         bool notify;  
  13.         sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);  
  14.         if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {  
  15.             if (!(events & ALOOPER_EVENT_INPUT)) {  
  16.                 ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "  
  17.                         "events=0x%x", connection->getInputChannelName(), events);  
  18.                 return 1;  
  19.             }  
  20.             nsecs_t currentTime = now();  
  21.             bool gotOne = false;  
  22.             status_t status;  
  23.             for (;;) {  
  24.                 uint32_t seq;  
  25.                 bool handled;  
  26.                 status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);  
  27.                 if (status) {  
  28.                     break;  
  29.                 }  
  30.                 d->finishDispatchCycleLocked(currentTime, connection, seq, handled);  
  31.                 gotOne = true;  
  32.             }  
  33.             if (gotOne) {  
  34.                 d->runCommandsLockedInterruptible();  
  35.                 if (status == WOULD_BLOCK) {  
  36.                     return 1;  
  37.                 }  
  38.             }  
  39.             notify = status != DEAD_OBJECT || !connection->monitor;  
  40.             if (notify) {  
  41.                 ALOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",  
  42.                         connection->getInputChannelName(), status);  
  43.             }  
  44.         } else {  
  45.             // Monitor channels are never explicitly unregistered.  
  46.             // We do it automatically when the remote endpoint is closed so don't warn  
  47.             // about them.   
  48.             notify = !connection->monitor;  
  49.             if (notify) {  
  50.                 ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred.  "  
  51.                         "events=0x%x", connection->getInputChannelName(), events);  
  52.             }  
  53.         }  
  54.         // Unregister the channel.   
  55.         d->unregisterInputChannelLocked(connection->inputChannel, notify);  
  56.         return 0; // remove the callback  
  57.     } // release lock   
  58. }</SPAN><SPAN style="FONT-SIZE: 14px">  
  59. </SPAN>  
int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {    InputDispatcher* d = static_cast<InputDispatcher*>(data);    { // acquire lock        AutoMutex _l(d->mLock);       ALOGD(" InputDispatcher::handleReceiveCallback !!!!!!!!!!!!!!!~~~~~~~~");        ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);        if (connectionIndex < 0) {            ALOGE("Received spurious receive callback for unknown input channel.  "                    "fd=%d, events=0x%x", fd, events);            return 0; // remove the callback        }        bool notify;        sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);        if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {            if (!(events & ALOOPER_EVENT_INPUT)) {                ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "                        "events=0x%x", connection->getInputChannelName(), events);                return 1;            }            nsecs_t currentTime = now();            bool gotOne = false;            status_t status;            for (;;) {                uint32_t seq;                bool handled;                status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);                if (status) {                    break;                }                d->finishDispatchCycleLocked(currentTime, connection, seq, handled);                gotOne = true;            }            if (gotOne) {                d->runCommandsLockedInterruptible();                if (status == WOULD_BLOCK) {                    return 1;                }            }            notify = status != DEAD_OBJECT || !connection->monitor;            if (notify) {                ALOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",                        connection->getInputChannelName(), status);            }        } else {            // Monitor channels are never explicitly unregistered.            // We do it automatically when the remote endpoint is closed so don't warn            // about them.            notify = !connection->monitor;            if (notify) {                ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred.  "                        "events=0x%x", connection->getInputChannelName(), events);            }        }        // Unregister the channel.        d->unregisterInputChannelLocked(connection->inputChannel, notify);        return 0; // remove the callback    } // release lock}