Android4.1 InputManagerService 流程

1. mInputManager = new InputManagerService(context, mInputMonitor);

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

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

  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)


  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


  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对象,后面会用到。

  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();
}

  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事件。

   

  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方法。

  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();

  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() 

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

  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去处理。

 

  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去接着处理事件。

  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

  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中。    


  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

  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具体代表什么意思)

  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);


  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,

  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对象,

  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的,上文也提到过。
  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

  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。

  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中。

  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继续运行


  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去完成具体的事物。


  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函数。


  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;
}


  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中去查找。

  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;
}


  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;
    }
}


  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函数来进一步处理。


  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);
}


  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窗口来执行键盘事件处理的流程了。

  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类型的变量。一个用于发布,一个用于接收。

  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;
}



  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 

  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中。


  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来处理。

  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);
        }


  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的工作,

  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);
        }
    }

  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); 

  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

  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

  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;
}


  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,回去接收这个信号处理。

  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。


  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
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值