IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 12 Input系统理解 -> 正文阅读

[移动开发]Android 12 Input系统理解

Android 12 Input系统理解

参考文献:
Input系统—启动篇
Input系统—InputReader线程
Input系统—InputDispatcher线程
Input系统—UI线程
Input系统—事件处理全过程

一、Input系统-事件处理过程

frameworks/native/services/inputflinger/
  - InputDispatcher.cpp
  - InputReader.cpp
  - InputManager.cpp
  - EventHub.cpp
  - InputListener.cpp
frameworks/native/libs/input/
  - InputTransport.cpp
  - Input.cpp
  - InputDevice.cpp
  - Keyboard.cpp
  - KeyCharacterMap.cpp
  - IInputFlinger.cpp

frameworks/base/services/core/
  - java/com/android/server/input/InputManagerService.java
  - jni/com_android_server_input_InputManagerService.cpp

1. Input系统—概述

用户触摸屏幕(TP)或者物理按键,触发的是硬件驱动。驱动将事件写入到输入设备节点;接着输入系统将设备节点经过每一层封装后,成为KeyEvent或者MotionEvent;最后,给到对应窗口(Window)消费该事件。

Input模块主要组成:

  • Native层的InputReader负责从EventHub取出事件并处理,再交给InputDispatcher
  • Native层的InputDispatcher接收来自InputReader的输入事件,并记录WMS的窗口信息,用于派发事件到合适的窗口
  • Java层的InputManagerService跟WMS交互,WMS记录所有窗口信息,并同步更新到IMS,为InputDispatcher正确派发事件到ViewRootImpl提供保障

Input相关动态库:

  • libinputflinger.so:frameworks/native/services/inputflinger/
  • libinputservice.so:frameworks/base/libs/input/
  • libinput.so: frameworks/native/libs/input/

2.Input系统—启动过程

frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
frameworks/native/services/inputflinger/InputManager.cpp

#SystemServer.java
├──startOtherServices()
   └──inputManager = new InputManagerService(context, mActivityManagerService);//InputManagerService初始化
   |  #InputManagerService.java
   |   └──mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
   |      #com_android_server_input_InputManagerService.cpp
   |       ├──nativeInit(JNIEnv* env, jclass /* clazz */,jobject serviceObj, jobject contextObj, jobject messageQueueObj)
   |          └──NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());
   |          └──InputManager* im = new InputManager(this, this);
   |             #InputManager.cpp
   |              └──mDispatcher = createInputDispatcher(dispatcherPolicy);//创建InputDispatcher对象
   |              └──mClassifier = new InputClassifier(mDispatcher);//创建InputClassifier对象
   |              └──mReader = createInputReader(readerPolicy, mClassifier);//创建InputReader对象
   └──inputManager.start();
      #com_android_server_input_InputManagerService.cpp
       └──nativeStart(mPtr);
          #InputManager.cpp
           ├──nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) 
              └──status_t result = mDispatcher->start();
              └──result = mReader->start();

2.1#SystemServer.java

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    ...
    inputManager = new InputManagerService(context, mActivityManagerService);//创建InputManagerService对象
    ...
    wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);//将InputManagerService与WindowManagerService绑定
    ...
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
    ...
    inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());//设置Input回调
    inputManager.start();//启动Input系统
}

2.2#InputManagerService.java

public InputManagerService(Context context, ActivityManagerService ams) {
    ...
    this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());//运行在线程"android.display"
    ...
    mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
    ...
}

2.3#nativeInit

<-com_android_server_input_InputManagerService.cpp>

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
      sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);//获取native消息队列
      ...
      NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());
      im->incStrong(0);
     eturn reinterpret_cast<jlong>(im);
 }

2.4#NativeInputManager

<-com_android_server_input_InputManagerService.cpp>

NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp<Looper>& looper) :mLooper(looper), mInteractive(true) {
    ...
    mServiceObj = env->NewGlobalRef(serviceObj);//上层IMS对象
    ...
    InputManager* im = new InputManager(this, this);// 创建InputManager对象
    ...
}

2.5#InputManager

<-InputManager.cpp>

InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    mClassifier = new InputClassifier(mDispatcher);
    mReader = createInputReader(readerPolicy, mClassifier);
}

2.6#InputDispatcher

<-InputDispatcher.cpp>

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
      : mPolicy(policy),
        mPendingEvent(nullptr),
        mLastDropReason(DropReason::NOT_DROPPED),
        mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
        mAppSwitchSawKeyDown(false),
        mAppSwitchDueTime(LONG_LONG_MAX),
        mNextUnblockedEvent(nullptr),
        mDispatchEnabled(false),
        mDispatchFrozen(false),
        mInputFilterEnabled(false),
        // mInTouchMode will be initialized by the WindowManager to the default device config.
        // To avoid leaking stack in case that call never comes, and for tests,
        // initialize it here anyways.
        mInTouchMode(true),
        mMaximumObscuringOpacityForTouch(1.0f),
        mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
        mWindowTokenWithPointerCapture(nullptr),
        mLatencyAggregator(),
        mLatencyTracker(&mLatencyAggregator),
        mCompatService(getCompatService()) {
     mLooper = new Looper(false);//创建Looper对象
    mReporter = createInputReporter();//创建InputReporter对象
    mKeyRepeatState.lastKeyEntry = nullptr;
    policy->getDispatcherConfiguration(&mConfig);//获取分发超时参数
}

该方法主要工作:

  • 创建属于自己线程的Looper对象;
  • 超时参数来自于IMS,参数默认值keyRepeatTimeout = 500,keyRepeatDelay = 50

2.7#InputReader

<-InputReader.cpp>

InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
                         const sp<InputReaderPolicyInterface>& policy,
                         const sp<InputListenerInterface>& listener)
      : mContext(this),
        mEventHub(eventHub),
        mPolicy(policy),
        mGlobalMetaState(0),
        mLedMetaState(AMETA_NUM_LOCK_ON),
        mGeneration(1),
        mNextInputDeviceId(END_RESERVED_ID),
        mDisableVirtualKeysTimeout(LLONG_MIN),
        mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    mQueuedListener = new QueuedInputListener(listener);//创建输入监听对象
    { // acquire lock
        std::scoped_lock _l(mLock);
        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    } // release lock
}

2.8#IMS.start()

<-InputManagerService.java>

public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);
        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);
        registerPointerSpeedSettingObserver();//注册触摸点速度观察者
        registerShowTouchesSettingObserver();//注册是否显示功能的观察者
        registerAccessibilityLargePointerSettingObserver();
        registerLongPressTimeoutObserver();
        registerMaximumObscuringOpacityForTouchSettingObserver();
        registerBlockUntrustedTouchesModeSettingObserver();
        mContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                updatePointerSpeedFromSettings();
                updateShowTouchesFromSettings();
                updateAccessibilityLargePointerFromSettings();
                updateDeepPressStatusFromSettings("user switched");
            }
        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
        updatePointerSpeedFromSettings();//更新触摸点的速度
        updateShowTouchesFromSettings();//更新是否在屏幕上显示触摸点状态
        updateAccessibilityLargePointerFromSettings();
        updateDeepPressStatusFromSettings("just booted");
        updateMaximumObscuringOpacityForTouchFromSettings();
        updateBlockUntrustedTouchesModeFromSettings();
    }

2.8#nativeStart

<-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();//调用InputManager.cpp中start()
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}

2.9#InputManager.start

<-InputManager.cpp>

status_t InputManager::start() {
    status_t result = mDispatcher->start();//启动InputDispatcher线程
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }
    result = mReader->start();//启动InputReader线程
    if (result) {
        ALOGE("Could not start InputReader due to error %d.", result);
        mDispatcher->stop();
        return result;
    }
    return OK;//“OK”代表成功,启动成功
}

3. Input系统—InputReader线程

frameworks/native/services/inputflinger/reader/InputReader.cpp
frameworks/native/services/inputflinger/reader/EventHub.cpp
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
frameworks/native/services/inputflinger/reader/InputDevice.cpp
frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
frameworks/native/services/inputflinger/InputListener.cpp
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
system/core/libutils/Looper.cpp
#InputReader.cpp
├──start()
   └──mThread = std::make_unique<InputThread>( "InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
      └──loopOnce()
      |  └──size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
      |  |  #EventHub.cpp
      |  |   ├──getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize)//通过EventHub(监听目录/dev/input)读取事件放入mEventBuffer, 再将事件input_event转换为RawEvent
      |  |      └──scanDevicesLocked()
      |  |         └──scanDirLocked(const std::string& dirname)
      |  |            └──openDeviceLocked(const std::string& devicePath)
      |  |               └──addDeviceLocked(std::unique_ptr<Device> device)
      |  └──processEventsLocked(mEventBuffer, count);//对事件进行加工, 转换RawEvent -> NotifyKeyArgs(NotifyArgs)
      |  |  └──if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT)
      |  |  |  └──processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,size_t count) 
      |  |  |     └──device->process(rawEvents, count);
      |  |  |        #InputDevice.cpp
      |  |  |         ├──process(const RawEvent* rawEvents, size_t count)
      |  |  |            └──mapper.process(rawEvent);//列举KeyboardInputMapper作为例子
      |  |  |               #KeyboardInputMapper.cpp
      |  |  |                ├──process(const RawEvent* rawEvent)
      |  |  |                   └──processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,int32_t usageCode)
      |  |  |                      └──getListener()->notifyKey(&args);
      |  |  |                         #InputListener.cpp
      |  |  |                          ├──notifyKey(const NotifyKeyArgs* args)
      |  |  |                             └──mArgsQueue.push_back(new NotifyKeyArgs(*args));
      |  |  └──else
      |  |     └──addDeviceLocked(rawEvent->when, rawEvent->deviceId);
      |  |        └──std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
      |  |           └──device->addEventHubDevice(eventHubId);
      |  |           #InputDevice.cpp
      |  |            ├──addEventHubDevice(int32_t eventHubId, bool populateMappers)
      |  |               └──添加各类输入设备
      |  └──mQueuedListener->flush();//将事件发送到InputDispatcher线程
      |     #InputListener.cpp
      |      ├──flush()
      |         └──notify(const sp<InputListenerInterface>& listener)
      |            └──listener->notifyKey(this);
      |               #InputDispatcher.cpp
      |               ├──notifyKey(const NotifyKeyArgs* args)
      |                  └──mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
      |                  |  #com_android_server_input_InputManagerService.cpp
      |                  |   ├──interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags)
      |                  |      └── wmActions = env->CallIntMethod(mServiceObj,gServiceClassInfo.interceptKeyBeforeQueueing, keyEventObj, policyFlags);    
      |                  └──mPolicy->filterInputEvent(&event, policyFlags)
      |                  |  #com_android_server_input_InputManagerService.cpp
      |                  |   ├──filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags)
      |                  |      └── jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,//当inputEventObj不为空,则调用Java层的IMS.filterInputEvent()
      |                  └──needWake = enqueueInboundEventLocked(std::move(newEntry));
      |                  |  #InputDispatcher.cpp
      |                  |   ├──enqueueInboundEventLocked(std::unique_ptr<EventEntry> newEntry)
      |                  |      └──shouldPruneInboundQueueLocked(const MotionEntry& motionEntry)
      |                  |         └──sp<InputWindowHandle> touchedWindowHandle =findTouchedWindowAtLocked(displayId, x, y, nullptr);//查询触摸的窗口
      |                  |         └──std::vector<TouchedMonitor> gestureMonitors = findTouchedGestureMonitorsLocked(displayId, {});//查询可触摸的手势
      |                  └──mLooper->wake();//唤起InputDispatcher线程
      |                     #Looper.cpp
      |                      ├──wake()
      |                         └──ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));
      └──mEventHub->wake(); //唤起EventHub
         #EventHub.cpp
          ├──wake()
             └──nWrite = write(mWakeWritePipeFd, "W", 1);

3.1#start()

<-InputReader.cpp>

status_t InputReader::start() {
    if (mThread) {//mThread不为空,InputReader已存在
        return ALREADY_EXISTS;
    }
    mThread = std::make_unique<InputThread>("InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
    return OK;
}

3.2#loopOnce()

<-InputReader.cpp>

void InputReader::loopOnce() {
    ...
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);//从EventHub读取事件,其中EVENT_BUFFER_SIZE = 256
    { // acquire lock
        std::scoped_lock _l(mLock);
        mReaderIsAliveCondition.notify_all();
        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;
            inputDevices = getInputDevicesLocked();
        }
    } // release lock
    ...
    // Send out a message that the describes the changed input devices.
    if (inputDevicesChanged) {//输入设备发生改变
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }
    mQueuedListener->flush();//发送事件到InputDispatcher
}

3.2#getEvents()

<-EventHub.cpp>

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    ...
    for (;;) {
      ...
        if (mNeedToScanDevices) {
            mNeedToScanDevices = false;
            scanDevicesLocked();//扫描设备
            mNeedToSendFinishedDeviceScan = true;
        }
        ...
      while (mPendingEventIndex < mPendingEventCount) {
        ...
        const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];//从mPendingEventItems读取事件项
        ...
        if (eventItem.data.fd == mWakeReadPipeFd) {
                if (eventItem.events & EPOLLIN) {
                    ALOGV("awoken after wake()");
                    awoken = true;
                    char wakeReadBuffer[16];
                    ssize_t nRead;
                    do {
                        nRead = read(mWakeReadPipeFd, wakeReadBuffer, sizeof(wakeReadBuffer));//从wakeReadBuffer中读取事件
                    } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(wakeReadBuffer));
                } else {
                    ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
                          eventItem.events);
                }
                continue;
        }
        ...
        // This must be an input event
        if (eventItem.events & EPOLLIN) {
             int32_t readSize = read(device->fd, readBuffer, sizeof(struct input_event) * capacity); //从设备不断读取事件,放入到readBuffer
             if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
                    // Device was removed before INotify noticed.
                    deviceChanged = true;
                    closeDeviceLocked(*device);
             }
             ...
             }else{
                   int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
                    size_t count = size_t(readSize) / sizeof(struct input_event);
                    for (size_t i = 0; i < count; i++) {
                        struct input_event& iev = readBuffer[i];//获取readBuffer的数据
                        event->when = processEventTimestamp(iev);//将input_event信息, 封装成RawEvent
                        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;
                    }
                    if (capacity == 0) {
                        // The result buffer is full.  Reset the pending event index
                        // so we will try to read the device again on the next iteration.
                        mPendingEventIndex -= 1;
                        break;
                    }
             }
             ...
        }
        ...
      }
      ...
      mLock.unlock(); // release lock before poll
      int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);//等待input事件的到来
      mLock.lock(); // reacquire lock after poll
      ...
    }
    ...
    return event - buffer; //返回所读取的事件个数
}

EventHub采用INotify + epoll机制实现监听目录/dev/input下的设备节点。

3.3设备扫描

<-EventHub.cpp>

void EventHub::scanDevicesLocked() {
    status_t result = scanDirLocked(DEVICE_PATH);//DEVICE_PATH="/dev/input"
    if (result < 0) {
        ALOGE("scan dir failed for %s", DEVICE_PATH);
    }
    if (isV4lScanningEnabled()) {
        result = scanVideoDirLocked(VIDEO_DEVICE_PATH);
        if (result != OK) {
            ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
        }
    }
    if (mDevices.find(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) == mDevices.end()) {
        createVirtualKeyboardLocked();
    }
}

status_t EventHub::scanDirLocked(const std::string& dirname) {
    for (const auto& entry : std::filesystem::directory_iterator(dirname)) {//读取/dev/input/目录下所有的设备节点
        openDeviceLocked(entry.path());//打开相应的设备节点
    }
    return 0;
}

void EventHub::openDeviceLocked(const std::string& devicePath) {
    ...
    int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);//打开设备文件
    InputDeviceIdentifier identifier;
    //获取设备名称
    if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
        ALOGE("Could not get device name for %s: %s", devicePath.c_str(), strerror(errno));
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.name = buffer;
    }
    ...
    // Get device identifier.
    struct input_id inputId;
    if (ioctl(fd, EVIOCGID, &inputId)) {
        ALOGE("could not get device input id for %s, %s\n", devicePath.c_str(), strerror(errno));
        close(fd);
        return;
    }
    identifier.bus = inputId.bustype;
    identifier.product = inputId.product;
    identifier.vendor = inputId.vendor;
    identifier.version = inputId.version;
    // Get device physical location.
    if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
        // fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.location = buffer;
    }
    // Get device unique id.
    if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
        // fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.uniqueId = buffer;
    }
    // Fill in the descriptor.
    assignDescriptorLocked(identifier);
    ...
    // Load the configuration file for the device.
    device->loadConfigurationLocked();
    ...
    addDeviceLocked(std::move(device));
}

void EventHub::addDeviceLocked(std::unique_ptr<Device> device) {
    reportDeviceAddedForStatisticsLocked(device->identifier, device->classes);
    mOpeningDevices.push_back(std::move(device));
}

3.4 设备增加

3.4.1#processEventsLocked()

<-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
            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;
    }
}
3.4.2#addDeviceLocked

<-InputReader.cpp>

void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
    if (mDevices.find(eventHubId) != mDevices.end()) {
        ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);
        return;//已添加的相同设备则不再添加
    }
    InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
    std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
    device->configure(when, &mConfig, 0);
    device->reset(when);
    ...
    mDevices.emplace(eventHubId, device);
    // Add device to device to EventHub ids map.
    const auto mapIt = mDeviceToEventHubIdsMap.find(device);
    if (mapIt == mDeviceToEventHubIdsMap.end()) {
        std::vector<int32_t> ids = {eventHubId};
        mDeviceToEventHubIdsMap.emplace(device, ids);
    } else {
        mapIt->second.push_back(eventHubId);
    }
    ...
}

std::shared_ptr<InputDevice> InputReader::createDeviceLocked( int32_t eventHubId, const InputDeviceIdentifier& identifier) {
    ...
    std::shared_ptr<InputDevice> device;
    if (deviceIt != mDevices.end()) {
        device = deviceIt->second;
    } else {
        int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();
        device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(), identifier);
    }
    device->addEventHubDevice(eventHubId);
    return device;
}
3.4.3#addEventHubDevice

<-InputDevice.cpp>

void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
    ...
    // Keyboard-like devices.
    uint32_t keyboardSource = 0;
    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
    if (classes.test(InputDeviceClass::KEYBOARD)) {
        keyboardSource |= AINPUT_SOURCE_KEYBOARD;
    }
    if (classes.test(InputDeviceClass::ALPHAKEY)) {
        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
    }
    if (classes.test(InputDeviceClass::DPAD)) {
        keyboardSource |= AINPUT_SOURCE_DPAD;
    }
    if (classes.test(InputDeviceClass::GAMEPAD)) {
        keyboardSource |= AINPUT_SOURCE_GAMEPAD;
    }
    //添加键盘类设备InputMapper
    if (keyboardSource != 0) {
        mappers.push_back(
                std::make_unique<KeyboardInputMapper>(*contextPtr, keyboardSource, keyboardType));
    }
    //添加鼠标类设备InputMapper
    if (classes.test(InputDeviceClass::CURSOR)) {
        mappers.push_back(std::make_unique<CursorInputMapper>(*contextPtr));
    }
    //添加触摸屏设备InputMapper
    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));
    }
    // Joystick-like devices.
    if (classes.test(InputDeviceClass::JOYSTICK)) {
        mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr));
    }
    // Motion sensor enabled devices.
    if (classes.test(InputDeviceClass::SENSOR)) {
        mappers.push_back(std::make_unique<SensorInputMapper>(*contextPtr));
    }
    // External stylus-like devices.
    if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) {
        mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr));
    }
    // insert the context into the devices set
    mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
    // Must change generation to flag this device as changed
    bumpGeneration();
}

3.5 事件处理

3.5.1#processEventsForDeviceLocked

<-InputReader.cpp>

void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,size_t count) {
    auto deviceIt = mDevices.find(eventHubId);
    if (deviceIt == mDevices.end()) {
        ALOGW("Discarding event for unknown eventHubId %d.", eventHubId);
        return;
    }
    std::shared_ptr<InputDevice>& device = deviceIt->second;
    if (device->isIgnored()) {
        // ALOGD("Discarding event for ignored deviceId %d.", deviceId);
        return;
    }
    device->process(rawEvents, count);
}
3.5.2#process

<-InputDevice.cpp>

void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    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
        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().c_str());
            mDropUntilNextSync = true;
            reset(rawEvent->when);
        } else {
            for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
                mapper.process(rawEvent);//调用具体mapper来处理,见【3.6】按键事件处理
            });
        }
        --count;
    }
}

3.6按键事件处理

3.6.1#KeyboardInputMapper.process

<-KeyboardInputMapper.cpp>

void KeyboardInputMapper::process(const RawEvent* rawEvent) {
    switch (rawEvent->type) {
        case EV_KEY: {
            int32_t scanCode = rawEvent->code;
            int32_t usageCode = mCurrentHidUsage;
            mCurrentHidUsage = 0;
            if (isKeyboardOrGamepadKey(scanCode)) {
                processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0, scanCode,usageCode);//获取所对应的KeyCode
            }
            break;
        }
        case EV_MSC: {
            if (rawEvent->code == MSC_SCAN) {
                mCurrentHidUsage = rawEvent->value;
            }
            break;
        }
        case EV_SYN: {
            if (rawEvent->code == SYN_REPORT) {
                mCurrentHidUsage = 0;
            }
        }
    }
}

void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,int32_t usageCode) {
    if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,&policyFlags)) {
        keyCode = AKEYCODE_UNKNOWN;
        keyMetaState = mMetaState;
        policyFlags = 0;
    }
    if (down) {
        // Rotate key codes according to orientation if needed.
        if (mParameters.orientationAware) {
            keyCode = rotateKeyCode(keyCode, getOrientation());
        }
        // Add key down.
        ssize_t keyDownIndex = findKeyDown(scanCode);
        if (keyDownIndex >= 0) {
            // key repeat, be sure to use same keycode as before in case of rotation
            keyCode = mKeyDowns[keyDownIndex].keyCode;
        } else {
            // key down
            if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
                getContext()->shouldDropVirtualKey(when, keyCode, scanCode)) {
                return;
            }
            if (policyFlags & POLICY_FLAG_GESTURE) {
                getDeviceContext().cancelTouch(when, readTime);
            }
            KeyDown keyDown;
            keyDown.keyCode = keyCode;
            keyDown.scanCode = scanCode;
            mKeyDowns.push_back(keyDown);
        }
        mDownTime = when;//记录按下时间点
    } else {
        // Remove key down.
        ssize_t keyDownIndex = findKeyDown(scanCode);
        if (keyDownIndex >= 0) {
            // key up, be sure to use same keycode as before in case of rotation
            keyCode = mKeyDowns[keyDownIndex].keyCode;
            mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);//键抬起操作,则擦除按下事件
        } else {
            // key was not actually down
            ALOGI("Dropping key up from device %s because the key was not down.  " "keyCode=%d, scanCode=%d", getDeviceName().c_str(), keyCode, scanCode);
            return;
        }
    }
    nsecs_t downTime = mDownTime;
    ...
    //创建NotifyKeyArgs对象, when记录eventTime, downTime记录按下时间;
    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);//通知key事件
}
3.6.2#QueuedInputListener.notifyKey

<-InputListener.cpp>

void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
    traceEvent(__func__, args->id);
    mArgsQueue.push_back(new NotifyKeyArgs(*args));
}

mArgsQueue的数据类型为Vector<NotifyArgs*>,将该key事件压人该栈顶。 到此,整个事件加工完成, 再然后就是将事件发送给InputDispatcher线程.
接下来,再回调InputReader的loopOnce过程, 可知当执行完processEventsLocked()过程, 然后便开始执行mQueuedListener->flush()过程, 如下文.

3.7#QueuedListener

3.7.1#flush()

<-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);//mInnerListener是InputDispatcher对象
        delete args;
    }
    mArgsQueue.clear();
}

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

  • NotifyConfigurationChangedArgs
  • NotifyKeyArgs
  • NotifyMotionArgs
  • NotifySwitchArgs
  • NotifyDeviceResetArgs

接着3.6节,可知此处是NotifyKeyArgs对象

3.7.2#NotifyKeyArgs.notify

<-InputListener.cpp>

void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
    listener->notifyKey(this);
}
3.7.3#InputDispatcher.notifyKey

<-InputDispatcher.cpp>

void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
   ...
   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);//初始化KeyEvent对象
   ...
   mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
   if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
        ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
              std::to_string(t.duration().count()).c_str());
    }
    bool needWake;
    { // acquire lock
        mLock.lock();
        if (shouldSendKeyToInputFilterLocked(args)) {
            mLock.unlock();
            policyFlags |= POLICY_FLAG_FILTERED;
            if (!mPolicy->filterInputEvent(&event, policyFlags)) {//mPolicy是指NativeInputManager对象
                return; // event was consumed by the filter
            }
            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);//创建KeyEntry对象
        needWake = enqueueInboundEventLocked(std::move(newEntry));//将KeyEntry放入队列
        mLock.unlock();
    } // release lock
    if (needWake) {
        mLooper->wake();//唤醒InputDispatcher线程
    }
}

该方法的主要功能:

  1. 调用NativeInputManager.interceptKeyBeforeQueueing,加入队列前执行拦截动作,但并不改变流程,调用链:
  • IMS.interceptKeyBeforeQueueing
  • InputMonitor.interceptKeyBeforeQueueing (继承IMS.WindowManagerCallbacks)
  • PhoneWindowManager.interceptKeyBeforeQueueing (继承WindowManagerPolicy)
  1. 当mInputFilterEnabled=true(该值默认为false,可通过setInputFilterEnabled设置),则调用NativeInputManager.filterInputEvent过滤输入事件;当返回值为false则过滤该事件,不再往下分发;
  2. 生成KeyEvent,并调用enqueueInboundEventLocked,将该事件加入到InputDispatcherd的成员变量mInboundQueue。

3.7.4#interceptKeyBeforeQueueing

<-com_android_server_input_InputManagerService.cpp>

void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
    ...
    if ((policyFlags & POLICY_FLAG_TRUSTED)) {
        nsecs_t when = keyEvent->getEventTime();//获取按下的时间
        JNIEnv* env = jniEnv();
        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
        jint wmActions;
        if (keyEventObj) {
            wmActions = env->CallIntMethod(mServiceObj,
                    gServiceClassInfo.interceptKeyBeforeQueueing,//调用Java层的IMS.interceptKeyBeforeQueueing
                    keyEventObj, policyFlags);
           ...
        } else {
            ...
        }
        handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
    } else {
       ...
    }
}

3.7.5#filterInputEvent

<-com_android_server_input_InputManagerService.cpp>

bool NativeInputManager::filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
    jobject inputEventObj;
    JNIEnv* env = jniEnv();
    switch (inputEvent->getType()) {
    case AINPUT_EVENT_TYPE_KEY:
        inputEventObj = android_view_KeyEvent_fromNative(env,
                static_cast<const KeyEvent*>(inputEvent));
        break;
    case AINPUT_EVENT_TYPE_MOTION:
        inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
                static_cast<const MotionEvent*>(inputEvent));
        break;
    default:
        return true; // dispatch the event normally
    }
    if (!inputEventObj) {
        ALOGE("Failed to obtain input event object for filterInputEvent.");
        return true; // dispatch the event normally
    }
    // The callee is responsible for recycling the event.
    jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,//当inputEventObj不为空,则调用Java层的IMS.filterInputEvent()
            inputEventObj, policyFlags);
    if (checkAndClearExceptionFromCallback(env, "filterInputEvent")) {
        pass = true;
    }
    env->DeleteLocalRef(inputEventObj);
    return pass;
}

3.7.6#enqueueInboundEventLocked

<-InputDispatcher.cpp>

bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newEntry) {
    ...
    switch (entry.type) {
        case EventEntry::Type::KEY: {
            // Optimize app switch latency.
            // If the application takes too long to catch up then we drop all events preceding
            // the app switch key.
            const KeyEntry& keyEntry = static_cast<const KeyEntry&>(entry);
            if (isAppSwitchKeyEvent(keyEntry)) {
                if (keyEntry.action == AKEY_EVENT_ACTION_DOWN) {
                    mAppSwitchSawKeyDown = true;
                } else if (keyEntry.action == AKEY_EVENT_ACTION_UP) {
                    if (mAppSwitchSawKeyDown) {
#if DEBUG_APP_SWITCH
                        ALOGD("App switch is pending!");
#endif
                        mAppSwitchDueTime = keyEntry.eventTime + APP_SWITCH_TIMEOUT;
                        mAppSwitchSawKeyDown = false;
                        needWake = true;
                    }
                }
            }
            break;
        }
        case EventEntry::Type::MOTION: {
            if (shouldPruneInboundQueueLocked(static_cast<MotionEntry&>(entry))) {
                mNextUnblockedEvent = mInboundQueue.back();
                needWake = true;
            }
            break;
        }
        case EventEntry::Type::FOCUS: {
            LOG_ALWAYS_FATAL("Focus events should be inserted using enqueueFocusEventLocked");
            break;
        }
        case EventEntry::Type::CONFIGURATION_CHANGED:
        case EventEntry::Type::DEVICE_RESET:
        case EventEntry::Type::SENSOR:
        case EventEntry::Type::POINTER_CAPTURE_CHANGED:
        case EventEntry::Type::DRAG: {
            // nothing to do
            break;
        }
    }
    return needWake;
}

bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) {
    ...
    if (isPointerDownEvent && mAwaitedFocusedApplication != nullptr) {
        int32_t displayId = motionEntry.displayId;
        int32_t x = static_cast<int32_t>(
                motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
        int32_t y = static_cast<int32_t>(
                motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
        sp<InputWindowHandle> touchedWindowHandle =findTouchedWindowAtLocked(displayId, x, y, nullptr);//查询可触摸的窗口
        if (touchedWindowHandle != nullptr &&
            touchedWindowHandle->getApplicationToken() !=
                    mAwaitedFocusedApplication->getApplicationToken()) {
            // User touched a different application than the one we are waiting on.
            ALOGI("Pruning input queue because user touched a different application while waiting "
                  "for %s",
                  mAwaitedFocusedApplication->getName().c_str());
            return true;
        }
       / / Alternatively, maybe there's a gesture monitor that could handle this event
        std::vector<TouchedMonitor> gestureMonitors = findTouchedGestureMonitorsLocked(displayId, {});//查询可触摸的手势
        for (TouchedMonitor& gestureMonitor : gestureMonitors) {
            sp<Connection> connection =
                    getConnectionLocked(gestureMonitor.monitor.inputChannel->getConnectionToken());
            if (connection != nullptr && connection->responsive) {
                // This monitor could take more input. Drop all events preceding this
                // event, so that gesture monitor could get a chance to receive the stream
                ALOGW("Pruning the input queue because %s is unresponsive, but we have a "
                      "responsive gesture monitor that may handle the event",
                      mAwaitedFocusedApplication->getName().c_str());
                return true;
            }
        }
    }
    ...
}

sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x,
                                                                 int32_t y, TouchState* touchState,
                                                                 bool addOutsideTargets,
                                                                 bool addPortalWindows,
                                                                 bool ignoreDragWindow) {
     ...
     // Traverse windows from front to back to find touched window.
    const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId);
    for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
        if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) {
            continue;
        }
        const InputWindowInfo* windowInfo = windowHandle->getInfo();
        if (windowInfo->displayId == displayId) {
            auto flags = windowInfo->flags;
            if (windowInfo->visible) {
                if (!flags.test(InputWindowInfo::Flag::NOT_TOUCHABLE)) {
                    bool isTouchModal = !flags.test(InputWindowInfo::Flag::NOT_FOCUSABLE) &&
                            !flags.test(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
                    if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
                        int32_t portalToDisplayId = windowInfo->portalToDisplayId;
                        if (portalToDisplayId != ADISPLAY_ID_NONE &&
                            portalToDisplayId != displayId) {
                            if (addPortalWindows) {
                                // For the monitoring channels of the display.
                                touchState->addPortalWindow(windowHandle);
                            }
                            return findTouchedWindowAtLocked(portalToDisplayId, x, y, touchState,
                                                             addOutsideTargets, addPortalWindows);
                        }
                        // Found window.
                        return windowHandle;//找到目标窗口
                    }
                }
                if (addOutsideTargets && flags.test(InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH)) {
                    touchState->addOrUpdateWindow(windowHandle,
                                                  InputTarget::FLAG_DISPATCH_AS_OUTSIDE,
                                                  BitSet32(0));
                }
            }
        }
    }
    return nullptr;                                                        
 }

此处mWindowHandles的赋值过程是由Java层的InputMonitor.setInputWindows(),经过JNI调用后进入InputDispatcher::setInputWindows()方法完成. 进一步说, 就是WMS执行addWindow()过程或许UI改变等场景,都会触发该方法的修改.

3.7.7#Looper.wake

<-Looper.cpp>

void Looper::wake() {
#if DEBUG_POLL_AND_WAKE
    ALOGD("%p ~ wake", this);
#endif
    uint64_t inc = 1;
    ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));
    if (nWrite != sizeof(uint64_t)) {
        if (errno != EAGAIN) {
            LOG_ALWAYS_FATAL("Could not write wake signal to fd %d (returned %zd): %s",
                             mWakeEventFd.get(), nWrite, strerror(errno));
        }
    }
}

【3.7】小节过程会调用enqueueInboundEventLocked()方法来决定是否需要将数字1写入句柄mWakeEventFd来唤醒InputDispatcher线程. 满足唤醒的条件:

  • 执行enqueueInboundEventLocked方法前,mInboundQueue队列为空,执行完必然不再为空,则需要唤醒分发线程;
  • 当事件类型为key事件,且发生一对按下和抬起操作,则需要唤醒;
  • 当事件类型为motion事件,且当前可触摸的窗口属于另一个应用,则需要唤醒.

3.8 小结

InputReader整个过程涉及多次事件封装转换,其主要工作核心是以下三大步骤:

  • getEvents:通过EventHub(监听目录/dev/input)读取事件放入mEventBuffer,而mEventBuffer是一个大小为256的数组, 再将事件input_event转换为RawEvent;
  • processEventsLocked: 对事件进行加工, 转换RawEvent -> NotifyKeyArgs(NotifyArgs)
  • QueuedListener->flush:将事件发送到InputDispatcher线程, 转换NotifyKeyArgs -> KeyEntry(EventEntry)

InputReader线程不断循环地执行InputReader.loopOnce(), 每次处理完生成的是EventEntry(比如KeyEntry, MotionEntry), 接下来的工作就交给InputDispatcher线程。

4. Input系统—InputDispatcher线程

frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
frameworks/native/libs/input/InputTransport.cpp
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
#InputDispatcher.cpp
 ├──start()
    └──mThread = std::make_unique<InputThread>("InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
       └──dispatchOnce()
          └──dispatchOnceInnerLocked(&nextWakeupTime);
          |  └──done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);
          |  |  └──findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry& entry, std::vector<InputTarget>& inputTargets,nsecs_t* nextWakeupTime)
          |  |  |  └──resetNoFocusedWindowTimeoutLocked();
          |  |  |  └──addWindowTargetLocked(focusedWindowHandle, InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,BitSet32(0), inputTargets);//成功找到目标窗口,添加到目标窗口
          |  |  └──addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
          |  |  └──dispatchEventLocked(currentTime, entry, inputTargets);
          |  |     └──updateInteractionTokensLocked(*eventEntry, inputTargets);
          |  |     └──pokeUserActivityLocked(*eventEntry);//向mCommandQueue队列添加doPokeUserActivityLockedInterruptible命令
          |  |     |  └──std::unique_ptr<CommandEntry> commandEntry =std::make_unique<CommandEntry>(&InputDispatcher::doPokeUserActivityLockedInterruptible);
          |  |     |  |  └── mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType,commandEntry->displayId);
          |  |     |  |      #com_android_server_input_InputManagerService.cpp
          |  |     |  |       ├──pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId)
          |  |     |  |          └──android_server_PowerManagerService_userActivity(eventTime, eventType, displayId);
          |  |     |  |             #com_android_server_power_PowerManagerService.cpp
          |  |     |  |              ├──env->CallVoidMethod(gPowerManagerServiceObj,gPowerManagerServiceClassInfo.userActivityFromNative,nanoseconds_to_milliseconds(eventTime), eventType, displayId, 0);
          |  |     |  |                 └──android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType,int32_t displayId)
          |  |     |  |                    #PowerManagerService.java
          |  |     |  |                     ├──userActivityFromNative(long eventTime, int event, int displayId, int flags)
          |  |     |  |                        └──userActivityInternal(int displayId, long eventTime, int event, int flags,int uid)
          |  |     |  └──postCommandLocked(std::move(commandEntry));
          |  |     |     └──mCommandQueue.push_back(std::move(commandEntry));// 将命令加入mCommandQueue队尾
          |  |     └──prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);//找到目标连接
          |  |        └──enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
          |  |           └──enqueueDispatchEntryLocked(const sp<Connection>& connection,std::shared_ptr<EventEntry> eventEntry,const InputTarget& inputTarget,int32_t dispatchMode)
          |  |           |  └──connection->outboundQueue.push_back(dispatchEntry.release());//添加到outboundQueue队尾
          |  |           └──startDispatchCycleLocked(currentTime, connection);
          |  |             #InputTransport.cpp
          |  |              ├──status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
          |  |                 |                      dispatchEntry->resolvedEventId, keyEntry.deviceId,
          |  |                 |                      keyEntry.source, keyEntry.displayId,
          |  |                 |                      std::move(hmac), dispatchEntry->resolvedAction,
          |  |                 |                      dispatchEntry->resolvedFlags, keyEntry.keyCode,
          |  |                 |                      keyEntry.scanCode, keyEntry.metaState,
          |  |                 |                      keyEntry.repeatCount, keyEntry.downTime,
          |  |                 |                      keyEntry.eventTime);//发布Key事件
          |  |                 └──return mChannel->sendMessage(&msg);
          |  └──releasePendingEventLocked();//释放pending事件
          └──runCommandsLockedInterruptible()
          └──mLooper->pollOnce(timeoutMillis);//进入epoll_wait

4.1#start()

<-InputDispatcher.cpp>

status_t InputDispatcher::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }
    mThread = std::make_unique<InputThread>(
            "InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
    return OK;
}

4.2#dispatchOnce()

<-InputDispatcher.cpp>

void InputDispatcher::dispatchOnce() {
     nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        std::scoped_lock _l(mLock);
        mDispatcherIsAlive.notify_all();//唤醒等待线程,monitor()用于监控dispatcher是否发生死锁
        // 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;
        }
        // If we are still waiting for ack on some events,
        // we might have to wake up earlier to check if an app is anr'ing.
        const nsecs_t nextAnrCheck = processAnrsLocked();
        nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
        // We are about to enter an infinitely long sleep, because we have no commands or
        // pending or queued events
        if (nextWakeupTime == LONG_LONG_MAX) {
            mDispatcherEnteredIdle.notify_all();
        }
    } // release lock
    nsecs_t currentTime = now();
    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
    mLooper->pollOnce(timeoutMillis);//进入epoll_wait
}

线程执行Looper->pollOnce,进入epoll_wait等待状态,当发生以下任一情况则退出等待状态:

  • callback:通过回调方法来唤醒;
  • timeout:到达nextWakeupTime时间,超时唤醒;
  • wake: 主动调用Looper的wake()方法;

4.3#dispatchOnceInnerLocked

<-InputDispatcher.cpp>

void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    nsecs_t currentTime = now();//当前时间,也是后面ANR计时的起点
    if (!mDispatchEnabled) { //默认值为false
        resetKeyRepeatLocked();//重置操作
    }
    if (mDispatchFrozen) { //默认值为false
        return; //当分发被冻结,则不再处理超时和分发事件的工作,直接返回
    }
    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;//在enqueueInboundEventLocked()的过程中已设置mAppSwitchDueTime等于eventTime加上500ms
    ...
    switch (mPendingEvent->type) {
        ...
        case EventEntry::Type::KEY: {
            std::shared_ptr<KeyEntry> keyEntry = std::static_pointer_cast<KeyEntry>(mPendingEvent);
            if (isAppSwitchDue) {
                if (isAppSwitchKeyEvent(*keyEntry)) {
                    resetPendingAppSwitchLocked(true);
                    isAppSwitchDue = false;
                } else if (dropReason == DropReason::NOT_DROPPED) {
                    dropReason = DropReason::APP_SWITCH;
                }
            }
            if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *keyEntry)) {
                dropReason = DropReason::STALE;
            }
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
                dropReason = DropReason::BLOCKED;
            }
            done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);// 分发按键事件
            break;
        }
        ...
    }
    ...
    if (done) {//分发操作完成,则进入该分支
        if (dropReason != DropReason::NOT_DROPPED) {
            dropInboundEventLocked(*mPendingEvent, dropReason);
        }
        mLastDropReason = dropReason;
        releasePendingEventLocked();//释放pending事件
        *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
    }
}

该方法主要功能:

  1. mDispatchFrozen用于决定是否冻结事件分发工作不再往下执行;
  2. 当事件分发的时间点距离该事件加入mInboundQueue的时间超过500ms,则认为app切换过期,即isAppSwitchDue=true;
  3. mInboundQueue不为空,则取出头部的事件,放入mPendingEvent变量;并重置ANR时间;
  4. 根据EventEntry的type类型分别处理,比如按键调用dispatchKeyLocked分发事件;再根据分发结果来决定是否进入done;
  5. 执行完成(done)的处理:
  • 根据dropReason(默认NOT_DROPPED不处理)来决定是否丢失事件; dropInboundEventLocked
  • 释放当前正在处理的事件(即mPendingEvent); releasePendingEventLocked

关于dispatchKeyLocked分发事件:

  1. 不会执行done过情况:
  • 当前Event时间小于唤醒时间;
  • 让policy有机会执行拦截操作;
  • 调用findFocusedWindowTargetsLocked方法的返回结果是INPUT_EVENT_INJECTION_PENDING, 即targets没有处于Ready状态;
  1. 会执行done的情况:
  • 该事件需要丢弃, 即dropReason != DROP_REASON_NOT_DROPPED;
  • findFocusedWindowTargetsLocked的返回结果不是INPUT_EVENT_INJECTION_PENDING(没有正在处理的事件);

4.4#dropInboundEventLocked

<-InputDispatcher.cpp>

void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) {
    const char* reason;
    switch (dropReason) {
        case DropReason::POLICY:
#if DEBUG_INBOUND_EVENT_DETAILS
            ALOGD("Dropped event because policy consumed it.");
#endif
            reason = "inbound event was dropped because the policy consumed it";
            break;
        case DropReason::DISABLED:
            if (mLastDropReason != DropReason::DISABLED) {
                ALOGI("Dropped event because input dispatch is disabled.");
            }
            reason = "inbound event was dropped because input dispatch is disabled";
            break;
        case DropReason::APP_SWITCH:
            ALOGI("Dropped event because of pending overdue app switch.");
            reason = "inbound event was dropped because of pending overdue app switch";
            break;
        case DropReason::BLOCKED:
            ALOGI("Dropped event because the current application is not responding and the user "
                  "has started interacting with a different application.");
            reason = "inbound event was dropped because the current application is not responding "
                     "and the user has started interacting with a different application";
            break;
        case DropReason::STALE:
            ALOGI("Dropped event because it is stale.");
            reason = "inbound event was dropped because it is stale";
            break;
        case DropReason::NO_POINTER_CAPTURE:
            ALOGI("Dropped event because there is no window with Pointer Capture.");
            reason = "inbound event was dropped because there is no window with Pointer Capture";
            break;
        case DropReason::NOT_DROPPED: {
            LOG_ALWAYS_FATAL("Should not be dropping a NOT_DROPPED event");
            return;
        }
}

4.5#dispatchKeyLocked

<-InputDispatcher.cpp>

bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<KeyEntry> entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
    ...
    // Handle case where the policy asked us to try again later last time.
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
        if (currentTime < entry->interceptKeyWakeupTime) {// case1: 当前时间小于唤醒时间,则进入等待状态。
            if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
                *nextWakeupTime = entry->interceptKeyWakeupTime;
            }
            return false; // wait until next wakeup
        }
        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
        entry->interceptKeyWakeupTime = 0;
    }
    // Give the policy a chance to intercept the key.
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {//case2: 让policy有机会执行拦截操作
            std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
                    &InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
            sp<IBinder> focusedWindowToken =
                    mFocusResolver.getFocusedWindowToken(getTargetDisplayId(*entry));
            commandEntry->connectionToken = focusedWindowToken;
            commandEntry->keyEntry = entry;
            postCommandLocked(std::move(commandEntry));
            return false; // wait for the command to run
        } else {
            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
        }
    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
        if (*dropReason == DropReason::NOT_DROPPED) {
            *dropReason = DropReason::POLICY;
        }
    }
    // Clean up if dropping the event.
    if (*dropReason != DropReason::NOT_DROPPED) {//case3: 如果需要丢弃该事件,则执行清理操作
        setInjectionResult(*entry,
                           *dropReason == DropReason::POLICY ? InputEventInjectionResult::SUCCEEDED
                                                             : InputEventInjectionResult::FAILED);
        mReporter->reportDroppedKey(entry->id);
        return true;
    }
    // Identify targets.
    std::vector<InputTarget> inputTargets;
    InputEventInjectionResult injectionResult =
            findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);//case4: 寻找焦点
    if (injectionResult == InputEventInjectionResult::PENDING) {
        return false;
    }
    setInjectionResult(*entry, injectionResult);
    if (injectionResult != InputEventInjectionResult::SUCCEEDED) {
        return true;
    }
    // Add monitor channels from event's or focused display.
    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
    // Dispatch the key.
    dispatchEventLocked(currentTime, entry, inputTargets);//只有injectionResult是成功,才有机会执行分发事件
    return true;
}

在以下场景下,有可能无法分发事件:

  • 当前时间小于唤醒时间(nextWakeupTime)的情况;
  • policy需要提前拦截事件的情况;
  • 需要drop事件的情况;
  • 寻找聚焦窗口失败的情况;

如果成功跳过以上所有情况,则会进入执行事件分发的过程。

4.6#findFocusedWindowTargetsLocked

<-InputDispatcher.cpp>

InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked(
        nsecs_t currentTime, const EventEntry& entry, std::vector<InputTarget>& inputTargets,
        nsecs_t* nextWakeupTime) {
    std::string reason;
    int32_t displayId = getTargetDisplayId(entry);
    sp<InputWindowHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId);
    std::shared_ptr<InputApplicationHandle> focusedApplicationHandle =
            getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
    ...
    if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {//找不到目标窗口,抛出ANR并开始计时
        if (!mNoFocusedWindowTimeoutTime.has_value()) {
            // We just discovered that there's no focused window. Start the ANR timer
            std::chrono::nanoseconds timeout = focusedApplicationHandle->getDispatchingTimeout(
                    DEFAULT_INPUT_DISPATCHING_TIMEOUT);
            mNoFocusedWindowTimeoutTime = currentTime + timeout.count();
            mAwaitedFocusedApplication = focusedApplicationHandle;
            mAwaitedApplicationDisplayId = displayId;
            ALOGW("Waiting because no window has focus but %s may eventually add a "
                  "window when it finishes starting up. Will wait for %" PRId64 "ms",
                  mAwaitedFocusedApplication->getName().c_str(), millis(timeout));
            *nextWakeupTime = *mNoFocusedWindowTimeoutTime;
            return InputEventInjectionResult::PENDING;
        } else if (currentTime > *mNoFocusedWindowTimeoutTime) {
            // Already raised ANR. Drop the event
            ALOGE("Dropping %s event because there is no focused window",
                  NamedEnum::string(entry.type).c_str());
            return InputEventInjectionResult::FAILED;
        } else {
            // Still waiting for the focused window
            return InputEventInjectionResult::PENDING;
        }
    }
   // we have a valid, non-null focused window
    resetNoFocusedWindowTimeoutLocked();
    // Check permissions.
    if (!checkInjectionPermission(focusedWindowHandle, entry.injectionState)) {
        return InputEventInjectionResult::PERMISSION_DENIED;
    }
   if (entry.type == EventEntry::Type::KEY) {
        if (shouldWaitToSendKeyLocked(currentTime, focusedWindowHandle->getName().c_str())) {
            *nextWakeupTime = *mKeyIsWaitingForEventsTimeout;
            return InputEventInjectionResult::PENDING;
        }
    }
    // Success!  Output targets.
    addWindowTargetLocked(focusedWindowHandle,//成功找到目标窗口,添加到目标窗口
                          InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
                          BitSet32(0), inputTargets);
    // Done.
    return InputEventInjectionResult::SUCCEEDED;//成功找到目标窗口
}

寻找聚焦窗口失败的情况:

  • 无窗口,无应用:Dropping event because there is no focused window or focused application.(这并不导致ANR的情况,因为没有机会调用handleTargetsNotReadyLocked)
  • 无窗口, 有应用:Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.

4.7#dispatchEventLocked

<-InputDispatcher.cpp>

void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
                                          std::shared_ptr<EventEntry> eventEntry,
                                          const std::vector<InputTarget>& inputTargets) {
    updateInteractionTokensLocked(*eventEntry, inputTargets);
    ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
    pokeUserActivityLocked(*eventEntry);//向mCommandQueue队列添加doPokeUserActivityLockedInterruptible命令
    for (const InputTarget& inputTarget : inputTargets) {
        sp<Connection> connection =
                getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
        if (connection != nullptr) {
            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());
            }
        }
    }
}

该方法主要功能是将eventEntry发送到目标inputTargets.
其中pokeUserActivityLocked(eventEntry)方法最终会调用到Java层的PowerManagerService.java中的userActivityFromNative()方法. 这也是PMS中唯一的native call方法。

4.8#pokeUserActivityLocked

<-InputDispatcher.cpp>

void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) {
    ...
   std::unique_ptr<CommandEntry> commandEntry =
            std::make_unique<CommandEntry>(&InputDispatcher::doPokeUserActivityLockedInterruptible);
    commandEntry->eventTime = eventEntry.eventTime;
    commandEntry->userActivityEventType = eventType;
    commandEntry->displayId = displayId;
    postCommandLocked(std::move(commandEntry));
}

void InputDispatcher::postCommandLocked(std::unique_ptr<CommandEntry> commandEntry) {
    mCommandQueue.push_back(std::move(commandEntry));// 将命令加入mCommandQueue队尾
}

4.9#prepareDispatchCycleLocked

<-InputDispatcher.cpp>

void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
                                                 const sp<Connection>& connection,
                                                 std::shared_ptr<EventEntry> eventEntry,
                                                 const InputTarget& inputTarget) {
    ...
    if (connection->status != Connection::STATUS_NORMAL) {
        return;//当连接已破坏,则直接返回
    }
    ...
    // Not splitting.  Enqueue dispatch entries for the event as is.
    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}

4.10#enqueueDispatchEntriesLocked

<-InputDispatcher.cpp>

void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
                                                   const sp<Connection>& connection,
                                                   std::shared_ptr<EventEntry> eventEntry,
                                                   const InputTarget& inputTarget) {
     bool wasEmpty = connection->outboundQueue.empty();
    // 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.empty()) {//当原先的outbound队列为空, 且当前outbound不为空的情况执行
        startDispatchCycleLocked(currentTime, connection);
    }
}

该方法主要功能:

  • 根据dispatchMode来分别执行DispatchEntry事件加入队列的操作。
  • 当起初connection.outboundQueue等于空, 经enqueueDispatchEntryLocked处理后, outboundQueue不等于空情况下, 则执行startDispatchCycleLocked()方法.

4.11#enqueueDispatchEntryLocked

<-InputDispatcher.cpp>

void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
                                                 std::shared_ptr<EventEntry> eventEntry,
                                                 const InputTarget& inputTarget,
                                                 int32_t dispatchMode) {
    ...
    int32_t inputTargetFlags = inputTarget.flags;
    if (!(inputTargetFlags & dispatchMode)) {
        return;//分发模式不匹配,则直接返回
    }
    inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
    switch (newEntry.type) {
        case EventEntry::Type::KEY: {
            const KeyEntry& keyEntry = static_cast<const KeyEntry&>(newEntry);
            dispatchEntry->resolvedEventId = keyEntry.id;
            dispatchEntry->resolvedAction = keyEntry.action;
            dispatchEntry->resolvedFlags = keyEntry.flags;
            if (!connection->inputState.trackKey(keyEntry, dispatchEntry->resolvedAction,
                                                 dispatchEntry->resolvedFlags)) {
                return; // skip the inconsistent event
            }
            break;
        }
        ...
    }
    ...
    // Enqueue the dispatch entry.
    connection->outboundQueue.push_back(dispatchEntry.release());//添加到outboundQueue队尾
    traceOutboundQueueLength(*connection);
}

该方法主要功能:

  • 根据dispatchMode来决定是否需要加入outboundQueue队列;
  • 根据EventEntry,来生成DispatchEntry事件;
  • 将dispatchEntry加入到connection的outbound队列.

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

4.12#startDispatchCycleLocked

<-InputDispatcher.cpp>

void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
                                               const sp<Connection>& connection) {
    ...
    while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.empty()) {//当Connection状态正常,且outboundQueue不为空
        DispatchEntry* dispatchEntry = connection->outboundQueue.front();
        dispatchEntry->deliveryTime = currentTime;
        const std::chrono::nanoseconds timeout =
                getDispatchingTimeoutLocked(connection->inputChannel->getConnectionToken());
        dispatchEntry->timeoutTime = currentTime + timeout.count();//设置deliveryTime时间
        // Publish the event.
        status_t status;
        const EventEntry& eventEntry = *(dispatchEntry->eventEntry);
        switch (eventEntry.type) {
            case EventEntry::Type::KEY: {
                const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
                std::array<uint8_t, 32> hmac = getSignature(keyEntry, *dispatchEntry);
                // Publish the key event.
                status = connection->inputPublisher//发布Key事件
                                 .publishKeyEvent(dispatchEntry->seq,
                                                  dispatchEntry->resolvedEventId, keyEntry.deviceId,
                                                  keyEntry.source, keyEntry.displayId,
                                                  std::move(hmac), dispatchEntry->resolvedAction,
                                                  dispatchEntry->resolvedFlags, keyEntry.keyCode,
                                                  keyEntry.scanCode, keyEntry.metaState,
                                                  keyEntry.repeatCount, keyEntry.downTime,
                                                  keyEntry.eventTime);
                break;
            }
            ...
        } 
        // Check the result.
        if (status) {//publishKeyEvent失败情况
            if (status == WOULD_BLOCK) {
                if (connection->waitQueue.empty()) {//pipe已满,但waitQueue为空. 不正常的行为
                    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=%s(%d)",
                          connection->getInputChannelName().c_str(), statusToString(status).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
                }
            } else {
                abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);//不不正常的行为
            }
            return;
        }
        // Re-enqueue the event on the wait queue.
        //从outboundQueue中取出事件,重新放入waitQueue队列
        connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
                                                    connection->outboundQueue.end(),
                                                    dispatchEntry));
        traceOutboundQueueLength(*connection);
        connection->waitQueue.push_back(dispatchEntry);
        if (connection->responsive) {
            mAnrTracker.insert(dispatchEntry->timeoutTime,
                               connection->inputChannel->getConnectionToken());
        }
        traceWaitQueueLength(*connection);
    }    
}

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

  • startDispatchCycleLocked触发时机:当起初connection.outboundQueue等于空, 经enqueueDispatchEntryLocked处理后, outboundQueue不等于空。
  • startDispatchCycleLocked主要功能: 从outboundQueue中取出事件,重新放入waitQueue队列
  • publishKeyEvent执行结果status不等于OK的情况下:
  1. WOULD_BLOCK,且waitQueue等于空,则调用abortBrokenDispatchCycleLocked(),该方法最终会调用到Java层的IMS.notifyInputChannelBroken().
  2. WOULD_BLOCK,且waitQueue不等于空,则处于阻塞状态,即inputPublisherBlocked=true
    其他情况,则调用abortBrokenDispatchCycleLocked
  • abortBrokenDispatchCycleLocked()方法最终会调用到Java层的IMS.notifyInputChannelBroken().

4.13#publishKeyEvent

<-InputTransport.cpp>

status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId,
                                         int32_t source, int32_t displayId,
                                         std::array<uint8_t, 32> hmac, int32_t action,
                                         int32_t flags, int32_t keyCode, int32_t scanCode,
                                         int32_t metaState, int32_t repeatCount, nsecs_t downTime,
                                         nsecs_t eventTime) {
    InputMessage msg;
    msg.header.type = InputMessage::Type::KEY;
    msg.header.seq = seq;
    msg.body.key.eventId = eventId;
    msg.body.key.deviceId = deviceId;
    msg.body.key.source = source;
    msg.body.key.displayId = displayId;
    msg.body.key.hmac = std::move(hmac);
    msg.body.key.action = action;
    msg.body.key.flags = flags;
    msg.body.key.keyCode = keyCode;
    msg.body.key.scanCode = scanCode;
    msg.body.key.metaState = metaState;
    msg.body.key.repeatCount = repeatCount;
    msg.body.key.downTime = downTime;
    msg.body.key.eventTime = eventTime;
    return mChannel->sendMessage(&msg);
}

InputChannel通过socket向远端的socket发送消息。

4.14#releasePendingEventLocked

<-InputDispatcher.cpp>

void InputDispatcher::releasePendingEventLocked() {
    if (mPendingEvent) {
        releaseInboundEventLocked(mPendingEvent);//释放mPendingEvent对象,并记录到mRecentQueue队列
        mPendingEvent = nullptr;//置空mPendingEvent变量.
    }
}

4.15#runCommandsLockedInterruptible

<-InputDispatcher.cpp>

bool InputDispatcher::runCommandsLockedInterruptible() {
    if (mCommandQueue.empty()) {
        return false;
    }
    do {
        std::unique_ptr<CommandEntry> commandEntry = std::move(mCommandQueue.front());//从mCommandQueue队列的头部取出第一个元素
        mCommandQueue.pop_front();
        Command command = commandEntry->command;
        command(*this, commandEntry.get()); // commands are implicitly 'LockedInterruptible'
        commandEntry->connection.clear();
    } while (!mCommandQueue.empty());
    return true;
}

通过循环方式处理完mCommandQueue队列的所有命令,处理过程从mCommandQueue中取出CommandEntry.
runCommandsLockedInterruptible是不断地从mCommandQueue队列取出命令,然后执行直到全部执行完成。 除了doPokeUserActivityLockedInterruptible,还有其他如下命令:

  • doNotifyANRLockedInterruptible
  • doInterceptKeyBeforeDispatchingLockedInterruptible
  • doDispatchCycleFinishedLockedInterruptible
  • doNotifyInputChannelBrokenLockedInterruptible
  • doNotifyConfigurationChangedInterruptible

4.16#doPokeUserActivityLockedInterruptible

<-InputDispatcher.cpp>

void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
    mLock.unlock();
    mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType,
                              commandEntry->displayId);
    mLock.lock();
}

4.17#pokeUserActivity

<-com_android_server_input_InputManagerService.cpp>

void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) {
    ATRACE_CALL();
    android_server_PowerManagerService_userActivity(eventTime, eventType, displayId);
}

4.18#android_server_PowerManagerService_userActivity

<-com_android_server_power_PowerManagerService.cpp>

void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType,
                                                     int32_t displayId) {
    if (gPowerManagerServiceObj) {
        ...
        env->CallVoidMethod(gPowerManagerServiceObj,
                gPowerManagerServiceClassInfo.userActivityFromNative,
                nanoseconds_to_milliseconds(eventTime), eventType, displayId, 0);
        checkAndClearExceptionFromCallback(env, "userActivityFromNative");
    }
}

4.19#PMS.userActivityFromNative

<-PowerManagerService.java>

    private void userActivityFromNative(long eventTime, int event, int displayId, int flags) {
        userActivityInternal(displayId, eventTime, event, flags, Process.SYSTEM_UID);
    }
    private void userActivityInternal(int displayId, long eventTime, int event, int flags,
            int uid) {
        synchronized (mLock) {
            if (displayId == Display.INVALID_DISPLAY) {
                if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {
                    updatePowerStateLocked();
                }
                return;
            }
            final DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
            if (displayInfo == null) {
                return;
            }
            final int groupId = displayInfo.displayGroupId;
            if (groupId == Display.INVALID_DISPLAY_GROUP) {
                return;
            }
            if (userActivityNoUpdateLocked(groupId, eventTime, event, flags, uid)) {
                updatePowerStateLocked();
            }
        }
    }

4.20 小结

  1. dispatchOnceInnerLocked(): 从InputDispatcher的mInboundQueue队列,取出事件EventEntry。另外该方法开始执行的时间点(currentTime)便是后续事件dispatchEntry的分发时间(deliveryTime)
  2. dispatchKeyLocked():满足一定条件时会添加命令doInterceptKeyBeforeDispatchingLockedInterruptible;
  3. enqueueDispatchEntryLocked():生成事件DispatchEntry并加入connection的outbound队列
  4. startDispatchCycleLocked():从outboundQueue中取出事件DispatchEntry, 重新放入connection的waitQueue队列;
  5. InputChannel.sendMessage通过socket方式将消息发送给远程进程;
  6. runCommandsLockedInterruptible():通过循环遍历地方式,依次处理mCommandQueue队列中的所有命令。而mCommandQueue队列中的命令是通过postCommandLocked()方式向该队列添加的。

5. Input系统—UI线程

Activity的生命周期的回调方法都是运行在主线程,也称之为UI线程,所有UI相关的操作都需要运行在该线程。所以这里从Activity最基本的创建过程开始说起。

frameworks/base/core/java/android/app/Activity.java
frameworks/base/core/java/android/view/WindowManagerGlobal.java
frameworks/base/core/java/android/view/ViewRootImpl.java
frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
frameworks/base/services/core/java/com/android/server/wm/Session.java
frameworks/base/services/core/java/com/android/server/wm/WindowState.java
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
frameworks/native/libs/input/InputTransport.cpp
frameworks/base/core/java/android/view/InputEventReceiver.java
frameworks/base/core/jni/android_view_InputEventReceiver.cpp
#xxxActivity.java
 ├──onCreate(Bundle savedInstanceState)
    #WindowManagerGlobal
     ├──addView()
        └──root = new ViewRootImpl(view.getContext(), display);//创建ViewRootImpl对象
        |  #ViewRootImpl.java
        |   ├──ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,boolean useSfChoreographer)
        |      └──mWindowSession = session;//WindowManagerGlobal.getWindowSession()
        |         #WindowManagerGlobal         
        |          ├──getWindowSession()
        |             └──InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();//获取IMS的代理类
        |             |    #InputMethodManager.java
        |             |     ├──ensureDefaultInstanceForDefaultDisplayIfNecessary()
        |             |        └──forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
        |             |           └──InputMethodManager instance = sInstanceMap.get(displayId);//根据displayId获取IMS代理对象
        |             └──IWindowManager windowManager = getWindowManagerService();//获取WMS的代理类
        |             └──windowManager.openSession(new IWindowSessionCallback.Stub() //经过Binder调用,最终调用WMS 
        |                #WindowManagerService.java
        |                 ├──openSession(IWindowSessionCallback callback)
        |                    └──return new Session(this, callback);
        └──root.setView(view, wparams, panelParentView, userId);
           #ViewRootImpl.java
            ├──setView(View view, WindowManager.LayoutParams attrs, View panelParentView,int userId)
               └──inputChannel = new InputChannel();//创建InputChannel对象
               └──res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(), userId,mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets, mTempControls);//通过Binder调用,进入system进程的Session
               |      #Session.java
               |       ├──addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,InputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls)
               |          └──return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,requestedVisibility, outInputChannel, outInsetsState, outActiveControls);
               |             #WindowManagerService.java
               |              ├──addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,int displayId, int requestUserId, InsetsState requestedVisibility,nputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls)
               |                 └──final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], attrs, viewVisibility, session.mUid, userId,session.mCanAddInternalSystemWindow);
               |                 |  #WindowState.java
               |                 |   ├──WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility,int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow,PowerManagerWrapper powerManagerWrapper)
               |                 |      └── mInputWindowHandle = new InputWindowHandleWrapper(new InputWindowHandle(mActivityRecord != null? mActivityRecord.getInputApplicationHandle(false /* update */) : null,getDisplayId()));
               |                 └──win.openInputChannel(outInputChannel);
               |                 |  #WindowState.java
               |                 |   ├──openInputChannel(InputChannel outInputChannel)
               |                 |      └──mInputChannel = mWmService.mInputManager.createInputChannel(name);
               |                 |         #InputManagerService.java
               |                 |          ├──createInputChannel(String name)
               |                 |             └──return nativeCreateInputChannel(mPtr, name);
               |                 |                #com_android_server_input_InputManagerService.cpp
               |                 |                 ├──nativeCreateInputChannel(JNIEnv* env, jclass /* clazz */, jlong ptr,jstring nameObj)
               |                 |                    └──createInputChannel(JNIEnv* /* env */, const std::string& name)
               |                 |                       └──return mInputManager->getDispatcher()->createInputChannel(name);
               |                 |                          #InputDispatcher.cpp
               |                 |                           ├──createInputChannel(const std::string& name)
               |                 |                              └──status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);//创建一对socket
               |                 |                              |  #InputTransport.cpp
               |                 |                              |   ├──openInputChannelPair(const std::string& name,std::unique_ptr<InputChannel>& outServerChannel,std::unique_ptr<InputChannel>& outClientChannel)
               |                 |                              |      └──socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)//创建socket对
               |                 |                              |      └──outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);//创建server InputChannel对象
               |                 |                              |      └──outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);//创建client InputChannel对象
               |                 |                              └──mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);//将该fd添加到Looper监听
               |                 |                              └──mLooper->wake();//connection改变, 则唤醒looper
               |                 └──focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, false /*updateInputWindows*/);//新添加window能接收按下操作,则更新聚焦窗口
               |                 └──displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);//设置当前聚焦窗口
               |                    #InputMonitor.java
               |                     ├──updateInputWindowsLw(boolean force)
               |                        └──scheduleUpdateInputWindows()
               |                           └──mHandler.post(mUpdateInputWindows);
               └──mInputEventReceiver = new WindowInputEventReceiver(inputChannel,Looper.myLooper());//创建WindowInputEventReceiver对象
                  #ViewRootImpl.java
                   ├──InputEventReceiver(InputChannel inputChannel, Looper looper)
                      └──mMessageQueue = looper.getQueue();//UI线程消息队列
                       └──mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),inputChannel, mMessageQueue);
                          #android_view_InputEventReceiver.cpp
                           ├──nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,jobject inputChannelObj, jobject messageQueueObj)
                              └──sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,receiverWeak, inputChannel, messageQueue);//创建NativeInputEventReceiver对象
                              └──status_t status = receiver->initialize();
                                 #android_view_InputEventReceiver.cpp
                                  ├──initialize()
                                     └──setFdEvents(int events)
                                        └──int fd = mInputConsumer.getChannel()->getFd();
                                        └──if(events)
                                        |  └──mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);//将socket客户端的fd添加到主线程的消息池
                                        └──else
                                           └──mMessageQueue->getLooper()->removeFd(fd);

5.1#onCreate

<-xxxActivity.java>

protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_account_bind);
    ...
}

Activity启动是由system进程控制:

  • handleLaunchActivity():会调用Activity.onCreate(), 该方法内再调用setContentView(),经过AMS与WMS的各种交互,层层调用后,进入handleResumeActivity()
  • handleResumeActivity():会调用Activity.makeVisible(),该方法继续调用便会执行到WindowManagerImpl.addView(), 该方法内部再调用WindowManagerGlobal.addView()

5.2#addView

<-WindowManagerGlobal.java>

public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow, int userId) {
    ...
    root = new ViewRootImpl(view.getContext(), display);//创建ViewRootImpl对象
    ...
    root.setView(view, wparams, panelParentView, userId);
    ...
}

5.3#ViewRootImpl

<-ViewRootImpl.java>

public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,
            boolean useSfChoreographer) {
    ...
     mWindowSession = session;//WindowManagerGlobal.getWindowSession()
     mDisplay = display;
     mThread = Thread.currentThread();//主线程
     mWindow = new W(this);
    ...
    mChoreographer = useSfChoreographer? Choreographer.getSfInstance() : Choreographer.getInstance();//界面刷新软中断
    ...
}
5.3.1#getWindowSession

<-WindowManagerGlobal.java>

public static IWindowSession getWindowSession() {
   synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();//获取IMS的代理类
                    IWindowManager windowManager = getWindowManagerService();//获取WMS的代理类
                    sWindowSession = windowManager.openSession(//经过Binder调用,最终调用WMS
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            });
                }catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
    }
}
5.3.2#ensureDefaultInstanceForDefaultDisplayIfNecessary

<-InputMethodManager.java>

public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() {
        forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
 }

private static InputMethodManager forContextInternal(int displayId, Looper looper) {
        final boolean isDefaultDisplay = displayId == Display.DEFAULT_DISPLAY;
        synchronized (sLock) {
            InputMethodManager instance = sInstanceMap.get(displayId);//根据displayId获取IMS代理对象
            if (instance != null) {
                return instance;
            }
            instance = createInstance(displayId, looper);
            // For backward compatibility, store the instance also to sInstance for default display.
            if (sInstance == null && isDefaultDisplay) {
                sInstance = instance;
            }
            sInstanceMap.put(displayId, instance);
            return instance;
        }
    }
5.3.3#WMS.openSession

<-WindowManagerService.java>

public IWindowSession openSession(IWindowSessionCallback callback) {
        return new Session(this, callback);
 }

再次经过Binder将数据写回app进程,则获取的便是Session的代理对象。

5.3.4#setView

<-ViewRootImpl.java>

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
    synchronized (this) {
        ...
        requestLayout();
        InputChannel inputChannel = null;
        if ((mWindowAttributes.inputFeatures & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
            inputChannel = new InputChannel();//创建InputChannel对象
        }
        ...
        res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,//通过Binder调用,进入system进程的Session
                            getHostVisibility(), mDisplay.getDisplayId(), userId,
                            mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
                            mTempControls);
       ...
       if (inputChannel != null) {
            if (mInputQueueCallback != null) {
                mInputQueue = new InputQueue();
                mInputQueueCallback.onInputQueueCreated(mInputQueue);
            }
            mInputEventReceiver = new WindowInputEventReceiver(inputChannel,Looper.myLooper());//创建WindowInputEventReceiver对象
            if (ENABLE_INPUT_LATENCY_TRACKING && mAttachInfo.mThreadedRenderer != null) {
                        InputMetricsListener listener = new InputMetricsListener();
                        mHardwareRendererObserver = new HardwareRendererObserver(
                                listener, listener.data, mHandler, true /*waitForPresentTime*/);
                        mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
             }
       }
   ...
}

该方法主要功能:

  1. 创建Java层的InputChannel对象mInputChannel
  2. 向WMS注册InputChannel信息,通过InputChannel.openInputChannelPair创建的socket pair,将其中的客户端赋值给mInputChannel.
  3. 创建WindowInputEventReceiver对象

跨进程调用,进入binder thread执行如下方法:

5.4#Session.addToDisplayAsUser

<-Session.java>

public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
        return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
                requestedVisibility, outInputChannel, outInsetsState, outActiveControls);
    }
5.4.1#WMS.addWindow

<-WindowManagerService.java>

public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
            int displayId, int requestUserId, InsetsState requestedVisibility,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
    ...
    synchronized (mGlobalLock) {
        ...
        final WindowState win = new WindowState(this, session, client, token, parentWindow,
                    appOp[0], attrs, viewVisibility, session.mUid, userId,
                    session.mCanAddInternalSystemWindow);
        ...
        displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
        final boolean openInputChannels = (outInputChannel != null
                    && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
            if  (openInputChannels) {
                win.openInputChannel(outInputChannel);
            }
        ...
        boolean focusChanged = false;
        if (win.canReceiveKeys()) {
              focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                        false /*updateInputWindows*/);//新添加window能接收按下操作,则更新聚焦窗口
              if (focusChanged) {
                    imMayMove = false;
              }
         }
         ...
         if (focusChanged) {
              displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
                        false /*updateInputWindows*/);
         }
         displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);//设置当前聚焦窗口
         ...
    }
    ...
}
5.4.2#WindowState

<-WindowState.java>

WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility,
            int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow,
            PowerManagerWrapper powerManagerWrapper) {
    ...
    mToken = token;
    ...
    mInputWindowHandle = new InputWindowHandleWrapper(new InputWindowHandle(
                mActivityRecord != null
                        ? mActivityRecord.getInputApplicationHandle(false /* update */) : null,
                getDisplayId()));
    mInputWindowHandle.setOwnerPid(s.mPid);
    mInputWindowHandle.setOwnerUid(s.mUid);
    mInputWindowHandle.setName(getName());
    mInputWindowHandle.setPackageName(mAttrs.packageName);
    mInputWindowHandle.setLayoutParamsType(mAttrs.type);
    ...
}
5.4.3#updateFocusedWindowLocked

<-RootWindowContainer.java>

boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
   mTopFocusedAppByProcess.clear();
    ...
    if (mTopFocusedDisplayId != topFocusedDisplayId) {
            mTopFocusedDisplayId = topFocusedDisplayId;
            mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
            mWmService.mPolicy.setTopFocusedDisplay(topFocusedDisplayId);
            ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d", topFocusedDisplayId);
    }
    return changed;
}
5.4.4#updateInputWindowsLw

<-InputMonitor.java>

void updateInputWindowsLw(boolean force) {
        if (!force && !mUpdateInputWindowsNeeded) {
            return;
        }
        scheduleUpdateInputWindows();
    }

private void scheduleUpdateInputWindows() {
        if (mDisplayRemoved) {
            return;
        }
        if (!mUpdateInputWindowsPending) {
            mUpdateInputWindowsPending = true;
            mHandler.post(mUpdateInputWindows);
        }
    }

5.5#openInputChannel

<-WindowState.java>

void openInputChannel(InputChannel outInputChannel) {
        if (mInputChannel != null) {
            throw new IllegalStateException("Window already has an input channel.");
        }
        String name = getName();
        mInputChannel = mWmService.mInputManager.createInputChannel(name);
        mInputChannelToken = mInputChannel.getToken();
        mInputWindowHandle.setToken(mInputChannelToken);
        mWmService.mInputToWindowMap.put(mInputChannelToken, this);
        if (outInputChannel != null) {
            mInputChannel.copyTo(outInputChannel);
        } else {
            // If the window died visible, we setup a fake input channel, so that taps
            // can still detected by input monitor channel, and we can relaunch the app.
            // Create fake event receiver that simply reports all events as handled.
            mDeadWindowEventReceiver = new DeadWindowEventReceiver(mInputChannel);
        }
}
5.5.1#createInputChannel

<-InputManagerService.java>

public InputChannel createInputChannel(String name) {
        return nativeCreateInputChannel(mPtr, name);
 }

private static native InputChannel nativeCreateInputChannel(long ptr, String name);
5.5.2#nativeCreateInputChannel

<-com_android_server_input_InputManagerService.cpp>

static jobject nativeCreateInputChannel(JNIEnv* env, jclass /* clazz */, jlong ptr,
                                        jstring nameObj) {
    ...
    base::Result<std::unique_ptr<InputChannel>> inputChannel = im->createInputChannel(env, name);
    ...
}

base::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputChannel(
        JNIEnv* /* env */, const std::string& name) {
    ATRACE_CALL();
    return mInputManager->getDispatcher()->createInputChannel(name);
}
5.5.3#createInputChannel

<-InputDispatcher.cpp>

Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
    ...
    std::unique_ptr<InputChannel> serverChannel;
    std::unique_ptr<InputChannel> clientChannel;
    status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);//创建一对socket
    if (result) {
        return base::Error(result) << "Failed to open input channel pair with name " << name;
    }
    { // acquire lock
        std::scoped_lock _l(mLock);
        const sp<IBinder>& token = serverChannel->getConnectionToken();
        int fd = serverChannel->getFd();
        sp<Connection> connection =
                new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);//创建Connection
        if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) {
            ALOGE("Created a new connection, but the token %p is already known", token.get());
        }
        mConnectionsByToken.emplace(token, connection);
        std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
                                                            this, std::placeholders::_1, token);
        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);//将该fd添加到Looper监听
    } // release lock
    // Wake the looper because some connections have changed.
    mLooper->wake();//connection改变, 则唤醒looper
    return clientChannel;
}

static status_t openInputChannelPair(const std::string& name,
                                     std::shared_ptr<InputChannel>& serverChannel,
                                     std::unique_ptr<InputChannel>& clientChannel) {
    std::unique_ptr<InputChannel> uniqueServerChannel;
    status_t result = InputChannel::openInputChannelPair(name, uniqueServerChannel, clientChannel);
    serverChannel = std::move(uniqueServerChannel);
    return result;
}
5.5.4#openInputChannelPair

<-InputTransport.cpp>

status_t InputChannel::openInputChannelPair(const std::string& name,
                                            std::unique_ptr<InputChannel>& outServerChannel,
                                            std::unique_ptr<InputChannel>& outClientChannel) {
    int sockets[2];
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {//真正创建socket对的地方
        status_t result = -errno;
        ALOGE("channel '%s' ~ Could not create socket pair.  errno=%s(%d)", name.c_str(),
              strerror(errno), errno);
        outServerChannel.reset();
        outClientChannel.reset();
        return result;
    }
    int bufferSize = SOCKET_BUFFER_SIZE;//32k
    setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
    sp<IBinder> token = new BBinder();
   std::string serverChannelName = name + " (server)";
    android::base::unique_fd serverFd(sockets[0]);
    outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);//创建server InputChannel对象
    std::string clientChannelName = name + " (client)";
    android::base::unique_fd clientFd(sockets[1]);
    outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);//创建client InputChannel对象
    return OK;
}

该方法主要功能:

  1. 创建socket pair; (非阻塞式的socket)
  2. 设置两个socket的接收和发送的buffer上限为32KB;
  3. 创建client和server的Native层InputChannel对象;
    • sockets[0]所对应的InputChannel名称的后缀为(server);
    • sockets[1]所对应的InputChannel名称的后缀为(client)

5.6#WindowInputEventReceiver

<-ViewRootImpl.java>

final class WindowInputEventReceiver extends InputEventReceiver {
    //inputChannel是指socket客户端,Looper是指UI线程的Looper
    public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
        super(inputChannel, looper); //【见小节3.2】
    }
    ...
}
5.6.1#InputEventReceiver

<-InputEventReceiver.java>

public InputEventReceiver(InputChannel inputChannel, Looper looper) {
        ...
        mInputChannel = inputChannel;
        mMessageQueue = looper.getQueue();//UI线程消息队列
        mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
                inputChannel, mMessageQueue);
        mCloseGuard.open("dispose");
 }

private static native long nativeInit(WeakReference<InputEventReceiver> receiver,
            InputChannel inputChannel, MessageQueue messageQueue);
5.6.2#nativeInit

<-android_view_InputEventReceiver.cpp>

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject inputChannelObj, jobject messageQueueObj) {
    std::shared_ptr<InputChannel> inputChannel =
            android_view_InputChannel_getInputChannel(env, inputChannelObj);
    ...
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);//获取UI主线程的消息队列
    ...
    sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
            receiverWeak, inputChannel, messageQueue);//创建NativeInputEventReceiver对象
    status_t status = receiver->initialize();
    ...
    receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
    return reinterpret_cast<jlong>(receiver.get());
}
5.6.3#NativeInputEventReceiver

<-android_view_InputEventReceiver.cpp>

NativeInputEventReceiver::NativeInputEventReceiver(
        JNIEnv* env, jobject receiverWeak, const std::shared_ptr<InputChannel>& inputChannel,
        const sp<MessageQueue>& messageQueue)
      : mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
        mInputConsumer(inputChannel),//inputChannel是socket客户端
        mMessageQueue(messageQueue),
        mBatchedInputEventPending(false),
        mFdEvents(0) {
}
5.6.4#initialize

<-android_view_InputEventReceiver.cpp>

status_t NativeInputEventReceiver::initialize() {
    setFdEvents(ALOOPER_EVENT_INPUT);
    return OK;
}

void NativeInputEventReceiver::setFdEvents(int events) {
    if (mFdEvents != events) {
        mFdEvents = events;
        int fd = mInputConsumer.getChannel()->getFd();
        if (events) {
            mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);//将socket客户端的fd添加到主线程的消息池
        } else {
            mMessageQueue->getLooper()->removeFd(fd);
        }
    }
}

5.7小结

ViewRootImpl的setView()过程:

  • 创建socket pair,作为InputChannel:
    • socket服务端保存到system_server中的WindowState的mInputChannel;
    • socket客户端通过binder传回到远程进程的UI主线程ViewRootImpl的mInputChannel;
  • 紧接着,完成了两个线程的epoll监听工作:
    • IMS.createInputChannel(): “InputDispatcher”线程监听socket服务端,收到消息后回调InputDispatcher.handleReceiveCallback();
    • setFdEvents(): UI主线程监听socket客户端,收到消息后回调NativeInputEventReceiver.handleEvent().
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-12-25 11:21:32  更:2022-12-25 11:26:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年3日历 -2024/3/28 23:04:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码