Android inputflinger系统分析

本文基于Android 12。

一、InputManagerService启动

SystemServer初始化InputManagerService(),然后调用其start()方法。

InputManagerService()构造方法中和start()分别调用了两个native方法:

1.1NativeImpl() 初始化

     InputManagerService(Injector injector) {
    
    
      		mNative = injector.getNativeService(this);
      }
      
      NativeInputManagerService getNativeService(InputManagerService service) {
    
    
          return new NativeInputManagerService.NativeImpl(service, mContext, mLooper.getQueue());
      }

1.2 start() 启动

     public void start() {
    
    
      		mNative.start();
      }

其中mLooper是DisplayThread.get().getLooper(),DisplayThread是systemserver进程中的单例模式,只能被WindowManager,DisplayManager, InputManager使用。

二、NativeInputManager, InputManager

2.1 NativeInputManager

NativeInputManagerService.NativeImpl()方法初始化NativeInputManager对象,参数中还把InputManagerService和mLooper也一起传递过去了,NativeInputManager定义在jni代码中。

    // com_android_server_input_InputManagerService.cpp
    class NativeInputManager : public virtual RefBase,
        public virtual InputReaderPolicyInterface,
        public virtual InputDispatcherPolicyInterface,
        public virtual PointerControllerPolicyInterface {
    
    }
    
    NativeInputManager::NativeInputManager(jobject contextObj,
            jobject serviceObj, const sp<Looper>& looper) :
            mLooper(looper), mInteractive(true) {
    
    
        JNIEnv* env = jniEnv();
    
        mServiceObj = env->NewGlobalRef(serviceObj);
    
        {
    
    
            AutoMutex _l(mLock);
            mLocked.systemUiLightsOut = false;
            mLocked.pointerSpeed = 0;
            mLocked.pointerAcceleration = android::os::IInputConstants::DEFAULT_POINTER_ACCELERATION;
            mLocked.pointerGesturesEnabled = true;
            mLocked.showTouches = false;
            mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
        }
        mInteractive = true;
    
        InputManager* im = new InputManager(this, this);
        mInputManager = im;
        defaultServiceManager()->addService(String16("inputflinger"), im);
    }
    
    static void nativeStart(JNIEnv* env, jobject nativeImplObj) {
    
    
        NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
    
        status_t result = im->getInputManager()->start();
        if (result) {
    
    
            jniThrowRuntimeException(env, "Input manager could not be started.");
        }
    }
  1. NativeInputManager实现了InputReaderPolicyInterface,InputDispatcherPolicyInterface,PointerControllerPolicyInterface接口,
  2. serviceObj和looper分别赋值给mServiceObj和mLooper变量,后续可以通过mServiceObj调用Java层InputManagerService对象的方法了。
  3. 把自己作为参数实例化InputManager。
  4. 添加“inputflinger”到ServiceManager。

2.2 InputManager

InputManager初始化:

    // InputManager.cpp
    InputManager::InputManager(
            const sp<InputReaderPolicyInterface>& readerPolicy,
            const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    
    
        mDispatcher = createInputDispatcher(dispatcherPolicy);
        mClassifier = std::make_unique<InputClassifier>(*mDispatcher);
        mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);
        mReader = createInputReader(readerPolicy, *mBlocker);
    }

InputManager定义了四个重要的变量,也是一个InputEvent的传递流程:

InputReader -> UnwantedInteractionBlocker -> InputClassifier -> InputDispatcher

  • mReader:通过EventHub监听"/dev/input"事件。
  • mBlocker:拦截不需要的事件。
  • mClassifier:对事件分类。
  • mDispatcher:分发事件。

其中mReader和mDispatcher还传递了NativeInputManager对象参数,赋值到各自的mPolicy变量,后续可直接通过mPolicy调用Java层InputMangerService对象方法。

初始化流程大概就是这样,接着1.2 start()开始启动InputManger。

    // InputManager.cpp
    status_t InputManager::start() {
    
    
        status_t result = mDispatcher->start();
        if (result) {
    
    
            ALOGE("Could not start InputDispatcher thread due to error %d.", result);
            return result;
        }
    
        result = mReader->start();
        if (result) {
    
    
            ALOGE("Could not start InputReader due to error %d.", result);
    
            mDispatcher->stop();
            return result;
        }
    
        return OK;
    }

调用mDispatcher和mReader各自start()方法。

2.2.1 事件传递

事件的传递流程是:InputReader -> UnwantedInteractionBlocker -> InputClassifier -> InputDispatcher

但是查看各个类结构,并没有看到其中相互关联了,原因是使用了代理设计模式:

QueuedListener,UnwantedInteractionBlocker,InputClassifier,InputDispatcher都实现了InputListenerInterface接口,他们都是输入事件的监听者,输入事件的链式传递就是通过QueuedListener实现的,这里使用了代理设计模式,代理对象是InputListenerInterface。

InputListenerInterface定义了事件监听接口:

    // InputListener.h
    class InputListenerInterface {
    
    
    public:
        virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) = 0;
        virtual void notifyKey(const NotifyKeyArgs* args) = 0;
        virtual void notifyMotion(const NotifyMotionArgs* args) = 0;
        virtual void notifySwitch(const NotifySwitchArgs* args) = 0;
        virtual void notifySensor(const NotifySensorArgs* args) = 0;
        virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) = 0;
        virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;
        virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) = 0;
    };

为了实现优雅的链式调用,QueuedListener内部持有一个InputListenerInterface实例化对象mInnerListener,和一个vector mArgsQueue管理所有输入事件,flush()方法遍历mArgsQueue所有输入事件,将其传递给mInnerListener,也就是下一个环节:

    // InputListener.h
    class QueuedInputListener : public InputListenerInterface {
    
    
    public:
      	void flush();
    private:
        InputListenerInterface& mInnerListener;
        std::vector<std::unique_ptr<NotifyArgs>> mArgsQueue;
    };
    
    // InputListner.cpp
    QueuedInputListener::QueuedInputListener(InputListenerInterface& innerListener)
          : mInnerListener(innerListener) {
    
    }
    
    void QueuedInputListener::flush() {
    
    
        for (const std::unique_ptr<NotifyArgs>& args : mArgsQueue) {
    
    
            args->notify(mInnerListener);
        }
        mArgsQueue.clear();
    }

而InputReader,UnwantedInteractionBlocker,InputClassifier都只需要持有QueuedInputListener引用就好了,类设计者不必关心下个环节具体是谁,只需要在处理事件后调用QueuedInputListener.flush()就可以把任务传递下去。

    class InputReader : public InputReaderInterface {
    
    
    private:
      QueuedInputListener mQueuedListener;
    }
    
    class UnwantedInteractionBlocker : public UnwantedInteractionBlockerInterface {
    
    
    private:
      QueuedInputListener mQueuedListener;
    }
    
    class InputClassifier : public InputClassifierInterface {
    
    
    private:
      QueuedInputListener mQueuedListener;
    }

InputManager初始化时实例化了以上对象,构造方法中传递mQueuedListener参数,在实例化的过程中确定了调用链环节。

三、InputReader

mReader = createInputReader(readerPolicy, *mBlocker);初始化InputReader。

    // InputReaderFactory.cpp
    std::unique_ptr<InputReaderInterface> createInputReader(
            const sp<InputReaderPolicyInterface>& policy, InputListenerInterface& listener) {
    
    
        return std::make_unique<InputReader>(std::make_unique<EventHub>(), policy, listener);
    }

InputReaderFactory实例化了一个EventHub对象传递给InputReader构造方法。

3.1 EventHub

    // EventHub.cpp
    EventHub::EventHub(void)
          : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
            mNextDeviceId(1),
            mControllerNumbers(),
            mNeedToSendFinishedDeviceScan(false),
            mNeedToReopenDevices(false),
            mNeedToScanDevices(true),
            mPendingEventCount(0),
            mPendingEventIndex(0),
            mPendingINotify(false) {
    
    
        ensureProcessCanBlockSuspend();
    
        // 1.创建一个新的epoll实例
        mEpollFd = epoll_create1(EPOLL_CLOEXEC);
        LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
    		
        // 2.创建一个新的inotify实例,Inotify API用于检测文件系统变化的机制。Inotify可用于检测单个文件,也可以检测整个目录。
        // 当目录下的设备节点发生增删事件时,可已通过 read(fd) 获取事件的详细信息
        mINotifyFd = inotify_init1(IN_CLOEXEC);
    
        std::error_code errorCode;
        bool isDeviceInotifyAdded = false;
        // 3.添加 /dev/input 或者 /dev 目录的Inotify
        if (std::filesystem::exists(DEVICE_INPUT_PATH, errorCode)) {
    
    
            addDeviceInputInotify();
        } else {
    
    
            addDeviceInotify();
            isDeviceInotifyAdded = true;
        }
    
        struct epoll_event eventItem = {
    
    };
        eventItem.events = EPOLLIN | EPOLLWAKEUP;
        eventItem.data.fd = mINotifyFd;
        // 4. 把 inotify 添加到 epoll 监听队列中,当 inotify 事件到来时,epoll_wait() 会
        // 立即返回,EventHub 可以从 fd 中读取设备节点的增删信息并进行处理
        int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
    
        // 5. 创建管道,fds[0] 表示管道的读端,fds[1] 表示管道的写端
        int wakeFds[2];
        result = pipe2(wakeFds, O_CLOEXEC);
    
        mWakeReadPipeFd = wakeFds[0];
        mWakeWritePipeFd = wakeFds[1];
    		// 设置唤醒读端为非阻塞式
        result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
    		// 设置唤醒写端为非阻塞式
        result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
    
        //6. 把唤醒读端的 fd 添加到 epoll 监听队列中,目的是在必要时唤醒 reader 线程
        eventItem.data.fd = mWakeReadPipeFd;
        result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
    }

EventHub采用INotify + epoll机制实现监听目录/dev/input下的设备节点,后续inputReader的loopOnce循环调用EventHub::getEvents()方法,解析数据封装为RawEvent对象。

3.2 InputReader::start

    // InputReader.cpp
    status_t InputReader::start() {
    
    
        if (mThread) {
    
    
            return ALREADY_EXISTS;
        }
        mThread = std::make_unique<InputThread>(
                "InputReader", [this]() {
    
     loopOnce(); }, [this]() {
    
     mEventHub->wake(); });
        return OK;
    }
    status_t InputReader::stop() {
    
    
        if (mThread && mThread->isCallingThread()) {
    
    
            ALOGE("InputReader cannot be stopped from its own thread!");
            return INVALID_OPERATION;
        }
        mThread.reset();
        return OK;
    }

1.1NativeImpl完成初始化后,1.2 mNative.start()调用InputManager::start()启动InputDispatcher和InputReader。

Start()启动"InputReader"线程,threadLoop()中循环调用loopOnce(),stop()方法调用mThread.reset(),执行mEventHub->wake()。

3.3 InputReader::loopOnce

    // InputReader.cpp
    void InputReader::loopOnce() {
    
    
      	// 1. 通过EventHub读取输入事件
        size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
    
        {
    
    
            std::scoped_lock _l(mLock);
            mReaderIsAliveCondition.notify_all();
    
          	// 2. 处理输入事件
            if (count) {
    
    
                processEventsLocked(mEventBuffer, count);
            }
        }
    		// 3. 清空mQueuedListener,将事件传递给 mBlocker(UnwantedInteractionBlocker)处理
        mQueuedListener.flush();
    }

loopOnce()方法包含了inputReader最主要的运行逻辑,先通过EventHub::getEvents()读取解析/dev/input节点下的事件,processEventsLocked()根据类型处理事件,最后通过QueuedListener传递给下一环,也就是mBlocker(UnwantedInteractionBlocker对象)。

3.3.1 EventHub::getEvents

    size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    
    
      	RawEvent* event = buffer;
        for (;;) {
    
    
          	// 1. 输入设备移除事件
            for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {
    
    
                event->type = DEVICE_REMOVED;
            }
          	// 2. 输入设备添加事件
    	      while (!mOpeningDevices.empty()) {
    
    
              	event->type = DEVICE_ADDED;
            }
          	// 3. 输入设备扫描完成事件
          	if (mNeedToSendFinishedDeviceScan) {
    
    
            		event->type = FINISHED_DEVICE_SCAN;
          	}
          	// 4. 输入事件
          	while (mPendingEventIndex < mPendingEventCount) {
    
    
                if (eventItem.events & EPOLLIN) {
    
    
                    event->when = processEventTimestamp(iev);
                    event->readTime = systemTime(SYSTEM_TIME_MONOTONIC);
                    event->deviceId = deviceId;
                    event->type = iev.type;
                    event->code = iev.code;
                    event->value = iev.value;
                    event += 1;
                    capacity -= 1;
                }
          	}
            int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
            mPendingEventCount = size_t(pollResult);
        }
    }

EventHub通过epoll读取输入事件,封装成RawEvent对象,event->type区分事件类型。

3.3.2 InputReader::processEventsLocked

    void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    
    
        for (const RawEvent* rawEvent = rawEvents; count;) {
    
    
            int32_t type = rawEvent->type;
            size_t batchSize = 1;
          // 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;
                }
                processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
            } else {
    
    
                switch (rawEvent->type) {
    
    
                    // 2.输入设备添加事件,InputDevice
                    case EventHubInterface::DEVICE_ADDED:
                        addDeviceLocked(rawEvent->when, rawEvent->deviceId);
                        break;
                    // 3.输入设备移除事件
                    case EventHubInterface::DEVICE_REMOVED:
                        removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
                        break;
                    // 4.输入设备扫描完成事件
                    case EventHubInterface::FINISHED_DEVICE_SCAN:
                        handleConfigurationChangedLocked(rawEvent->when);
                        break;
                    default:
                        ALOG_ASSERT(false); // can't happen
                        break;
                }
            }
            count -= batchSize;
            rawEvent += batchSize;
        }
    }

从EventHub获取到封装好的RawEvent后,RawEvent保存了事件的原始数据,并没有对事件进行细致的解析,设备添加事件也是一个RawEvent,还有比如用户输入事件,键盘、鼠标、传感器等事件在这里都没有被区分开,processEventsLocked()对原始事件进行处理。

3.3.2.1设备添加事件

先看下设备添加事件DEVICE_ADDED的处理流程:

inputflinger定义了InputDevice类描述输入设备对象,InputMapper把原始事件RawEvent解析成具体对应事件的参数,InputMapper的具体实现类有:

  • CursorInputMapper
  • KeyboardInputMapper
  • TouchInputMapper
  • SensorInputMapper

等等。

addDeviceLocked()调用createDeviceLocked()创建一个InputDevice对象,device->addEventHubDevice(eventHubId)将InputDevice和InputMapper实现类关联起来,添加到mDevices变量管理。

    // InputDevice.h
    private:
    	std::unordered_map<int32_t, DevicePair> mDevices;
    
    // InputDevice.cpp
    void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
    
    
    		
      	// mappers
      	std::vector<std::unique_ptr<InputMapper>> mappers;
      
        if (classes.test(InputDeviceClass::KEYBOARD)) {
    
    
            keyboardSource |= AINPUT_SOURCE_KEYBOARD;
        }
        if (classes.test(InputDeviceClass::TOUCH_MT)) {
    
    
            mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
        } else if (classes.test(InputDeviceClass::TOUCH)) {
    
    
            mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
        }
      	// 添加到 mDevices
       	mDevices.insert({
    
    eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
    }
3.3.2.2 输入事件

对于输入事件,inputReader调用processEventsForDeviceLocked()方法处理:

    // InputReader.cpp
    void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,
                                                   size_t count) {
    
    
      auto deviceIt = mDevices.find(eventHubId);
      device->process(rawEvents, count);
    }

mDevices管理着所有输入设备,找到对应的输入设备调用process()方法。

    // InputDevice.cpp
    void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    
    
        for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
    
    
            for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
    
    
                        mapper.process(rawEvent);
                    });
        }
    }

InputDevice也是从mDevices变量找到对应的InputMapper对象,交给mapper.process(rawEvent);处理。接下来就是InputMapper的各种实现类解析RawEvent数据了,这里我们关注键盘输入KeyboardInputMapper实现类。

KeyboardInputMapper剔除多余不感兴趣的数据,KeyboardInputMapper::processKey()将数据解析封装成一个NotifyKeyArgs对象,交给下一个环节:

    // KeyboardInputMapper.cpp
    void KeyboardInputMapper::process(const RawEvent* rawEvent) {
    
    
        switch (rawEvent->type) {
    
    
            case EV_KEY: {
    
    
                if (isKeyboardOrGamepadKey(scanCode)) {
    
    
                    processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0, scanCode,
                               usageCode);
                }
                break;
            }
        }
    }
    
    void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,
                                         int32_t usageCode) {
    
    
      	NotifyKeyArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
                           getDisplayId(), policyFlags,
                           down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
                           AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
        getListener().notifyKey(&args);
    }

getListener()返回的是InputReader的mQueuedListener对象。

    // InputListener.cpp
    void QueuedInputListener::notifyConfigurationChanged(
            const NotifyConfigurationChangedArgs* args) {
    
    
        traceEvent(__func__, args->id);
        mArgsQueue.emplace_back(std::make_unique<NotifyConfigurationChangedArgs>(*args));
    }

2.2.1小节中提到过,InputListener.mArgsQueue是一个vector数组,保存管理着loopOnce()执行一次读取的所有输入事件,刚解析的键盘输入事件被添加到mArgsQueue变量。

3.3.3 mQueuedListener.flush()

事件的读取解析都完成了,接下来InputReader将处理流程交给下一个环节UnwantedInteractionBlocker了。

    // InputListener.cpp
    void QueuedInputListener::flush() {
    
    
        for (const std::unique_ptr<NotifyArgs>& args : mArgsQueue) {
    
    
            args->notify(mInnerListener);
        }
        mArgsQueue.clear();
    }
    
    void NotifyKeyArgs::notify(InputListenerInterface& listener) const {
    
    
        listener.notifyKey(this);
    }

这里的mInnerListener就是mBlocker,交给mBlocker的notifyKey()方法处理后,清空数组mArgsQueue。

mBlocker将事件传递给mClassifier,mClassifier将事件传递给mDispatcher。

四、InputDispatcher

4.1 InputDispatcher::notifyKey

键盘输入事件传递到InputDispatcher::notifyKey()。

    // InputDispatcher.h
    std::deque<std::shared_ptr<EventEntry>> mInboundQueue GUARDED_BY(mLock);
    
    // InputDispatcher.cpp
    void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
    
    
      
      	// 1.封装成 KeyEvent
        KeyEvent event;
        event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
                         args->action, flags, keyCode, args->scanCode, metaState, repeatCount,
                         args->downTime, args->eventTime);
      	// 2.在event事件入队前处理
        mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
      
        {
    
    
            mLock.lock();
            std::unique_ptr<KeyEntry> newEntry =
            std::make_unique<KeyEntry>(args->id, args->eventTime, args->deviceId, args->source,
                                       args->displayId, policyFlags, args->action, flags,
                                       keyCode, args->scanCode, metaState, repeatCount,
                                       args->downTime);
    		// 3.event入队
            needWake = enqueueInboundEventLocked(std::move(newEntry));
            mLock.unlock();
       }
       // 4.唤醒 mLooper
       if (needWake) {
    
    
           mLooper->wake();
       }
    }

notifyKey主要做了四件事:

  • EventHub将事件读取解析为RawEvent,KeyboardInputMapper将RawEvent封装成NotifyKeyArgs,事件传递到InputDispatcher,终于被封装成了KeyEvent对象。
  • InputDispatcher持有mInboundQueue变量,管理所有到达需要处理的事件,使用EventEntry对象描述,所有需要分发的事件都被封装成EventEntry入队到mInboundQueue。这里在入队之前调用了interceptKeyBeforeQueueing()方法,在事件被设备读取之前先进行一些处理,比如power按键需要对应用程序的生命周期处理,2.2小节提到过,InputDispatcher和InputReader都各自持有mPolicy对象,实际实现是NativeInputManger对象,这样就可以调用Java层的InputMangerService方法了,最终调用到熟悉的PhoneWindowManger.interceptKeyBeforeQueueing()。
      // InputManagerCallback.java
      		/**
           * Provides an opportunity for the window manager policy to intercept early key
           * processing as soon as the key has been read from the device.
           */
          @Override
          public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
          
          
              return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
          }
    
  • 封装成EventEntry入队。
  • 唤醒mLooper开始处理事件分发。

4.2 InputDispatcher::start

2.2小节中,InputManager::start()分别调用了InputDispatcher和InputReader的start()方法,之前已经分析了InputReader.start(),现在看下InputDispatcher.start()的启动过程。

    // InputDispathcer.h
    using Command = std::function<void()>;
    std::deque<Command> mCommandQueue GUARDED_BY(mLock);
    
    // InputDispatcher.cpp
    status_t InputDispatcher::start() {
    
    
        if (mThread) {
    
    
            return ALREADY_EXISTS;
        }
        mThread = std::make_unique<InputThread>(
                "InputDispatcher", [this]() {
    
     dispatchOnce(); }, [this]() {
    
     mLooper->wake(); });
        return OK;
    }

启动"InputDispatcher"线程,循环调用dispatchOnce()方法。

4.3 InputDispatcher::dispatchOnce

    // InputDispatcher.cpp
    void InputDispatcher::dispatchOnce() {
    
    
        nsecs_t nextWakeupTime = LONG_LONG_MAX;
        {
    
    
            std::scoped_lock _l(mLock);
            mDispatcherIsAlive.notify_all();
    
          // 1. 如果mCommandQueue没有待处理的Command,则执行dispatchOnceInnerLocked去产生Command
            if (!haveCommandsLocked()) {
    
    
                dispatchOnceInnerLocked(&nextWakeupTime);
            }
    
          //2. 如果mCommandQueue队列消息不为空,则循环从中取出Command进行处理
            if (runCommandsLockedInterruptable()) {
    
    
                nextWakeupTime = LONG_LONG_MIN;
            }
    
          // 3.判断是否要触发ANR
            const nsecs_t nextAnrCheck = processAnrsLocked();
            nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
    
            if (nextWakeupTime == LONG_LONG_MAX) {
    
    
                mDispatcherEnteredIdle.notify_all();
            }
        }
    
        nsecs_t currentTime = now();
        int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
      // 4. mLooper睡眠等待时间timeoutMillis
        mLooper->pollOnce(timeoutMillis);
    }

mCommandQueue队列变量管理Command对象,Command实际指向一个函数std::function<void()>,执行一些必要特殊的操作,通知Java层的InputMangerService,比如焦点改变:sendFocusChangedCommandLocked(),ANR发生:onAnrLocked()等等。

4.3.1 dispatchOnceInnerLocked

事件的分发逻辑在dispatchOnceInnerLocked()实现:

    // InputDispatcher.cpp
    void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    
    
      	// 1.当前没有在等待的事件,从mInboundQueue获取。
        if (!mPendingEvent) {
    
    
            mPendingEvent = mInboundQueue.front();
            mInboundQueue.pop_front();
        }
      	// 2.根据type分别处理
        switch (mPendingEvent->type) {
    
    
              case EventEntry::Type::MOTION: {
    
    
                  std::shared_ptr<MotionEntry> motionEntry =
                          std::static_pointer_cast<MotionEntry>(mPendingEvent);
                  if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
    
    
                      dropReason = DropReason::APP_SWITCH;
                  }
                  if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
    
    
                      dropReason = DropReason::STALE;
                  }
                  if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
    
    
                      dropReason = DropReason::BLOCKED;
                  }
                  done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);
                  break;
              }
      	}
    }

mPendingEvent保存当前处理的事件,没有的话从mInboundQueue队列中取出,4.1小节enqueueInboundEventLocked()方法,键盘输入事件就被封装成EventEntry入队到mInboundQueue队列中,后续将在这里被处理。

这里我们关心MOTION触屏输入事件,继续交给dispatchMotionLocked()处理。

4.3.2 dispatchMotionLocked

    // InputDispatcher.cpp
    bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<MotionEntry> entry,
                                               DropReason* dropReason, nsecs_t* nextWakeupTime) {
    
    
      	const bool isPointerEvent = isFromSource(entry->source, AINPUT_SOURCE_CLASS_POINTER);
        // Identify targets.
        std::vector<InputTarget> inputTargets;
        if (isPointerEvent) {
    
    
            // Pointer event.  (eg. touchscreen)
            injectionResult =
                    findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime,
                                                   &conflictingPointerActions);
        } else {
    
    
            // Non touch event.  (eg. trackball)
            injectionResult =
                    findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
        }
        dispatchEventLocked(currentTime, entry, inputTargets);
      	return true;
    }

isPointerEvent区分是触摸屏幕还是轨迹球,InputTarget具体说明了输入事件如何分发到具体的window上,其中保存了数据传输路径InputChannel等。

为了找到正确的焦点窗口,mFocusedApplicationHandlesByDisplay变量保存了当前持有焦点的App,每启动一个新的App,焦点App都会通过InputMonitor更新,InputMonitor在View的显示过程中被初始化:https://blog.csdn.net/qq_36063677/article/details/129908973:

    // InputMonitor.java
    		void setFocusedAppLw(ActivityRecord newApp) {
    
    
            // Focused app has changed.
            mService.mInputManager.setFocusedApplication(mDisplayId,
                    newApp != null ? newApp.getInputApplicationHandle(true /* update */) : null);
        }
    
    // InputDispatcher.cpp
    		// Focused applications.
        std::unordered_map<int32_t, std::shared_ptr<InputApplicationHandle>>
                mFocusedApplicationHandlesByDisplay GUARDED_BY(mLock);

mFocusedWindowTokenByDisplay变量保存了各个Display设备(考虑到多个显示设备的情况)当前的焦点Window,由surfaceflinger进程负责更新:

    // SurfaceFlinger.cpp
    void SurfaceFlinger::updateInputFlinger() {
    
    
        for (const auto& focusRequest : inputWindowCommands.focusRequests) {
    
    
            inputFlinger->setFocusedWindow(focusRequest);
        }
    }
    // FocusResolver.h
    std::unordered_map<int32_t /* displayId */, NamedToken> mFocusedWindowTokenByDisplay;

对于触摸屏幕,findTouchedWindowTargetsLocked()对分屏的使用情景进行了适配,isSplit变量标识当前是否处于分屏状态。

找到了正确的inputTargets后,dispatchEventLocked(currentTime, entry, inputTargets);继续分发过程。

4.3.3 dispatchEventLocked

    // InputDispatcher.cpp
    void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
                                              std::shared_ptr<EventEntry> eventEntry,
                                              const std::vector<InputTarget>& inputTargets) {
    
    
        for (const InputTarget& inputTarget : inputTargets) {
    
    
            sp<Connection>   =
                    getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
            if (connection != nullptr) {
    
    
                prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
            }
        }
    }

getConnectionLocked()方法通过InputChannel的token获取链接Connection对象,mConnectionsByToken是一个map变量,InputDispatcher维护mConnectionsByToken变量,保存所有当前连接的Connection,key值是token,Binder类型。关于InputChanel的建立,参考下一章节。

接下来prepareDispatchCycleLocked()调用enqueueDispatchEntriesLocked()方法:

4.3.4 enqueueDispatchEntriesLocked

    void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
                                                       const sp<Connection>& connection,
                                                       std::shared_ptr<EventEntry> eventEntry,
                                                       const InputTarget& inputTarget) {
    
    
      	// 1. 添加分发条目到队列连接对象 connection
        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);
      
        // 2. 开始分发
        if (wasEmpty && !connection->outboundQueue.empty()) {
    
    
            startDispatchCycleLocked(currentTime, connection);
        }
    }

enqueueDispatchEntryLocked()添加分发条目到队列连接对象Connection,然后开始分发工作,查看enqueueDispatchEntryLocked()具体实现:

4.3.4.1 enqueueDispatchEntryLocked
    void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
                                                     std::shared_ptr<EventEntry> eventEntry,
                                                     const InputTarget& inputTarget,
                                                     int32_t dispatchMode) {
    
    
    		// 1. 封装 DispatchEntry对象                                    
        std::unique_ptr<DispatchEntry> dispatchEntry =
                createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);
      	// 2. 添加到 connection->outboundQueue队列
      	connection->outboundQueue.push_back(dispatchEntry.release());
    }

在这里EventEntry又被解析封装成DispatchEntry对象,专门用于分发工作。

回到分发流程startDispatchCycleLocked()。

4.3.4.2 startDispatchCycleLocked
    void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
                                                   const sp<Connection>& connection) {
    
    
      
        while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
    
    
          DispatchEntry* dispatchEntry = connection->outboundQueue.front();
          switch (eventEntry.type) {
    
    
              case EventEntry::Type::MOTION: {
    
    
                // Publish the motion event.
                    status = connection->inputPublisher
                                       .publishMotionEvent(dispatchEntry->seq,
                                                         dispatchEntry->resolvedEventId,
                                                         motionEntry.deviceId, motionEntry.source,
                                                         motionEntry.displayId, std::move(hmac),
                                                         dispatchEntry->resolvedAction,
                                                         motionEntry.actionButton,
                                                         dispatchEntry->resolvedFlags,
                                                         motionEntry.edgeFlags, motionEntry.metaState,
                                                         motionEntry.buttonState,
                                                         motionEntry.classification,
                                                         dispatchEntry->transform,
                                                         motionEntry.xPrecision, motionEntry.yPrecision,
                                                         motionEntry.xCursorPosition,
                                                         motionEntry.yCursorPosition,
                                                         dispatchEntry->rawTransform,
                                                         motionEntry.downTime, motionEntry.eventTime,
                                                         motionEntry.pointerCount,
                                                         motionEntry.pointerProperties, usingCoords);
                    break;
              }
          }
          connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
                                                        connection->outboundQueue.end(),
                                                        dispatchEntry));
        }
    }

从connection->outboundQueue不断取出DispatchEntry,调用connection->inputPublisher.publishMotionEvent()发送输入事件,分发完成后在outboundQueue中擦除对象。connection从InputChannel对象获取,InputChannel描述了inputflinger和事件接受对象的连接,那么InputChannel是怎么建立的呢,在(InputChannel文章)继续分析。

猜你喜欢

转载自blog.csdn.net/qq_36063677/article/details/130475299
今日推荐