android中输入系统之内核到InputManagerService过程(源码)

愿每一份努力都不会被辜负-陈

总体流程

在Android中,Touch事件的分发分服务端和应用端。在服务端由WindowManagerService(借助InputManagerService)负责采集和分发的,在应用端则
是由ViewRootlmpl(内部有一个mView变量指向View树的根,负责控制View树的Ul绘制和事件消息的分发)负责分发的。当输入设备可用时,比如触屏,Linux内核会在/dev/input中创建对应的设备节点,输入事件所产生的原始信息会被Linux内核中的输入子系统采集,原始信息由Kernel Space的驱动层一直传递到User Space的设备节点。IMS所做的工作就是监听/dev/input下的所有的设备节点,当设备节点有数据时会将数据进行加工处理并找到合适的Window,将输入事件派发给它。

总体来说分为以下三个流程:事件采集,事件中转以及事件分发。

在这里插入图片描述

事件的本质

事件的本质其实就是一个个文件,事件产生后由Linux系统将数据保存到dev/input文件夹下。

我们可以通过命令来获取输入事件的信息:

adb shell getevent
adb shell input event 4
adb shell getevent -t -I

Linux-Posix函数(关键函数用到)

  • ePoll

    被公认为Linux2.6下性能最好的多路l/O就绪通知方法。

    epoll只有epoll_create,epoll_ctl,epoll_wait 3个系统调用。

    epoll create:当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽(无限的创建文件夹同样会导致fd被耗尽)。
    epoll _ctl:epol的事件注册函数,它不同于select(是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。
    epoll wait:收集在epoll监控的事件中已经发送的事件。参数events是分配好的epoll event结构体数组,epoll将会把发生的事件赋值到levents数组中(events不可以是空指针,内核只负责把数据复制到这个events数组中,不会去帮助我们在用户态中分配内存)。maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll create(时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。如果函数调用成功,返回对应/O上已准备好的文件描述符数目,如返回0表示已超时

    具体参考:https://blog.csdn.net/xiajun07061225/article/details/9250579

  • iNotify

    它是一个内核用于通知用户空间程序文件系统变化的机制

    int fd = inotify init ():每一个inotify实例对应一个独立的排序的队列

    inotify add watch:fd是 inotify init0返回的文件描述符,path是被监视的目标的路径名(即文件名或目录名),mask是事件掩码,在头文件linux/inotify.h中定义了每一位代表的事件。可以使用同样的方式来修改事件掩码,即改变希望被通知的inotify 事件。Wd是watch描述符。

    具体用法参考:https://blog.csdn.net/breakout_alex/article/details/89028868

  • socketpair

    socketpairO函数用于创建一对无名的、相互连接的套接子。

    具体使用参考:https://blog.csdn.net/weixin_40039738/article/details/81095013

  • fd

    linux中,每一个进程在内核中,都对应有一个“打开文件”数组,存放指向文件对象的指针,而fd是这个数组的下标。
    我们对文件进行操作时,系统调用,将fd传入内核,内核通过fd找到文件,对文件进行操作。
    既然是数组下标,fd的类型为int,<0为非法值,>=0为合法值。在ilinux中,一个进程默认可以打开的文件数为1024个,fd的范围为0~1023。可以通
    过设置,改变最大值。
    在linux中,值为0、1、2的fd,分别代表标准输入、标准输出、标准错误输出。

从内核到IMS过程

源码流程

在这里插入图片描述

EventHub

  • INotify

    INotify是Linux提供的一种文件系统变化通知机制,什么叫文件系统变化?创建,删除,读写通通叫做变化,使用如下代码就可以将某个目录加入到INotify中。

    int inotifyFd = inotify init();
    int wd =inotify_add_watch(inotifyFd,"/dev/input", IN_CREATE|IN_DELETE):
    

    上述两行代码就将”/dev/input”加入到了INotify中,这样,对于外部输入设备的插拔就可以很好的被检测到了。可不幸的是,INotify发现文件系统变化后不
    会主动告诉别人,它需要主动通过reado函数读取inotifyFd描述符来获取具体变化信息。也就是说,你插入了鼠标,INotify马上就知道了这个信息,并且将
    信息更新到了inotifyFd描述符对应的对象当中

  • Eventhub

    EventHub 通过读取/dev/input/下的相关文件来判断是否有新事件,并通知InputReader。

    Epoll可以用来监听多个描述符的可读写inotifyFd状态,什么意思呢?比如说上面说到了外部输入设备插拔可以被INotify检测到,并且将相信信息写入到inotifyFd对用的对象中,但是我没法知道INotify什么时候捕获到了这些信息。而Epoll可以监听inotifyFd对应的对象内容是否有变化,一旦有变化马上能进行处理,平常大部分时间没监听到变化时睡大觉(其实Android中的Handler中的消息队列用到了epoll机制)。

    epoll wait大部分时间处于阻塞状态(这点和socket等待连接很相似),一旦/dev/input/evento节点有变化(即产生了输入事件),epoll wait会执行完毕

    //frameworks/native/services/inputflinger/EventHub.cpp
    EventHub::EventHub(void) :
            mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
            mOpeningDevices(0), mClosingDevices(0),
            mNeedToSendFinishedDeviceScan(false),
            mNeedToReopenDevices(false), mNeedToScanDevices(true),
            mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
        acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
    
         //创建epoll列表
        mEpollFd = epoll_create(EPOLL_SIZE_HINT);
        LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
    
         //初始化盘符并且监听。
        mINotifyFd = inotify_init();
        int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
        LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s.  errno=%d",
                DEVICE_PATH, errno);
    
        struct epoll_event eventItem;
        memset(&eventItem, 0, sizeof(eventItem));
        eventItem.events = EPOLLIN;
        eventItem.data.u32 = EPOLL_ID_INOTIFY;
         //epoll监听mINotifyFd。
        result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
        LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance.  errno=%d", errno);
    
        int wakeFds[2];
        result = pipe(wakeFds);
        LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
    
        mWakeReadPipeFd = wakeFds[0];
        mWakeWritePipeFd = wakeFds[1];
    
        result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
        LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
                errno);
    
        result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
        LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
                errno);
    
        eventItem.data.u32 = EPOLL_ID_WAKE;
        result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
        LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
                errno);
    
        int major, minor;
        getLinuxRelease(&major, &minor);
        // EPOLLWAKEUP was introduced in kernel 3.5
        mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);
    }
    

IMS概述

  • InputReaderThread

    InputReader会不断的循环读取EventHub中的原始输入事件。

  • InputDispatcherThread

    InputDispatcher中保存了WMS中的所有的Window信息(WMS会将窗口的信息实时的更新到InputDispatcher中),这样InputDispatcher就可以将输入事
    件派发给合适的Window

整体流程源码分析

  1. 由SystemServer启动一个IMS进程进程,然后进行各个对象的初始化

    SystemServer开启其他服务(这个在之前的博客有详细介绍)

    //com/android/server/SystemServer.java 
    private void startOtherServices() {
          ......
            traceBeginAndSlog("StartInputManagerService");
            inputManager = new InputManagerService(context);
            traceEnd();
        
        //将inputManager与WindowManagerService关联
           wm = WindowManagerService.main(context, inputManager,
                        mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                        !mFirstBoot, mOnlyCore, new PhoneWindowManager());
        //注册wms服务
                ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                        DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
        //注册ims服务
                ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                        /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
          ......
      }
    

    InputManagerService的构造方法

        public InputManagerService(Context context) {
            this.mContext = context;
            this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
    
            mUseDevInputEventForAudioJack =
                    context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
            Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                    + mUseDevInputEventForAudioJack);
            //调用到jni的初始化方法。
            mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
    
            String doubleTouchGestureEnablePath = context.getResources().getString(
                    R.string.config_doubleTouchGestureEnableFile);
            mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
                new File(doubleTouchGestureEnablePath);
    
            LocalServices.addService(InputManagerInternal.class, new LocalService());
        }
    
  2. 同步会在native层进行初始化,开启一个InputManager对象,开启两个线程,一个Reader线程用来读取触摸信号,一个Dispatcher用来转发信息,EventHub负责采集底层信号。

    通过jni调用到nativeInit方法。

    //frameworks/base/services/core/jni/com_android_server_input_InputManagerService
       
    static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
            jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
        sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
        if (messageQueue == NULL) {
            jniThrowRuntimeException(env, "MessageQueue is not initialized.");
            return 0;
        }
    
        //初始化InputManager
        NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
                messageQueue->getLooper());
        im->incStrong(0);
        return reinterpret_cast<jlong>(im);
    } 
    

    创建NativeInputManager对象

    ///frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
    NativeInputManager::NativeInputManager(jobject contextObj,
            jobject serviceObj, const sp<Looper>& looper) :
            mLooper(looper), mInteractive(true) {
        JNIEnv* env = jniEnv();
    
        mContextObj = env->NewGlobalRef(contextObj);
        mServiceObj = env->NewGlobalRef(serviceObj);
    
        {
            AutoMutex _l(mLock);
            mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
            mLocked.pointerSpeed = 0;
            mLocked.pointerGesturesEnabled = true;
            mLocked.showTouches = false;
            mLocked.pointerCapture = false;
        }
        mInteractive = true;
    
         //注意此处创建了EventHub
        sp<EventHub> eventHub = new EventHub();
        //并把EventHub作为参数传入到InputManager中
        mInputManager = new InputManager(eventHub, this, this);
    }
    
    

    InputManager构造方法

    /frameworks/native/services/inputflinger/InputManager.cpp
    InputManager::InputManager(
            const sp<EventHubInterface>& eventHub,
            const sp<InputReaderPolicyInterface>& readerPolicy,
            const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
        //创建InputDispatcher对象
        mDispatcher = new InputDispatcher(dispatcherPolicy);
        //创建InputReader对象,InputReader在创建之初就与InputDispatcher产生了紧密的关联,后面会使用nQueuedListener->flush()通知事件。
    
        mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
        //初始化
        initialize();
    }
    

    initialize()初始化

    ///frameworks/native/services/inputflinger/InputManager.cpp
    void InputManager::initialize() {
        //创建绣程“InputReader”
        mReaderThread = new InputReaderThread(mReader);
        //创建线程”InputDispatcher“
        mDispatcherThread = new InputDispatcherThread(mDispatcher);
    }
    

    InputReader构造方法

    //frameworks/native/services/inputflinger/InputReader.cpp
    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) {
        //创建Listener回调,这个后面会调用nQueuedListener->flush(),记住这个listener是一个InputDispatcher
        mQueuedListener = new QueuedInputListener(listener);
    
        { // acquire lock
            AutoMutex _l(mLock);
    
            refreshConfigurationLocked(0);
            updateGlobalMetaStateLocked();
        } // release lock
    }
    

    InputDispatcher构造方法

    //frameworks/native/services/inputflinger/InputDispatcher.cpp
    InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
        mPolicy(policy),
        mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
        mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
        mNextUnblockedEvent(NULL),
        mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
        mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
        mLooper = new Looper(false);
    
        mKeyRepeatState.lastKeyEntry = NULL;
    
        policy->getDispatcherConfiguration(&mConfig);
    }
    
  3. 通过IMS.start启动上面两个线程流程

    inputManager.start()

    //com/android/server/SystemServer.java
    traceBeginAndSlog("StartInputManager");
                inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
                inputManager.start();
                traceEnd();
    

    InputManagerService.start

    //com/android/server/input/InputManagerService.java 
    public void start() {
            Slog.i(TAG, "Starting input manager");
          //jni 开启inputmanager
            nativeStart(mPtr);
    
            // Add ourself to the Watchdog monitors.
            Watchdog.getInstance().addMonitor(this);
    
            registerPointerSpeedSettingObserver();
            registerShowTouchesSettingObserver();
            registerAccessibilityLargePointerSettingObserver();
    
            mContext.registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    updatePointerSpeedFromSettings();
                    updateShowTouchesFromSettings();
                    updateAccessibilityLargePointerFromSettings();
                }
            }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
    
            updatePointerSpeedFromSettings();
            updateShowTouchesFromSettings();
            updateAccessibilityLargePointerFromSettings();
        }
    
    

    nativeStart()

    ///frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
    static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
        NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
    
        status_t result = im->getInputManager()->start();
        if (result) {
            jniThrowRuntimeException(env, "Input manager could not be started.");
        }
    }
    
    ///frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
    status_t InputManager::start() {
        status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
        if (result) {
            ALOGE("Could not start InputDispatcher thread due to error %d.", result);
            return result;
        }
    
        result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
        if (result) {
            ALOGE("Could not start InputReader thread due to error %d.", result);
    
            mDispatcherThread->requestExit();
            return result;
        }
    
        return OK;
    }
    
  4. InputRerader线程处理过程

    InputRender线程运行。

    ///frameworks/native/services/inputflinger/InputReader.cpp
    bool InputReaderThread::threadLoop() {
        mReader->loopOnce();
        return true;
    }
    

    处理事件

    ///frameworks/native/services/inputflinger/InputReader.cpp
    void InputReader::loopOnce() {
        int32_t oldGeneration;
        int32_t timeoutMillis;
        bool inputDevicesChanged = false;
        Vector<InputDeviceInfo> inputDevices;
        { // acquire lock
            AutoMutex _l(mLock);
    
            oldGeneration = mGeneration;
            timeoutMillis = -1;
    
            uint32_t changes = mConfigurationChangesToRefresh;
            if (changes) {
                mConfigurationChangesToRefresh = 0;
                timeoutMillis = 0;
                refreshConfigurationLocked(changes);
            } else if (mNextTimeout != LLONG_MAX) {
                nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
                timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
            }
        } // release lock
    
    	//内部有一个epoll_wait()  挂起
    	//唤醒由linux驱动去更改dev/input下的文件造成  inotify+epoll,从Eventhub中读取事件,这里注意因为之前将的EventHub.getEvent中有epoll wait进行阻塞,若FD发生改变则执行后面代码
        //通过EventHub的getEvents函数获取事件信息,并存放到mEventBuffer中。
    
        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) {
    #if DEBUG_RAW_EVENTS
                    ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
    #endif
                    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);
        }
    
        // Flush queued events out to the listener.
        // This must happen outside of the lock because the listener could potentially call
        // back into the InputReader's methods, such as getScanCodeState, or become blocked
        // on another thread similarly waiting to acquire the InputReader lock thereby
        // resulting in a deadlock.  This situation is actually quite plausible because the
        // listener is actually the input dispatcher, which calls into the window manager,
        // which occasionally calls into the input reader.
        mQueuedListener->flush();
    }
    

    处理事件信息:processEventsLocked

    ///frameworks/native/services/inputflinger/InputReader.cpp
    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: %zu Count: %zu", batchSize, count);
    #endif
                //手动注意,继续调用。,处理deviceId所对应的设备的原始输入事件。
                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;
        }
    }
    
    

    继续调用processEventsForDeviceLocked:

    ///frameworks/native/services/inputflinger/InputReader.cpp
    void InputReader::processEventsForDeviceLocked(int32_t deviceId,
            const RawEvent* rawEvents, size_t count) {
        //从mDevices中获取对应的deviceIndex
        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
        if (deviceIndex < 0) {
            ALOGW("Discarding event for unknown deviceId %d.", deviceId);
            return;
        }
    
        //查找设备
        InputDevice* device = mDevices.valueAt(deviceIndex);
        if (device->isIgnored()) {
            //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
            return;
        }
    
        device->process(rawEvents, count);
    }
    
    

    调用inputDevice.process()

    ///frameworks/native/services/inputflinger/InputReader.cpp
    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();
        //遍历处理该InputDevice的所有事件
        for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
    #if DEBUG_RAW_EVENTS
            ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
                    rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
                    rawEvent->when);
    #endif
    
            //mDropUntilNextSync默认值为false,如果设备的输入事件的缓冲区溢出,这个值为true
            if (mDropUntilNextSync) {
                if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
                    mDropUntilNextSync = false;
    #if DEBUG_RAW_EVENTS
                    ALOGD("Recovered from input event buffer overrun.");
    #endif
                } else {
    #if DEBUG_RAW_EVENTS
                    ALOGD("Dropped input event while waiting for next input sync.");
    #endif
                }
            } 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);
                }
            }
            --count;
        }
    }
    
    

    交给对应的设备处理 mapper->process(rawEvent),这里需要注意,InputMapper有很多的子类,我们要找触摸事件的相关处理就是找到TouchlnputMapper

    ///frameworks/native/services/inputflinger/InputReader.cpp
    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);
        }
    }
    

    继续sync

    ///frameworks/native/services/inputflinger/InputReader.cpp
    void TouchInputMapper::sync(nsecs_t when) {
        const RawState* last = mRawStatesPending.isEmpty() ?
                &mCurrentRawState : &mRawStatesPending.top();
    
        // Push a new state.
        mRawStatesPending.push();
        RawState* next = &mRawStatesPending.editTop();
        next->clear();
        next->when = when;
    
        // Sync button state.
        next->buttonState = mTouchButtonAccumulator.getButtonState()
                | mCursorButtonAccumulator.getButtonState();
    
        // Sync scroll
        next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
        next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
        mCursorScrollAccumulator.finishSync();
    
        // Sync touch
        syncTouch(when, next);
    
        // Assign pointer ids.
        if (!mHavePointerIds) {
            assignPointerIds(last, next);
        }
    
    #if DEBUG_RAW_EVENTS
        ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
                "hovering ids 0x%08x -> 0x%08x",
                last->rawPointerData.pointerCount,
                next->rawPointerData.pointerCount,
                last->rawPointerData.touchingIdBits.value,
                next->rawPointerData.touchingIdBits.value,
                last->rawPointerData.hoveringIdBits.value,
                next->rawPointerData.hoveringIdBits.value);
    #endif
    
        processRawTouches(false /*timeout*/);
    }
    

    processRawTouches(最终的目的是找到数据的最终去向)

    ///frameworks/native/services/inputflinger/InputReader.cpp
    void TouchInputMapper::processRawTouches(bool timeout) {
        if (mDeviceMode == DEVICE_MODE_DISABLED) {
            // Drop all input if the device is disabled.
            mCurrentRawState.clear();
            mRawStatesPending.clear();
            return;
        }
    
        // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
        // valid and must go through the full cook and dispatch cycle. This ensures that anything
        // touching the current state will only observe the events that have been dispatched to the
        // rest of the pipeline.
        const size_t N = mRawStatesPending.size();
        size_t count;
        for(count = 0; count < N; count++) {
            const RawState& next = mRawStatesPending[count];
    
            // A failure to assign the stylus id means that we're waiting on stylus data
            // and so should defer the rest of the pipeline.
            if (assignExternalStylusId(next, timeout)) {
                break;
            }
    
            // All ready to go.
            clearStylusDataPendingFlags();
            mCurrentRawState.copyFrom(next);
            if (mCurrentRawState.when < mLastRawState.when) {
                mCurrentRawState.when = mLastRawState.when;
            }
            cookAndDispatch(mCurrentRawState.when);
        }
        if (count != 0) {
            mRawStatesPending.removeItemsAt(0, count);
        }
    
        if (mExternalStylusDataPending) {
            if (timeout) {
                nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
                clearStylusDataPendingFlags();
                mCurrentRawState.copyFrom(mLastRawState);
    #if DEBUG_STYLUS_FUSION
                ALOGD("Timeout expired, synthesizing event with new stylus data");
    #endif
                //手动注意
                cookAndDispatch(when);
            } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
                mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
                getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
            }
        }
    }
    

    cookAndDispatch

    ///frameworks/native/services/inputflinger/InputReader.cpp
    void TouchInputMapper::cookAndDispatch(nsecs_t when) {
        // Always start with a clean state.
        mCurrentCookedState.clear();
    
        // Apply stylus buttons to current raw state.
        applyExternalStylusButtonState(when);
    
        // Handle policy on initial down or hover events.
        bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
                && mCurrentRawState.rawPointerData.pointerCount != 0;
    
        uint32_t policyFlags = 0;
        bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
        if (initialDown || buttonsPressed) {
            // If this is a touch screen, hide the pointer on an initial down.
            if (mDeviceMode == DEVICE_MODE_DIRECT) {
                getContext()->fadePointer();
            }
    
            if (mParameters.wake) {
                policyFlags |= POLICY_FLAG_WAKE;
            }
        }
    
        // 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)) {
            mCurrentRawState.rawPointerData.clear();
        }
    
        // Cook pointer data.  This call populates the mCurrentCookedState.cookedPointerData 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();
    
        // Apply stylus pressure to current cooked state.
        applyExternalStylusTouchState(when);
    
        // Synthesize key down from raw buttons if needed.
        synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
                policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);
    
        // Dispatch the touches either directly or by translation through a pointer on screen.
        if (mDeviceMode == DEVICE_MODE_POINTER) {
            for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);
                    !idBits.isEmpty(); ) {
                uint32_t id = idBits.clearFirstMarkedBit();
                const RawPointerData::Pointer& pointer =
                        mCurrentRawState.rawPointerData.pointerForId(id);
                if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
                    mCurrentCookedState.stylusIdBits.markBit(id);
                } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
                    mCurrentCookedState.fingerIdBits.markBit(id);
                } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
                    mCurrentCookedState.mouseIdBits.markBit(id);
                }
            }
            for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);
                    !idBits.isEmpty(); ) {
                uint32_t id = idBits.clearFirstMarkedBit();
                const RawPointerData::Pointer& pointer =
                        mCurrentRawState.rawPointerData.pointerForId(id);
                if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
                        || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
                    mCurrentCookedState.stylusIdBits.markBit(id);
                }
            }
    
            // Stylus takes precedence over all tools, then mouse, then finger.
            PointerUsage pointerUsage = mPointerUsage;
            if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
                mCurrentCookedState.mouseIdBits.clear();
                mCurrentCookedState.fingerIdBits.clear();
                pointerUsage = POINTER_USAGE_STYLUS;
            } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
                mCurrentCookedState.fingerIdBits.clear();
                pointerUsage = POINTER_USAGE_MOUSE;
            } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
                    isPointerDown(mCurrentRawState.buttonState)) {
                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(mCurrentRawState.buttonState);
                mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
                        mCurrentCookedState.cookedPointerData.idToIndex,
                        mCurrentCookedState.cookedPointerData.touchingIdBits);
            }
    
            if (!mCurrentMotionAborted) {
                dispatchButtonRelease(when, policyFlags);
                dispatchHoverExit(when, policyFlags);
                //手动注意,分发消息
                dispatchTouches(when, policyFlags);
                dispatchHoverEnterAndMove(when, policyFlags);
                dispatchButtonPress(when, policyFlags);
            }
    
            if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
                mCurrentMotionAborted = false;
            }
        }
    
        // Synthesize key up from raw buttons if needed.
        synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
                policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);
    
        // Clear some transient state.
        mCurrentRawState.rawVScroll = 0;
        mCurrentRawState.rawHScroll = 0;
    
        // Copy current touch to last touch in preparation for the next cycle.
        mLastRawState.copyFrom(mCurrentRawState);
        mLastCookedState.copyFrom(mCurrentCookedState);
    }
    
    

    dispatchTouches

    ///frameworks/native/services/inputflinger/InputReader.cpp
    void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
        BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
        BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
        int32_t metaState = getContext()->getGlobalMetaState();
        int32_t buttonState = mCurrentCookedState.buttonState;
    
        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, 0, metaState, buttonState,
                        AMOTION_EVENT_EDGE_FLAG_NONE,
                        mCurrentCookedState.deviceTimestamp,
                        mCurrentCookedState.cookedPointerData.pointerProperties,
                        mCurrentCookedState.cookedPointerData.pointerCoords,
                        mCurrentCookedState.cookedPointerData.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(
                    mCurrentCookedState.cookedPointerData.pointerProperties,
                    mCurrentCookedState.cookedPointerData.pointerCoords,
                    mCurrentCookedState.cookedPointerData.idToIndex,
                    mLastCookedState.cookedPointerData.pointerProperties,
                    mLastCookedState.cookedPointerData.pointerCoords,
                    mLastCookedState.cookedPointerData.idToIndex,
                    moveIdBits);
            if (buttonState != mLastCookedState.buttonState) {
                moveNeeded = true;
            }
    
            // Dispatch pointer up events.
            while (!upIdBits.isEmpty()) {
                uint32_t upId = upIdBits.clearFirstMarkedBit();
    
                //手动注意。
                dispatchMotion(when, policyFlags, mSource,
                        AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,
                        mCurrentCookedState.deviceTimestamp,
                        mLastCookedState.cookedPointerData.pointerProperties,
                        mLastCookedState.cookedPointerData.pointerCoords,
                        mLastCookedState.cookedPointerData.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 && !moveIdBits.isEmpty()) {
                ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
                dispatchMotion(when, policyFlags, mSource,
                        AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
                        mCurrentCookedState.deviceTimestamp,
                        mCurrentCookedState.cookedPointerData.pointerProperties,
                        mCurrentCookedState.cookedPointerData.pointerCoords,
                        mCurrentCookedState.cookedPointerData.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, 0, metaState, buttonState, 0,
                        mCurrentCookedState.deviceTimestamp,
                        mCurrentCookedState.cookedPointerData.pointerProperties,
                        mCurrentCookedState.cookedPointerData.pointerCoords,
                        mCurrentCookedState.cookedPointerData.idToIndex,
                        dispatchedIdBits, downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
            }
        }
    }
    

    dispatchMotion

    ///frameworks/native/services/inputflinger/InputReader.cpp
    void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
            int32_t action, int32_t actionButton, int32_t flags,
            int32_t metaState, int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
            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, actionButton, flags, metaState, buttonState, edgeFlags,
                mViewport.displayId, deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
                xPrecision, yPrecision, downTime);
        getListener()->notifyMotion(&args);
    }
    
    

    getListener()->notifyMotion(&args);.当前这个getListener实际获取是mQueuedListener=new QueuedlnputListener(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);
    
        { // acquire lock
            AutoMutex _l(mLock);
    
            refreshConfigurationLocked(0);
            updateGlobalMetaStateLocked();
        } // release lock
    }
    

    InputLintener.cpp.QueuedlnputListenernotifyMotion这里我们实际可以看到他就是往一个队列当中添加数据,实际上是我们将触摸相关的事件进行包装之后,将其加入到一个ArgsQueue队列,到此,我们已经将数据加入到参数队列中。

    ///frameworks/native/services/inputflinger/InputListener.cpp
    void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
        mArgsQueue.push(new NotifyMotionArgs(*args));
    }
    

    这时我们在回到上面loopOnce()方法中processEventsLocked调用之后,发现当前mQueueListener->flush的调用

        // Flush queued events out to the listener.
        // This must happen outside of the lock because the listener could potentially call
        // back into the InputReader's methods, such as getScanCodeState, or become blocked
        // on another thread similarly waiting to acquire the InputReader lock thereby
        // resulting in a deadlock.  This situation is actually quite plausible because the
        // listener is actually the input dispatcher, which calls into the window manager,
        // which occasionally calls into the input reader.
        mQueuedListener->flush();
    

    flush()

    遍历整个mArgsQueue数组,在input架构中NotifyArgs的实现子类主要有以下几类

    • NotifyConfigurationChangedArgs
    • NotifyKeyArgs
    • NotifyMotionArgs 通知motion事件
    • NotifySwitchArgs
    • NotifvDeviceResetAras
    ///frameworks/native/services/inputflinger/InputListener.cpp
    void QueuedInputListener::flush() {
        size_t count = mArgsQueue.size();
        for (size_t i = 0; i < count; i++) {
            NotifyArgs* args = mArgsQueue[i];
            args->notify(mInnerListener);
            delete args;
        }
        mArgsQueue.clear();
    }
    
    

    上面的listener根据溯源可以看到是lnputDispatcher,是调用InputDispatcher中的notifyMotion,这里就完成了向InputDispatcher的信息传递

    void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {
    	//实际上就是在调用InputDispatcher.notifyMotion
        listener->notifyMotion(this);
    }
    
    
    InputReader::InputReader(const sp<EventHubInterface>& eventHub,
            const sp<InputReaderPolicyInterface>& policy,
            const sp<InputListenerInterface>& listener) ://注意listener
            mContext(this), mEventHub(eventHub), mPolicy(policy),
            mGlobalMetaState(0), mGeneration(1),
            mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
            mConfigurationChangesToRefresh(0) {
        mQueuedListener = new QueuedInputListener(listener);//注意这个listener
    
        { // acquire lock
            AutoMutex _l(mLock);
    
            refreshConfigurationLocked(0);
            updateGlobalMetaStateLocked();
        } // release lock
    }
    
    
    InputManager::InputManager(
            const sp<EventHubInterface>& eventHub,
            const sp<InputReaderPolicyInterface>& readerPolicy,
            const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
        mDispatcher = new InputDispatcher(dispatcherPolicy);
        mReader = new InputReader(eventHub, readerPolicy, mDispatcher);//注意这个listener实际就是dispatcher
        initialize();
    }
    
    
    

    10.执行notifyMotion中的唤醒操作InputDispatcher.cpp

    ///frameworks/native/services/inputflinger/InputDispatcher.cpp
    void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
    #if DEBUG_INBOUND_EVENT_DETAILS
        ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, "
                "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
                "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
                args->eventTime, args->deviceId, args->source, args->policyFlags,
                args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
                args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
        for (uint32_t i = 0; i < args->pointerCount; i++) {
            ALOGD("  Pointer %d: id=%d, toolType=%d, "
                    "x=%f, y=%f, pressure=%f, size=%f, "
                    "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
                    "orientation=%f",
                    i, args->pointerProperties[i].id,
                    args->pointerProperties[i].toolType,
                    args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
                    args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
                    args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
                    args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
                    args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
                    args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
                    args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
                    args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
                    args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
        }
    #endif
        if (!validateMotionEvent(args->action, args->actionButton,
                    args->pointerCount, args->pointerProperties)) {
            return;
        }
    
        uint32_t policyFlags = args->policyFlags;
        policyFlags |= POLICY_FLAG_TRUSTED;
    
        android::base::Timer t;
        mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);
        if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
            ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
                    std::to_string(t.duration().count()).c_str());
        }
    
        bool needWake;
        { // acquire lock
            mLock.lock();
    
            if (shouldSendMotionToInputFilterLocked(args)) {
                mLock.unlock();
    
                MotionEvent event;
                event.initialize(args->deviceId, args->source, args->action, args->actionButton,
                        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->actionButton, args->flags,
                    args->metaState, args->buttonState,
                    args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
                    args->displayId,
                    args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
    
            needWake = enqueueInboundEventLocked(newEntry);
            mLock.unlock();
        } // release lock
    
        if (needWake) {//注意这里唤醒looper。
            mLooper->wake();
        }
    }
    
  5. .InputDispatcher线程处理过程

    InputDispatcher线程开启

    ///frameworks/native/services/inputflinger/InputDispatcher.cpp
    bool InputDispatcherThread::threadLoop() {
        mDispatcher->dispatchOnce();
        return true;
    }
    

    dispatchOnce()轮询

    pollOnce这里是等待被唤醒,进入epoll wait等待状态,当发生以下任一情况则退出等待状态:
    callback:通过回调方法来唤醒;
    timeout:到达nextWakeupTime时间,超时唤醒;
    wake:主动调用Looper的wake0方法;

    ///frameworks/native/services/inputflinger/InputDispatcher.cpp
    void InputDispatcher::dispatchOnce() {
        nsecs_t nextWakeupTime = LONG_LONG_MAX;
        { // acquire lock
            AutoMutex _l(mLock);
            mDispatcherIsAliveCondition.broadcast();
    
            // Run a dispatch loop if there are no pending commands.
            // The dispatch loop might enqueue commands to run afterwards.
            if (!haveCommandsLocked()) {
                dispatchOnceInnerLocked(&nextWakeupTime);
            }
    
            // Run all pending commands if there are any.
            // If any commands were run then force the next poll to wake up immediately.
            if (runCommandsLockedInterruptible()) {
                nextWakeupTime = LONG_LONG_MIN;
            }
        } // 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);
    }
    
   
dispatchOnceInnerLocked
   
   ```c++
   ///frameworks/native/services/inputflinger/InputDispatcher.cpp
   void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
       nsecs_t currentTime = now();
   
       // Reset the key repeat timer whenever normal dispatch is suspended while the
       // device is in a non-interactive state.  This is to ensure that we abort a key
       // repeat if the device is just coming out of sleep.
       if (!mDispatchEnabled) {
           resetKeyRepeatLocked();
       }
   
       // If dispatching is frozen, do not process timeouts or try to deliver any new events.
       //如果InputDispatcher被冻结,则不进行派发操作。
       if (mDispatchFrozen) {
   #if DEBUG_FOCUS
           ALOGD("Dispatch frozen.  Waiting some more.");
   #endif
           return;
       }
   
       // 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.
       //如果isAppSwitchDue为true,则说明没有及时相应Home键操作。
       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.
       //如果还没有待分发的事件,则在mInboundQueue中取出一个事件。
       if (! mPendingEvent) {
           //如果mInboundQueue为空,并且没有待分发的事件就return。
           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.
               //如果mInboundQueue不为空,则取队列头部的EventEntry赋值给mPendingEvent
               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.
       ALOG_ASSERT(mPendingEvent != NULL);
       bool done = false;
       DropReason dropReason = DROP_REASON_NOT_DROPPED;
       if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
           dropReason = DROP_REASON_POLICY;
       } else if (!mDispatchEnabled) {
           dropReason = DROP_REASON_DISABLED;
       }
   
       if (mNextUnblockedEvent == mPendingEvent) {
           mNextUnblockedEvent = NULL;
       }
   
       switch (mPendingEvent->type) {
       case EventEntry::TYPE_CONFIGURATION_CHANGED: {
           ConfigurationChangedEntry* typedEntry =
                   static_cast<ConfigurationChangedEntry*>(mPendingEvent);
           done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
           dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
           break;
       }
   
       case EventEntry::TYPE_DEVICE_RESET: {
           DeviceResetEntry* typedEntry =
                   static_cast<DeviceResetEntry*>(mPendingEvent);
           done = dispatchDeviceResetLocked(currentTime, typedEntry);
           dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
           break;
       }
   
       case EventEntry::TYPE_KEY: {
           KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
           if (isAppSwitchDue) {
               if (isAppSwitchKeyEventLocked(typedEntry)) {
                   resetPendingAppSwitchLocked(true);
                   isAppSwitchDue = false;
               } else if (dropReason == DROP_REASON_NOT_DROPPED) {
                   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 = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
           break;
       }
   
       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;
       }
   
       default:
           ALOG_ASSERT(false);
           break;
       }
   
       if (done) {
        if (dropReason != DROP_REASON_NOT_DROPPED) {
               dropInboundEventLocked(mPendingEvent, dropReason);
        }
           mLastDropReason = dropReason;
   
           //释放本次事件处理对象
        releasePendingEventLocked();
           //使InputDispatcher能够快速处理下一个分发事件。
           *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
       }
   }

dispatchMotionLocked

这里两条线,
1.findTouchedWindowTargetLocked 负责找到要分发的Window
2.dispatchEventLocked 负责具体分发目标

///frameworks/native/services/inputflinger/InputDispatcher.cpp
bool InputDispatcher::dispatchMotionLocked(
        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
    // Preprocessing.
    if (! entry->dispatchInProgress) {
        //标记当前已经进入分发流程
        entry->dispatchInProgress = true;

        logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
    }

    //如果事件是需要丢弃的,则返回true,不会为该事件寻找合适的窗口
    // 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)负责找到要分发的Window
        injectionResult = findTouchedWindowTargetsLocked(currentTime,
                entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
    } else {
        //处理非触摸形式的事件 比如轨迹球。
        // Non touch event.  (eg. trackball)负责找到要分发的Window
        injectionResult = findFocusedWindowTargetsLocked(currentTime,
                entry, inputTargets, nextWakeupTime);
    }
    //输入事件被挂起,说明找到了窗口并且窗口无响应。
    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
        return false;
    }

    setInjectionResultLocked(entry, injectionResult);
    //输入事件没有分发成功,说明没有找到合适的窗口。
    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
        if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
            CancelationOptions::Mode mode(isPointerEvent ?
                    CancelationOptions::CANCEL_POINTER_EVENTS :
                 CancelationOptions::CANCEL_NON_POINTER_EVENTS);
            CancelationOptions options(mode, "input event injection failed");
         synthesizeCancelationEventsForMonitorsLocked(options);
        }
     return true;
    }

    //将分发的目标添加到inputTargets列表中。
    addMonitoringTargetsLocked(inputTargets);

    // Dispatch the motion.
    if (conflictingPointerActions) {
        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
                "conflicting pointer actions");
        synthesizeCancelationEventsForAllConnectionsLocked(options);
    }
    //将事件分发给inputTargets列表的目标。
    dispatchEventLocked(currentTime, entry, inputTargets);//负责具体分发目标
    return true;
}

我们先分析findTouchedWindowTargetLocked这条线。

这是一个很长的方法,省略一些无关的代码。大体是判断这个事件的类型,获取能够处理这个事件的forceground window,如果这个window不能够继续处理事件,就是说这个window的主线程被某些耗时操作占据,handleTargetsNotReadyLocked这个方法主要是判定当前的window是否发生ANR如果没有则处理下面的addWindowTargetLocked。

///frameworks/native/services/inputflinger/InputDispatcher.cpp
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
        const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
        bool* outConflictingPointerActions) {

......
    //确保所有触摸过的前台窗口都为新的输入做好了准备
      for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
        const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
        if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
            // Check whether the window is ready for more input.
            //检查窗口是否准备好接收更多的输入。
            std::string reason = checkWindowReadyForMoreInputLocked(currentTime,
                    touchedWindow.windowHandle, entry, "touched");
            if (!reason.empty()) {
                //如果窗口没有准备好,则将原因赋值给injectionResult
                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
                        NULL, touchedWindow.windowHandle, nextWakeupTime, reason.c_str());
                goto Unresponsive;
            }
        }
    }  
    ......
        
        
          // Success!  Output targets.窗口检查成功
    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;

    //遍历mTempTouchState中的窗口
    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
        const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
       //为每个mTempTouchState中的窗口生成inputTargets
        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这里主要的目的是将inputChannel添加至InputTarget中

///frameworks/native/services/inputflinger/InputDispatcher.cpp
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;
}

我们在看看另一条线dispatchEventLocked(向目标窗口发送事件)

///frameworks/native/services/inputflinger/InputDispatcher.cpp
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);

    //遍历inputTargets列表
    for (size_t i = 0; i < inputTargets.size(); i++) {
        const InputTarget& inputTarget = inputTargets.itemAt(i);

        //根据inputTarget内部的inputChannel来获取Connection的索引。
        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
        if (connectionIndex >= 0) {
            //获取mConnectionsByFd容器中的Connection
            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
            //手动注意
            //根据inputTarget开始事件发送循环。
            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().c_str());
#endif
        }
    }
}

prepareDispatchCycleLocked

///frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
#if DEBUG_DISPATCH_CYCLE
    ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
            "xOffset=%f, yOffset=%f, scaleFactor=%f, "
            "pointerIds=0x%x",
            connection->getInputChannelName().c_str(), inputTarget->flags,
            inputTarget->xOffset, inputTarget->yOffset,
            inputTarget->scaleFactor, inputTarget->pointerIds.value);
#endif

    // 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) {
#if DEBUG_DISPATCH_CYCLE
        ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
                connection->getInputChannelName().c_str(), connection->getStatusLabel());
#endif
        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
            }
#if DEBUG_FOCUS
            ALOGD("channel '%s' ~ Split motion event.",
                    connection->getInputChannelName().c_str());
            logOutboundMotionDetailsLocked("  ", splitMotionEntry);
#endif
            //手动注意
            enqueueDispatchEntriesLocked(currentTime, connection,
                    splitMotionEntry, inputTarget);
            splitMotionEntry->release();
            return;
        }
    }

    // Not splitting.  Enqueue dispatch entries for the event as is.
    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}

enqueueDispatchEntriesLocked

该方法主要功能:

  • 根据dispatchMode来决定是否需要加入outboundQueue队列;

  • 根据EventEntry,来生成DispatchEntry事件;

  • 将dispatchEntry加入到connection的outbound队列.

    执行到这里,其实等于又做了一次搬运的工作,将InputDispatcher中mlnboundQueue中的事件取出后,找到目标window后,封装dispatchEntry加入到connection的outbound队列.

///frameworks/native/services/inputflinger/InputDispatcher.cpp
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);
    }
}

startDispatchCycleLocked

startDispatchCycleLocked的主要功能:从outboundQueue中取出事件,重新放入waitQueue队列

startDispatchCycleLocked触发时机:当起初connection.outboundQueue等于空,经enqueueDispatchEntryLocked处理后,outboundQueue不等于空。

///frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection) {
#if DEBUG_DISPATCH_CYCLE
    ALOGD("channel '%s' ~ startDispatchCycle",
            connection->getInputChannelName().c_str());
#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: {
            KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);

            // Publish the key event.
            status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
                    keyEntry->deviceId, keyEntry->source,
                    dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
                    keyEntry->keyCode, keyEntry->scanCode,
                    keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
                    keyEntry->eventTime);
            break;
        }

        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;
            if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
                    && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
                float scaleFactor = dispatchEntry->scaleFactor;
                xOffset = dispatchEntry->xOffset * scaleFactor;
                yOffset = dispatchEntry->yOffset * scaleFactor;
                if (scaleFactor != 1.0f) {
                    for (uint32_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;

                // We don't want the dispatch target to know.
                if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
                    for (uint32_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, motionEntry->displayId,
                    dispatchEntry->resolvedAction, motionEntry->actionButton,
                    dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
                    motionEntry->metaState, motionEntry->buttonState,
                    xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
                    motionEntry->downTime, motionEntry->eventTime,
                    motionEntry->pointerCount, motionEntry->pointerProperties,
                    usingCoords);
            break;
        }

        default:
            ALOG_ASSERT(false);
            return;
        }

        // 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().c_str(),
                            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().c_str());
#endif
                    connection->inputPublisherBlocked = true;
                }
            } else {
                ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
                        "status=%d", connection->getInputChannelName().c_str(), 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的inputPublisher的publishMotionEvent方法将事件分发消耗。

///frameworks/native/services/inputflinger/InputTransport.cpp
status_t InputPublisher::publishMotionEvent(
        uint32_t seq,
        int32_t deviceId,
        int32_t source,
        int32_t displayId,
        int32_t action,
        int32_t actionButton,
        int32_t flags,
        int32_t edgeFlags,
        int32_t metaState,
        int32_t buttonState,
        float xOffset,
        float yOffset,
        float xPrecision,
        float yPrecision,
        nsecs_t downTime,
        nsecs_t eventTime,
        uint32_t pointerCount,
        const PointerProperties* pointerProperties,
        const PointerCoords* pointerCoords) {
#if DEBUG_TRANSPORT_ACTIONS
    ALOGD("channel '%s' publisher ~ 
          publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
            "action=0x%x, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, "
            "metaState=0x%x, buttonState=0x%x, xOffset=%f, yOffset=%f, "
            "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", "
            "pointerCount=%" PRIu32,
            mChannel->getName().c_str(), seq,
            deviceId, source, action, actionButton, flags, edgeFlags, metaState, buttonState,
            xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
#endif

    if (!seq) {
        ALOGE("Attempted to publish a motion event with sequence number 0.");
        return BAD_VALUE;
    }

    if (pointerCount > MAX_POINTERS || pointerCount < 1) {
        ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %" PRIu32 ".",
                mChannel->getName().c_str(), pointerCount);
        return BAD_VALUE;
    }

    InputMessage msg;
    msg.header.type = InputMessage::TYPE_MOTION;
    msg.body.motion.seq = seq;
    msg.body.motion.deviceId = deviceId;
    msg.body.motion.source = source;
    msg.body.motion.displayId = displayId;
    msg.body.motion.action = action;
    msg.body.motion.actionButton = actionButton;
    msg.body.motion.flags = flags;
    msg.body.motion.edgeFlags = edgeFlags;
    msg.body.motion.metaState = metaState;
    msg.body.motion.buttonState = buttonState;
    msg.body.motion.xOffset = xOffset;
    msg.body.motion.yOffset = yOffset;
    msg.body.motion.xPrecision = xPrecision;
    msg.body.motion.yPrecision = yPrecision;
    msg.body.motion.downTime = downTime;
    msg.body.motion.eventTime = eventTime;
    msg.body.motion.pointerCount = pointerCount;
    for (uint32_t i = 0; i < pointerCount; i++) {
        msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]);
        msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]);
    }
    //最后将消息发送
    return mChannel->sendMessage(&msg);
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈德山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值