安卓Input功能学习笔记_1

安卓Input功能学习笔记

1 文章导读

1.1 文档面向的人群

面向安卓应用和系统开发人员,能够了解Input系统相关内容,如Input事件的生产、传递、消费流程;

1.2 整理文档的目的

作为Input系统的学习笔记,记录并整理相关内容,经常回顾,加深对Input系统的理解;

1.3 文档内容简介

本文介绍安卓系统驱动以上的整体流程,包括InputManagerService,InputFlinger,App层相关内容;

2 功能学习计划

2.1 目的和学习内容

了解安卓系统Input子系统的设计和实现方法,期望能够提出对某个系统的输入框架的理解,具备Input子系统的架构能力;
能够解决Input相关问题,实现Input相关功能定制,如多屏控制(监护模式)、硬按键、多输入法等功能。

2.2 抛出问题,带着问题学习

1.Input事件/对象是从哪里生产的?如何转换为MotionEvent和KeyEvent等事件?
2.系统会将Input事件传递给前台窗口,是如何判断前台窗口的?
3.系统和App进程的Input交互通道是什么,如何建立的?
4.Input事件在系统侧的传递流程是什么样的?
5.App进程是如何接收到Input事件的?
6.Input事件在App侧的传递流程是什么样的?
7.Input事件有哪些类型,分别有什么用途?
8.输入法是如何工作的(可以另开章节,本篇不涉及)?
9.如何创建一个Input驱动文件,开发流程是什么样的?
10.系统是如何拦截Home/Volume等按键的?
11.Input事件处理超时会产生ANR,系统是如何实现的?
12.按键ScanCode和KeyCode转换方法;

2.3 预期的学习顺序和方法

1.阅读Input相关博客或文档,对模块和整体流程有模糊认知;
2.通过阅读AOSP中跟InputManagerService相关代码,了解IMS的初始化过程;
3.在App-View的onClickListener中打印堆栈信息,学习App侧Input事件传递流程;
4.阅读InputDispatcher/InputReader/EventHub相关代码,了解Input事件的生产流程和对象转换流程;
5.阅读IMS中事件传递相关代码,了解IMS传递事件时,如何选择目标App;
6.尝试编写测试App,确认不同输入事件的用途;

3 Input模块整体介绍

3.1 模块介绍和架构图

参考4.2.2和4.3.2章节图示;

3.2 模块关键类图

参考4.2.3和4.3.3章节类图;

3.4 子模块划分和介绍

Input系统可以划分以下子模块/流程,本篇会跟进调查这些流程,来对Input功能有完整的认识:
1.IMS服务初始化流程:
指系统在system_server进程创建InputManagerService时,初始化InputReader、InputDispatcher,准备读取Input事件的流程;

2.App创建InputChannel和注册到IMS的流程;
App和IMS的交互依赖InputChannel,需要调查App创建InputChannel对象的流程;

3.IMS读取和传递Input事件的流程;
IMS通过EventHub对象从驱动读取数据,并将这些数据进行传递的过程;

4.App接收Input事件的流程;
App从InputChannel中读取Input事件的流程;

5.App传递Input事件的流程;
App接收到Input事件时,将Input事件进行分类,传递给对应的Activity和View的流程;

4 子模块详细分析

4.1 IMS服务初始化流程

4.1.1 流程介绍

此处会介绍system_server进程启动后,初始化framework层Input框架的流程;
包括创建InputManagerServer及native层的InputReader,InputDispatcher的流程。
从InputManagerService对象创建,到InputReader线程启动,尝试读取输入数据为止,是本章节的主要流程;

4.1.2 相关模块架构图

在这里插入图片描述

4.1.3 类图

在这里插入图片描述

4.1.4 时序图

4.1.4.1 InputManagerService初始化流程

在这里插入图片描述

4.1.4.2 InputManagerService开始工作流程

在这里插入图片描述

4.1.5 代码解读

IMS初始化流程代码:
IMS的初始化流程,是在SystemServer.java中开始的,IMS服务也存活于system_server进程中;SystemServer在开机过程中会初始化IMS服务:

frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
...

InputManagerService inputManager = null;
..
// 调用IMS的构造方法
inputManager = new InputManagerService(context);

// MWS和IMS的关联关系
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
        new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
        DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
        /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
...
// 调用了start方法;
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();
...

// 在AMS的systemReady中,调用inputManagerF.systemRunning();
mActivityManagerService.systemReady(() -> {
final InputManagerService inputManagerF = inputManager;

if (inputManagerF != null) {
    inputManagerF.systemRunning();
}

以上代码,调用了IMS的以下三个关键方法: new InputManagerService(context);
inputManager.start(); inputManagerF.systemRunning();
接下来我们围绕这三个方法,确认IMS的初始化流程;

4.1.5.1 IMS构造方法

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
// 由此可见,IMS本身是一个binder对象;
public class InputManagerService extends IInputManager.Stub implements Watchdog.Monitor {
    public InputManagerService(Context context) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());

        // 读取input 和display port的对应关系,此处好像决定了触屏事件和触屏id的对应关系,TODO;
        mStaticAssociations = loadStaticInputPortAssociations();
        mUseDevInputEventForAudioJack =
                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                + mUseDevInputEventForAudioJack);
        // 调用nativeinit方法,注意变量,service自身,context引用,还有messageQueue!
        // 注意此处mPtr,是native层一个c++对象的内存地址。
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
        String doubleTouchGestureEnablePath = context.getResources().getString(
                R.string.config_doubleTouchGestureEnableFile);
        mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
            new File(doubleTouchGestureEnablePath);

        LocalServices.addService(InputManagerInternal.class, new LocalService());
    }

来看下nativeInit方法的作用,入参是this-IMS对象,将一个java对象传入jni方法中,可能会有c++和java的相互调用;

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
private static native long nativeInit(InputManagerService service,
        Context context, MessageQueue messageQueue);

frameworks/base/services/core/jni/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);
    if (messageQueue == nullptr) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
    //创建了NativeIM对象,并返回此对象的内存地址;注意传参,java层的context,service和messagequeue!
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper()); 
    im->incStrong(0);
    // 返回im的内存地址,这样java就可以持有im的对象,并调用im对象的方法了;
    return reinterpret_cast<jlong>(im);
}

来看下NativeInputManager的构造方法:

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();
    // mServiceObj是成员变量,NativeInputManager持有Java IMS对象的引用,可以调用java层的接口;
    mServiceObj = env->NewGlobalRef(serviceObj);

    {
        AutoMutex _l(mLock);
        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
        mLocked.pointerSpeed = 0;
        mLocked.pointerGesturesEnabled = true;
        mLocked.showTouches = false;
        mLocked.pointerCapture = false;
        mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
    }
    mInteractive = true;

    //*
     * 这里创建了native层的一个对象InputManager,注意传参为两个this!* 分别对应了NativeInputManager的两个不同的父类readerPolicy和dispatcherPolicy!
     * 所以InputManager中的readerPolicy和dispatcherPolicy,都是指NativeInputManager对象;
     */ 
    mInputManager = new InputManager(this, this);  
    /// 将mInputManager作为binder服务,添加到ServiceManager中,SurfaceFlinger里会用到。
    defaultServiceManager()->addService(String16("inputflinger"),
            mInputManager, false);
}

继续跟进new InputManager(this, this)的流程,NativeInputManager相当于java层的IMS和Native层的InputManager之间通信的桥梁:

frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    // 创建InputDispatcher对象,持有dispatcherPolicy-即NativeInputManager
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    // 创建InputClassifier对象,持有mDispatcher
    mClassifier = new InputClassifier(mDispatcher);
    // 创建InputReader对象,持有readerPolicy和InputClassifier;
    // 相当于持有了NativeInputManager和mDispatcher;
    mReader = createInputReader(readerPolicy, mClassifier);
}

注意此处出现了耳熟能详的两个模块,InputDispatcher、InputReader; 我们来对以下三个关键方法进行一一分析
mDispatcher = createInputDispatcher(dispatcherPolicy);
mClassifier = new InputClassifier(mDispatcher);
mReader = createInputReader(readerPolicy, mClassifier);

frameworks/native/services/inputflinger/dispatcher/InputDispatcherFactory.cpp

sp<InputDispatcherInterface> createInputDispatcher(
        const sp<InputDispatcherPolicyInterface>& policy) {
    // 创建InputDispatcher 对象;
    return new android::inputdispatcher::InputDispatcher(policy);
}

构造方法:
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),
        mFocusedDisplayId(ADISPLAY_ID_DEFAULT) {
    mLooper = new Looper(false);
    mReporter = createInputReporter();

    mKeyRepeatState.lastKeyEntry = nullptr;
    // policy指向NativeInputManager,
    // 此处通过NativeInputManager调用了Java层的方法,从java config文件中读取一些配置信息;
    policy->getDispatcherConfiguration(&mConfig);
}
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
    ATRACE_CALL();
    JNIEnv* env = jniEnv();
    // 此处从IMS中读取到了两个配置信息,并保存到了InputDispatcher的outConfig中;
    jint keyRepeatTimeout = env->CallIntMethod(mServiceObj,
            gServiceClassInfo.getKeyRepeatTimeout);
    if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) {
        outConfig->keyRepeatTimeout = milliseconds_to_nanoseconds(keyRepeatTimeout);// 查询keyRepeatTimeout
    }

    jint keyRepeatDelay = env->CallIntMethod(mServiceObj,
            gServiceClassInfo.getKeyRepeatDelay);
    if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) {
        outConfig->keyRepeatDelay = milliseconds_to_nanoseconds(keyRepeatDelay); // 查询keyRepeatDelay
    }
}

createInputDispatcher流程至此结束;
此处创建了InputDispatcher对象,并从java层读取了两个配置属性;

来继续看下mClassifier = new InputClassifier(mDispatcher);的流程
先来看下几个关键类的继承关系,以便对这些类的多重身份有一定的了解:

// InputDispatcher继承关系如下:
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.h
class InputDispatcher : public android::InputDispatcherInterface {

// 重要的函数声明;
frameworks/native/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface {

// 说明InputDispatcher会接收这些方法调用。
// 可能是通过InputReader->InputListener->InputDispatcher的流程进行调用;
frameworks/native/services/inputflinger/include/InputListener.h 
class InputListenerInterface : public virtual RefBase {
protected:
    InputListenerInterface() { }
    virtual ~InputListenerInterface() { }

public:
    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) = 0;
    virtual void notifyKey(const NotifyKeyArgs* args) = 0;
    virtual void notifyMotion(const NotifyMotionArgs* args) = 0;
    virtual void notifySwitch(const NotifySwitchArgs* args) = 0;
    virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;
};
// 创建InputClassifier,这里的代码很简单,把mListener指向了listener,也就是InputDispatcher
frameworks/native/services/inputflinger/InputClassifier.cpp

InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
      : mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {}

来看下关键的代码,根据名字也能猜出,此类跟Input事件和读取相关:
mReader = createInputReader(readerPolicy, mClassifier);

// 注意此处,是先通过make_unique创建了EventHub对象,然后在调用了InputReader的构造方法!
// 注意InputReader的三个入参:
// 一个是EventHud对象,一个是readerPilicy(也就是NativeInputManager),一个是InputClassifier;
frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy, const sp<InputListenerInterface>& listener) {
    return new InputReader(std::make_unique<EventHub>(), policy, listener);
}

来看下EventHub的创建流程,确认EventHub的功能,分析后再跟进InputReader的创建过程.

frameworks/native/services/inputflinger/reader/include/EventHub.h

/*
 * Input device classes.
 */
enum {
    /* The input device is a keyboard or has buttons. */
    INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001,

    /* The input device is an alpha-numeric keyboard (not just a dial pad). */
    INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002,

    /* The input device is a touchscreen or a touchpad (either single-touch or multi-touch). */
    INPUT_DEVICE_CLASS_TOUCH = 0x00000004,

    /* The input device is a cursor device such as a trackball or mouse. */
    INPUT_DEVICE_CLASS_CURSOR = 0x00000008,

    /* The input device is a multi-touch touchscreen. */
    INPUT_DEVICE_CLASS_TOUCH_MT = 0x00000010,

    /* The input device is a directional pad (implies keyboard, has DPAD keys). */
    INPUT_DEVICE_CLASS_DPAD = 0x00000020,

    /* The input device is a gamepad (implies keyboard, has BUTTON keys). */
    INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,

    /* The input device has switches. */
    INPUT_DEVICE_CLASS_SWITCH = 0x00000080,

    /* The input device is a joystick (implies gamepad, has joystick absolute axes). */
    INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100,

    /* The input device has a vibrator (supports FF_RUMBLE). */
    INPUT_DEVICE_CLASS_VIBRATOR = 0x00000200,

    /* The input device has a microphone. */
    INPUT_DEVICE_CLASS_MIC = 0x00000400,

    /* The input device is an external stylus (has data we want to fuse with touch data). */
    INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,

    /* The input device has a rotary encoder */
    INPUT_DEVICE_CLASS_ROTARY_ENCODER = 0x00001000,

    /* The input device is virtual (not a real device, not part of UI configuration). */
    INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000,

    /* The input device is external (not built-in). */
    INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000,
};


class EventHub : public EventHubInterface {
public:
    EventHub();

class EventHubInterface {
public:
    EventHubInterface() {}
    ...
}


class EventHub : public EventHubInterface {
public:
    EventHub();

    virtual uint32_t getDeviceClasses(int32_t deviceId) const override;

    virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override;

    virtual int32_t getDeviceControllerNumber(int32_t deviceId) const override;

    virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const override;

    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
                                         RawAbsoluteAxisInfo* outAxisInfo) const override;

    virtual bool hasRelativeAxis(int32_t deviceId, int axis) const override;

    virtual bool hasInputProperty(int32_t deviceId, int property) const override;

    virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override;

    virtual status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const override;

    virtual void setExcludedDevices(const std::vector<std::string>& devices) override;

    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override;
    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override;
    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const override;
    virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
                                          int32_t* outValue) const override;

    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const override;

    virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) override;
    virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override;

    virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const override;
    virtual bool hasLed(int32_t deviceId, int32_t led) const override;
    virtual void setLedState(int32_t deviceId, int32_t led, bool on) override;

    virtual void getVirtualKeyDefinitions(int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const override;

    virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const override;
    virtual bool setKeyboardLayoutOverlay(int32_t deviceId,
                                          const sp<KeyCharacterMap>& map) override;

    virtual void vibrate(int32_t deviceId, nsecs_t duration) override;
    virtual void cancelVibrate(int32_t deviceId) override;

    virtual void requestReopenDevices() override;

    virtual void wake() override;

    virtual void dump(std::string& dump) override;
    virtual void monitor() override;

    virtual ~EventHub() override;

private:
    // EventHub中定义了一个Device类型的结构体,根据next可以看到,这个是一个链表类型的数据结构;
    // 每个Device的path,都在/dev/input下有对应的驱动文件;
    struct Device {
        Device* next;

        int fd; // may be -1 if device is closed
        const int32_t id;
        const std::string path;
        const InputDeviceIdentifier identifier;

        std::unique_ptr<TouchVideoDevice> videoDevice;

        uint32_t classes;

        uint8_t keyBitmask[(KEY_MAX + 1) / 8];
        uint8_t absBitmask[(ABS_MAX + 1) / 8];
        uint8_t relBitmask[(REL_MAX + 1) / 8];
        uint8_t swBitmask[(SW_MAX + 1) / 8];
        uint8_t ledBitmask[(LED_MAX + 1) / 8];
        uint8_t ffBitmask[(FF_MAX + 1) / 8];
        uint8_t propBitmask[(INPUT_PROP_MAX + 1) / 8];

        std::string configurationFile;
        PropertyMap* configuration;
        std::unique_ptr<VirtualKeyMap> virtualKeyMap;
        KeyMap keyMap;

        sp<KeyCharacterMap> overlayKeyMap;
        sp<KeyCharacterMap> combinedKeyMap;

        bool ffEffectPlaying;
        int16_t ffEffectId; // initially -1

        int32_t controllerNumber;

        Device(int fd, int32_t id, const std::string& path,
               const InputDeviceIdentifier& identifier);
        ~Device();

        void close();

        bool enabled; // initially true
        status_t enable();
        status_t disable();
        bool hasValidFd();
        const bool isVirtual; // set if fd < 0 is passed to constructor

        const sp<KeyCharacterMap>& getKeyCharacterMap() const {
            if (combinedKeyMap != nullptr) {
                return combinedKeyMap;
            }
            return keyMap.keyCharacterMap;
        }
    };

    // EventHub操作Device的一些方法;
    status_t openDeviceLocked(const char* devicePath);
    void openVideoDeviceLocked(const std::string& devicePath);
    void createVirtualKeyboardLocked();
    ...

    int32_t mNextDeviceId;

    BitSet32 mControllerNumbers;

    KeyedVector<int32_t, Device*> mDevices;
    /**
     * Video devices that report touchscreen heatmap, but have not (yet) been paired
     * with a specific input device. Video device discovery is independent from input device
     * discovery, so the two types of devices could be found in any order.
     * Ideally, video devices in this queue do not have an open fd, or at least aren't
     * actively streaming.
     */
    std::vector<std::unique_ptr<TouchVideoDevice>> mUnattachedVideoDevices;

    Device* mOpeningDevices;
    Device* mClosingDevices;

    bool mNeedToSendFinishedDeviceScan;
    bool mNeedToReopenDevices;
    bool mNeedToScanDevices;
    std::vector<std::string> mExcludedDevices;

    int mEpollFd;
    int mINotifyFd;
    int mWakeReadPipeFd;
    int mWakeWritePipeFd;
    ...
};

EventHub的构造方法,我们看到make_unique方法,没有任何入参,所以EventHub是不依赖外部对象的,只会对外提供开放接口:

frameworks/native/services/inputflinger/reader/EventHub.cpp

// EventHub扫描Device的路径:
static const char* DEVICE_PATH = "/dev/input";
// v4l2 devices go directly into /dev
static const char* VIDEO_DEVICE_PATH = "/dev";


EventHub::EventHub(void)
      : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
        mNextDeviceId(1),
        mControllerNumbers(),
        mOpeningDevices(nullptr),
        mClosingDevices(nullptr),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false),
        mNeedToScanDevices(true),
        mPendingEventCount(0),
        mPendingEventIndex(0),
        mPendingINotify(false) {
    ensureProcessCanBlockSuspend();

    // 跟驱动交互相关的函数,看不懂~~~
    mEpollFd = epoll_create1(EPOLL_CLOEXEC);
    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));

    // 初始化跟/dev/input/相关的数据;
    mINotifyFd = inotify_init();
    mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
    LOG_ALWAYS_FATAL_IF(mInputWd < 0, "Could not register INotify for %s: %s", DEVICE_PATH,
                        strerror(errno));
    if (isV4lScanningEnabled()) {
        mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
        LOG_ALWAYS_FATAL_IF(mVideoWd < 0, "Could not register INotify for %s: %s",
                            VIDEO_DEVICE_PATH, strerror(errno));
    } else {
        mVideoWd = -1;
        ALOGI("Video device scanning disabled");
    }

    struct epoll_event eventItem = {};
    eventItem.events = EPOLLIN | EPOLLWAKEUP;
    eventItem.data.fd = mINotifyFd;
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance.  errno=%d", errno);

    // 创建并初始化用于线程唤醒的两个pipe,mWakeReadPipeFd,mWakeWritePipeFd;
    int wakeFds[2];
    result = pipe(wakeFds);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);

    mWakeReadPipeFd = wakeFds[0];
    mWakeWritePipeFd = wakeFds[1];

    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
                        errno);

    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
                        errno);

    eventItem.data.fd = mWakeReadPipeFd;
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
                        errno);
}

来看下初始化InputReader的流程new InputReader(std::make_unique(), policy, listener);

frameworks/native/services/inputflinger/reader/InputReader.cpp

InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
                         const sp<InputReaderPolicyInterface>& policy,
                         const sp<InputListenerInterface>& listener)
      : mContext(this), // 注意此处不是赋值,是调用了mContext的构造方法;    
        mEventHub(eventHub),//赋值,将EventHub跟InputReader进行关联!
        mPolicy(policy), // 赋值!NativeInputManager;
        mGlobalMetaState(0),
        mGeneration(1),
        mNextInputDeviceId(END_RESERVED_ID),
        mDisableVirtualKeysTimeout(LLONG_MIN),
        mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    mQueuedListener = new QueuedInputListener(listener);

    { // acquire lock
        AutoMutex _l(mLock);
        // 通过InputManagerService读取系统res配置信息,存储到InputReader的mConfig中,如excludedDevice,portAssociations
        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    } // release lock
}
5.1.5.2 IMS_start方法解析

IMS的初始化流程中,IMS构造方法和nativeInit方法执行完成后,初始化了IMS、NativeInputManager、InputManager、InputDispatcher、InputClassifier、InputReader、EventHub等对象;
来看下IMS的start方法的作用:

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    public void start() {
        Slog.i(TAG, "Starting input manager");
        // 通知native层开始工作,估计跟reader和dispatcher线程启动相关;
        nativeStart(mPtr);  

        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);

        // 注册一些数据的设置变化监听;
        registerPointerSpeedSettingObserver();
        registerShowTouchesSettingObserver();
        registerAccessibilityLargePointerSettingObserver();
        registerLongPressTimeoutObserver();

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

nativeStart方法:

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    // 调用InputManager的start方法;
    status_t result = im->getInputManager()->start();  
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}

inline sp<InputManager> getInputManager() const { return mInputManager; }

来看下im->getInputManager()->start()方法:

frameworks/native/services/inputflinger/InputManager.cpp
status_t InputManager::start() {
    // 调用InputDispatcher的start方法方法;
    status_t result = mDispatcher->start(); 
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }

    // 调用InputReader的start方法;
    result = mReader->start(); 
    if (result) {
        ALOGE("Could not start InputReader due to error %d.", result);

        mDispatcher->stop();
        return result;
    }

    return OK;
}

IMS的start方法,调用到InputManager的start方法,然后通知mDispatcher和mReader进行start,调用到了InputDispatcher和InputReader的start方法;
猜测start方法会让mDispatcher和mReader开始工作,进行输入事件的读取和传递工作;

先来看InputDispatcher的start流程:

frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

status_t InputDispatcher::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }
    // /创建并运行线程,入参是线程名称,以及两个函数指针;
    mThread = std::make_unique<InputThread>("InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); }); 
    return OK;
}

上面的make_unique,会创建线程并调用dispatchOnce方法,来看下代码:

// InputThread的定义:
frameworks/native/services/inputflinger/include/InputThread.h

class InputThread {
public:
    explicit InputThread(std::string name, std::function<void()> loop,
                         std::function<void()> wake = nullptr);
    virtual ~InputThread();

    bool isCallingThread();

private:
    std::string mName;
    std::function<void()> mThreadWake;
    sp<Thread> mThread;
};

// InputThread和InputThreadImpl的实现:
frameworks/native/services/inputflinger/InputThread.cpp  // InputThread线程
// 继承自Thread对象
// Implementation of Thread from libutils.
class InputThreadImpl : public Thread {
public:
    explicit InputThreadImpl(std::function<void()> loop)
          : Thread(/* canCallJava */ true), mThreadLoop(loop) {}

    ~InputThreadImpl() {}

private:
    std::function<void()> mThreadLoop;

    bool threadLoop() override {  // 猜测线程启动后执行threadLoop()方法,然后调用到mThreadLoop(),也就是dispatchOnce方法。
        mThreadLoop();
        return true;
    }
};

} // namespace
// make_unique创建InputThread对象,会触发此处的构造方法;
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
      : mName(name), mThreadWake(wake) {// 赋值,mThreadWake指向了mLooper->wake();
    // 创建线程,传入InputDispatcher的dispatchOnce方法;mThreadLoop就指向了此方法;
    mThread = new InputThreadImpl(loop);
    //开始线程run,会持续调用InputThreadImpl的threadLoop方法,直到返回false或调用exit;
    mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}

Thread.h对run和threadLoop的解释:

system/core/libutils/include/utils/Thread.h
class Thread : virtual public RefBase
{
public:
    // Create a Thread object, but doesn't create or start the associated
    // thread. See the run() method.
    explicit            Thread(bool canCallJava = true);
    virtual             ~Thread();

    // 用threadLoop执行线程!
    // Start the thread in threadLoop() which needs to be implemented.
    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    run(    const char* name,
                                int32_t priority = PRIORITY_DEFAULT,
                                size_t stack = 0);
    
    // Ask this object's thread to exit. This function is asynchronous, when the
    // function returns the thread might still be running. Of course, this
    // function can be called from a different thread.
    virtual void        requestExit();
    ......
    
private:
    // 派生类/子类必须重写threadLoop方法,当threadLoop返回true时,会重新调用threadLoop;
    // threadLoop此循环直到requestExit才停止!
    // Derived class must implement threadLoop(). The thread starts its life
    // here. There are two ways of using the Thread object:
    // 1) loop: if threadLoop() returns true, it will be called again if
    //          requestExit() wasn't called.
    // 2) once: if threadLoop() returns false, the thread will exit upon return.
    virtual bool        threadLoop() = 0;

private:
    Thread& operator=(const Thread&);
    static  int             _threadLoop(void* user);
    const   bool            mCanCallJava;
    ...
};

}  // namespace android

总结:
至此InputDispatcher的start方法初始化完成,创建了一个线程,并会持续调用InputDispatcher的dispatchOnce方法;
dispatcherOnce方法是对Input事件的传递流程,会在4.4章节“IMS读取和传递INput事件流程”中进行解读;

来看下InputReader的start方法,也是一样的流程!

frameworks/native/services/inputflinger/reader/InputReader.cpp

status_t InputReader::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }
    // 可以看到InputReader::start()方法,也是创建了一个线程,持续调用loopOnce方法;
    // loopOnce方法会尝试从EventHub中读取Input事件;
    mThread = std::make_unique<InputThread>(
            "InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); }); // 这里会执行loopOnce方法,来跟进下;
    return OK;
}
frameworks/native/services/inputflinger/reader/InputReader.cpp
void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    std::vector<InputDeviceInfo> inputDevices;
    ......
    // 读取各种事件,包括Input事件,放入mEventBuffer中;
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); // 从EventHub读取输入事件;

    { // acquire lock
        AutoMutex _l(mLock);
        mReaderIsAliveCondition.broadcast();

        // 若读取到了输入事件,则处理输入事件(readerPolicy或传给InputDispatcher);
        }
        if (count) {
            processEventsLocked(mEventBuffer, count); 

        ......
    } // release lock

    // Send out a message that the describes the changed input devices.
    if (inputDevicesChanged) {
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }

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

InputReader-start方法总结:
InputReader的start方法,也是创建了一个线程,并循环调用InputReader的loopOnce方法;
loopOnce方法会从EventHub中读取事件,并进行传递;
loopOnce方法,会在4.4章节“IMS读取和传递INput事件流程”中进行解读;

IMS_start方法总结:
InputManagerService的start方法,会调用到native层InputManager的start方法,然后分别创建InputDispatcher和InputReader的线程;
在这两个线程中,持续调用dispatcheOnce和loopOnce方法,进行Input事件的读取和传递流程;

4.2 App初始化输入框架的流程

4.2.1 流程简介

在Activity执行onResume的流程中,会创建一对InputChannel对象,两个InputChannel分别注册到IMS和APP进程中;
IMS读取到的输入数据,通过InputChannel传递给APP进程;

4.2.2 相关模块数据流图

以下图示,体现了输入事件的数据,在App进程中的数据流向。
在这里插入图片描述

4.2.3 类图

此流程相关类图,包含app和system_server进程相关类;
可以了解到App初始化Input功能的对象关联关系和方法调用;
在这里插入图片描述

4.2.4 时序图

4.2.4.1 App初始化Input功能流程

在这里插入图片描述

4.2.4.2 WMS注册InputChannel流程

此处流程,是App初始化Input功能的一部分;
通过WMS创建一对InputChannel,WMS将其中一个InputChannel注册到InputManagerService作为数据发送端,将另一个InputChannel传递给App,作为输入事件的接收端。
在这里插入图片描述

4.2.4.3 openInputChannelPair流程

在这里插入图片描述

4.2.5 代码解读

4.2.5.1 创建InputChannel流程:

输入管道的创建起源,可以从AMS通知Activity进行resume开始:

frameworks/base/core/java/android/app/servertransaction/ResumeActivityItem.java
    @Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
        // resume某个Activiy
        client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
                "RESUME_ACTIVITY");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
frameworks/base/core/java/android/app/ActivityThread.java
    @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
        ...
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
        ......

        // The window is now visible if it has been added, we are not
        // simply finishing, and we are not starting another activity.
        if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
            ...

            r.activity.mVisibleFromServer = true;
            mNumVisibleActivities++;
            if (r.activity.mVisibleFromClient) {
                // makeVisible使activity显示到界面上,过程中会创建InputChannel对象.
                // makeVisible会调用WMS的addView方法;
                r.activity.makeVisible();
            }
        }
        ...
    }

makeVisible->addView流程:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/java/android/app/Activity.java
    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            // 注意此处mDecor传入了WindowManagerGlobal,是ViewRootImpl中的mView对象;
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

frameworks/base/core/java/android/view/WindowManagerImpl.java
    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        // WindowManagerGlobal的addView流程;
        mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
                mContext.getUserId());
    }


frameworks/base/core/java/android/view/WindowManagerGlobal.java
    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow, int userId) {
        ...

        ViewRootImpl root;
        View panelParentView = null;

        synchronized (mLock) {
            ...
            // 创建ViewRootImpl对象
            root = new ViewRootImpl(view.getContext(), display);

            view.setLayoutParams(wparams);

            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);

            // do this last because it fires off messages to start doing things
            try {
                // 调用ViewRootImpl 的 setView方法,会触发new InputChannel流程
                root.setView(view, wparams, panelParentView, userId);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }

ViewRootImpl-setView触发的创建和注册InputChannel流程:

frameworks/base/core/java/android/view/ViewRootImpl.java
    /**
     * We have one child
     */
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {
        synchronized (this) {
            if (mView == null) {
                mView = view;

                ......

                // Schedule the first layout -before- adding to the window
                // manager, to make sure we do the relayout before receiving
                // any other events from the system.
                requestLayout();
                InputChannel inputChannel = null;
                // 创建InputChannel
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    // 初始化一个空的本地InputChannel,暂时不能用于接收数据;
                    inputChannel = new InputChannel(); 
                }
                mForceDecorViewVisibility = (mWindowAttributes.privateFlags
                        & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
                // 调用wms进程中,WindowSession的addToDisplayAsUser方法;
                // 此处是一次binder跨进程调用;
                // inputChannel是一个inout类型参数,在binder调用后,会赋予此channel读取输入数据的能力。;
                // wms进程中会创建一对InputChannel,其中一个会反向赋值给此inputChannel
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    adjustLayoutParamsForCompatibility(mWindowAttributes);
                    res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mDisplayCutout, inputChannel,
                            mTempInsets, mTempControls);
                    setFrame(mTmpFrame);
                } catch (RemoteException e) {
                    ......
                } finally {
                    if (restore) {
                        attrs.restore();
                    }
                }

                ......

                if (inputChannel != null) {
                    if (mInputQueueCallback != null) {
                        mInputQueue = new InputQueue();
                        mInputQueueCallback.onInputQueueCreated(mInputQueue);
                    }
                    // 将inputChannel和WindowInputEventReceiver进行关联;
                    // 猜测InputChannel读取到的Input数据,
                    // 会触发WindowInputEventReceiver 的onInputEvent(InputEvent event)回调!
                    mInputEventReceiver = new WindowInputEventReceiver(inputChannel, Looper.myLooper());
                }
    ....
    }

注意此处有三个关键行为: inputChannel = new InputChannel();
mWindowSession.addToDisplayAsUser…; mInputEventReceiver = new
WindowInputEventReceiver(inputChannel, Looper.myLooper());
下面会跟进这三个关键行为,来分析InputChannel的创建和注册到IMS的流程:

InputChannel构造方法:
frameworks/base/core/java/android/view/InputChannel.java
public final class InputChannel implements Parcelable {
    ...
    @SuppressWarnings("unused")
    @UnsupportedAppUsage
    private long mPtr; // used by native code

    private static native InputChannel[] nativeOpenInputChannelPair(String name);

    ...
    private native void nativeTransferTo(InputChannel other);
    ...

    private native String nativeGetName();

    /**
     * Creates an uninitialized input channel.注意此处的注释,创建的是未初始化的对象。
     * It can be initialized by reading from a Parcel or by transferring the state of
     * another input channel into this one.
     */
    @UnsupportedAppUsage
    public InputChannel() {// 啥也没干,注意此时mPtr 为 0!
    }
}

来看下非常重要的mWindowSession.addToDisplayAsUser流程;
先来看下mWindowSession是什么:

frameworks/base/core/java/android/view/WindowManagerGlobal.java
    @UnsupportedAppUsage
    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    // Emulate the legacy behavior.  The global instance of InputMethodManager
                    // was instantiated here.
                    // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage
                    InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
                    IWindowManager windowManager = getWindowManagerService();
                    // mWindowSession是wms返回的一个session对象;是一个binder对象;
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            });
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
    }

// wms进程openSession方法:
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    @Override
    public IWindowSession openSession(IWindowSessionCallback callback) {
        return new Session(this, callback);
    }

// Session的构造方法
frameworks/base/services/core/java/com/android/server/wm/Session.java
    public Session(WindowManagerService service, IWindowSessionCallback callback) {
        mService = service; // wms
        mCallback = callback; // app端的new IWindowSessionCallback.Stub()
        mUid = Binder.getCallingUid(); // app 进程相关uid
        mPid = Binder.getCallingPid(); // app 进程相关pid
        mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
        mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission(
                INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
        mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission(
                HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED;
        mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER)
                == PERMISSION_GRANTED;
        mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
        mDragDropController = mService.mDragDropController;
        StringBuilder sb = new StringBuilder();
        sb.append("Session{");
        sb.append(Integer.toHexString(System.identityHashCode(this))); // 当前对象hash
        sb.append(" ");
        sb.append(mPid);
        if (mUid < Process.FIRST_APPLICATION_UID) {
            sb.append(":");
            sb.append(mUid);
        } else {
            sb.append(":u");
            sb.append(UserHandle.getUserId(mUid));
            sb.append('a');
            sb.append(UserHandle.getAppId(mUid));
        }
        sb.append("}");
        // mStringName带有this的hashCode,是每个activity/window唯一标识;
        mStringName = sb.toString(); 

        try {
            mCallback.asBinder().linkToDeath(this, 0);
        } catch (RemoteException e) {
            // The caller has died, so we can just forget about this.
            // Hmmm, should we call killSessionLocked()??
        }
    }

看到mWindowSession是WMS里new Session的binder类型的对象;
来继续跟进mWindowSession.addToDisplayAsUser流程:

frameworks/base/services/core/java/com/android/server/wm/Session.java
    // 注意入参,app侧创建的inputChannel对象,在这里是InputChannel outInputChannel;
    // 此对象在aidl中声明了inout方向,说明对于此数据的修改,可以影响到app侧;
    @Override
    public int addToDisplayAsUser(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, int userId, Rect outFrame,
            Rect outContentInsets, Rect outStableInsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
                outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
                outInsetsState, outActiveControls, userId);
    }

// win.openInputChannel,创建可以互相通信的InputChannel对;

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

    public int addWindow(Session session, IWindow client, int seq,
            LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
            Rect outContentInsets, Rect outStableInsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
            int requestUserId) {
            ...

            ActivityRecord activity = null;
            final boolean hasParent = parentWindow != null;
            // Use existing parent window token for child windows since they go in the same token
            // as there parent window so we can apply the same policy on them.
            WindowToken token = displayContent.getWindowToken(
                    hasParent ? parentWindow.mAttrs.token : attrs.token);
            ...
            if (token == null) {
                if (!unprivilegedAppCanCreateTokenWith(parentWindow, callingUid, type,
                        rootType, attrs.token, attrs.packageName)) {
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
                if (hasParent) {
                    // Use existing parent window token for child windows.
                    token = parentWindow.mToken;
                } else {
                    final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
                    token = new WindowToken(this, binder, type, false, displayContent,
                            session.mCanAddInternalSystemWindow, isRoundedCornerOverlay);
                }
            } else if (rootType >= FIRST_APPLICATION_WINDOW
            ...
            } else if (token.asActivityRecord() != null) {
                ProtoLog.w(WM_ERROR, "Non-null activity for system window of rootType=%d",
                        rootType);
                // It is not valid to use an app token with other system types; we will
                // instead make a new token for it (as if null had been passed in for the token).
                attrs.token = null;
                token = new WindowToken(this, client.asBinder(), type, false, displayContent,
                        session.mCanAddInternalSystemWindow);
            }

            // 创建WindowState对象;
            final WindowState win = new WindowState(this, session, client, token, parentWindow,
                    appOp[0], seq, attrs, viewVisibility, session.mUid, userId,
                    session.mCanAddInternalSystemWindow);
            ......

            // 通过WindowState对象尝试openInputChannel,创建通信通道;

            final boolean openInputChannels = (outInputChannel != null
                    && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
            if  (openInputChannels) {
                win.openInputChannel(outInputChannel);
            }
            ......
            win.attach();
            mWindowMap.put(client.asBinder(), win);
            win.initAppOpsState();

            ...

            win.mToken.addWindow(win);
            displayPolicy.addWindowLw(win, attrs);
            ...

            outInsetsState.set(win.getInsetsState(), win.isClientLocal());

            if (mInTouchMode) {
                res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
            }
            if (win.mActivityRecord == null || win.mActivityRecord.isClientVisible()) {
                res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
            }

            displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();

            boolean focusChanged = false;
            if (win.canReceiveKeys()) {// 可以接收按键值
                // 更新WindowFocuse?
                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                        false /*updateInputWindows*/);
                if (focusChanged) {
                    imMayMove = false;
                }
            }

            ...
            // 更新InputFocus?
            if (focusChanged) {
               displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
                        false /*updateInputWindows*/);
            }
            displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
            ...
    }

以上代码,看到以下关键流程: WindowState-openInputChannel(outInputChannel);
focusChanged =
updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
false /updateInputWindows/); displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
false /updateInputWindows/); displayContent.getInputMonitor().updateInputWindowsLw(false
/force/);

先来分析WindowState-openInputChannel(outInputChannel)方法:

frameworks/base/services/core/java/com/android/server/wm/WindowState.java
    void openInputChannel(InputChannel outInputChannel) {
        if (mInputChannel != null) {
            throw new IllegalStateException("Window already has an input channel.");
        }
        String name = getName();
        // 通过InputChannel的静态方法,创建一对InputChannel,注意入参为name;
        InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);///重要!!!
        mInputChannel = inputChannels[0];
        mClientChannel = inputChannels[1];
        // 将inputChannels[0]注册到IMS,作为服务端;
        mWmService.mInputManager.registerInputChannel(mInputChannel);
        mInputWindowHandle.token = mInputChannel.getToken();
        if (outInputChannel != null) {
            // 将inputChannels[1]复制到入参outInputChannel中,传到app中。
            // app就可以从outInputChannel中读取Input数据;
            mClientChannel.transferTo(outInputChannel);
            mClientChannel.dispose();
            mClientChannel = null;
        } else {
            // If the window died visible, we setup a dummy input channel, so that taps
            // can still detected by input monitor channel, and we can relaunch the app.
            // Create dummy event receiver that simply reports all events as handled.
            mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
        }
        mWmService.mInputToWindowMap.put(mInputWindowHandle.token, this);
    }

InputChannel.openInputChannelPair创建了一对儿可以相互通信的socket,具备一一对应的关联关系,并持有一个共同的BBinder对象。
openInputChannelPair流程在4.2.5.4章节有详细介绍,这里不再赘述,可以理解为创建了一对InputChannel(socket通信),这一对InputChannel可以相互通信。

来看下mClientChannel.transferTo(outInputChannel)方法,是如何将socket转移给outInputChannel的:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/java/android/view/InputChannel.java
    public void transferTo(InputChannel outParameter) {
        if (outParameter == null) {
            throw new IllegalArgumentException("outParameter must not be null");
        }

        nativeTransferTo(outParameter);
    }

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/jni/android_view_InputChannel.cpp
static void android_view_InputChannel_nativeTransferTo(JNIEnv* env, jobject obj,
        jobject otherObj) {
    if (android_view_InputChannel_getNativeInputChannel(env, otherObj) != nullptr) {
        jniThrowException(env, "java/lang/IllegalStateException",
                "Other object already has a native input channel.");
        return;
    }
// 获取NativeInputChannel指针对象;
    NativeInputChannel* nativeInputChannel =
            android_view_InputChannel_getNativeInputChannel(env, obj);  
// 将此NativeInputChannel指针对象赋予App端的InputChannel-mPtr中;
android_view_InputChannel_setNativeInputChannel(env, otherObj, nativeInputChannel); 
// 释放System_server层的NativeInputChannel指向的指针,置为null;    android_view_InputChannel_setNativeInputChannel(env, obj, nullptr); 
}

// 获取NativeInputChannel指针

static NativeInputChannel* android_view_InputChannel_getNativeInputChannel(JNIEnv* env,
        jobject inputChannelObj) {
    // 对象的地址;
    jlong longPtr = env->GetLongField(inputChannelObj, gInputChannelClassInfo.mPtr);
    return reinterpret_cast<NativeInputChannel*>(longPtr);
}

设置java层InputChannel的mPtr的数值,指向native指针。

static void android_view_InputChannel_setNativeInputChannel(JNIEnv* env, jobject inputChannelObj, NativeInputChannel* nativeInputChannel) {
    env->SetLongField(inputChannelObj, gInputChannelClassInfo.mPtr,
             reinterpret_cast<jlong>(nativeInputChannel));
}

至此,经过binder调用进system_server进程-mWindowSession.addToDisplayAsUse,回到App进程后,App端的InputChannel的mPtr已经被赋值;

4.2.5.2 InputChannel注册到IMS的流程

来看下WindowState-openInputChannel方法里的mInputManager.registerInputChannel(mInputChannel)流程;
server端的socket添加到了IMS中;我们猜测IMS进程获取输入事件后,通过这个server端socket对象,同App进程中的client端对象(InputChannel)进行通信;

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    public void registerInputChannel(InputChannel inputChannel) {
        if (inputChannel == null) {
            throw new IllegalArgumentException("inputChannel must not be null.");
        }
        // 注意入参mPtr,以及inputChannel;
        // mPtr是IMS初始化阶段,创建的NativeInputManager对象的指针;
        nativeRegisterInputChannel(mPtr, inputChannel);
    }
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
        jlong ptr, jobject inputChannelObj) {
    // 将mPtr转换为NativeInputManager对象;
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    // 将jobject对象转变为native层的InputChannel对象;
    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
            inputChannelObj);
    if (inputChannel == nullptr) {
        throwInputChannelNotInitialized(env);
        return;
    }

    // InputManager.cpp的registerInputChannel方法;
    status_t status = im->registerInputChannel(env, inputChannel); 

    if (status) {
        std::string message;
        message += StringPrintf("Failed to register input channel.  status=%d", status);
        jniThrowRuntimeException(env, message.c_str());
        return;
    }

    android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
            handleInputChannelDisposed, im);
}

我们看到以上流程,是将InputChannel对象,注册到IMS的native层中; 以上代码有两个关键函数:
sp inputChannel =
android_view_InputChannel_getInputChannel(env,
inputChannelObj); status_t status = im->registerInputChannel(env, inputChannel);

android_view_InputChannel_getInputChannel方法:

frameworks/base/core/jni/android_view_InputChannel.cpp
sp<InputChannel> android_view_InputChannel_getInputChannel(JNIEnv* env, jobject inputChannelObj) {
    // 将inputChannelObj 转变为NativeInputChannel对象;
    NativeInputChannel* nativeInputChannel =
            android_view_InputChannel_getNativeInputChannel(env, inputChannelObj);
    // 从NativeInputChannel获取InputChannel并返回
     nativeInputChannel != nullptr ? nativeInputChannel->getInputChannel() : nullptr;
}

// android_view_InputChannel_getNativeInputChannel 方法:

static NativeInputChannel* android_view_InputChannel_getNativeInputChannel(JNIEnv* env,
        jobject inputChannelObj) {
    // 获取NativeInputChannel的内存指针:
    jlong longPtr = env->GetLongField(inputChannelObj, gInputChannelClassInfo.mPtr);
    return reinterpret_cast<NativeInputChannel*>(longPtr);
}

// NativeInputChannel的声明;
// InputChannel中包含new InputChannel(name, std::move(fd), token);

frameworks/base/core/jni/android_view_InputChannel.cpp
class NativeInputChannel {
public:
    explicit NativeInputChannel(const sp<InputChannel>& inputChannel);
    ~NativeInputChannel();

    inline sp<InputChannel> getInputChannel() { return mInputChannel; }

    void setDisposeCallback(InputChannelObjDisposeCallback callback, void* data);
    void invokeAndRemoveDisposeCallback(JNIEnv* env, jobject obj);

private:
    sp<InputChannel> mInputChannel;
    InputChannelObjDisposeCallback mDisposeCallback;
    void* mDisposeData;
};

im->registerInputChannel(env, inputChannel)流程:
frameworks/native/services/inputflinger/InputManager.cpp
void InputManager::registerInputChannel(const sp<InputChannel>& channel) {
    IPCThreadState* ipc = IPCThreadState::self();
    const int uid = ipc->getCallingUid();
    if (uid != AID_SHELL && uid != AID_ROOT) {
        ALOGE("Invalid attempt to register input channel over IPC"
                "from non shell/root entity (PID: %d)", ipc->getCallingPid());
        return;
    }
    // 调用InputDispatcher的注册方法,将InputChannel注册到InputDispatcher中;
    mDispatcher->registerInputChannel(channel);
}


frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
#if DEBUG_REGISTRATION
    ALOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().c_str());
#endif

    { // acquire lock
        std::scoped_lock _l(mLock);
        sp<Connection> existingConnection = getConnectionLocked(inputChannel->getConnectionToken());
        if (existingConnection != nullptr) {
            ALOGW("Attempted to register already registered input channel '%s'",
                  inputChannel->getName().c_str());
            return BAD_VALUE;
        }

        // 将inputChannel封装在了Connection对象中;
        sp<Connection> connection = new Connection(inputChannel, false /*monitor*/, mIdGenerator); // InputChannel封装到了Connection中

        // socket的fd;
        int fd = inputChannel->getFd();
        // 将封装了InputChannel的Connection,保存在mConnectionsByFd中;
        mConnectionsByFd[fd] = connection; // fd和connection的对应关系
        // token和inputChannel的对应关系,保存在了mInputChannelsByToken中;
        mInputChannelsByToken[inputChannel->getConnectionToken()] = inputChannel; // token 和 inputChannel的对应关系;

        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
    } // release lock

    // Wake the looper because some connections have changed.
    mLooper->wake();
    return OK;
}

// handleReceiveCallback方法,此方法在其他章节进行分析,属于事件传递流程的一部分:
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
...
}

//mConnectionsByFd和mInputChannelsByToken的数据声明:
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.h

// All registered connections mapped by channel file descriptor.
std::unordered_map<int, sp<Connection>> mConnectionsByFd GUARDED_BY(mLock);

std::unordered_map<sp<IBinder>, sp<InputChannel>, IBinderHash> mInputChannelsByToken
        GUARDED_BY(mLock);

至此WindowState-openInputChannel(outInputChannel)方法结束;
以上流程,把一个InputChannel注册到了system_server进程,保存在了IMS-InputDispatcher对象中的两个map数据结构中mConnectionsByFd、mInputChannelsByToken。
我们猜测IMS收到InputEvent输入事件后,会将数据传入InputChannel中;另一个InputChannel会传递给app侧,作为通信通道的另一端,来接收输入事件;

4.2.5.3 Window和焦点display变更流程

WindowManagerService-addWindow中,WindowState-openInputChannel(outInputChannel)创建并注册InputChannel到IMS中;
之后调用了以下方法,来更新焦点屏幕和焦点window:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,
        LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
        Rect outContentInsets, Rect outStableInsets,
        DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
        InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
        int requestUserId) {
......
创建和注册InputChannel;
......
//1-1流程
displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
                        false /*updateInputWindows*/);
//1-2流程
focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                        false /*updateInputWindows*/);
//1-3流程
displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
...
}

1-1,来看下第二个关键方法调用,即WMS-addView-addWindow中的以下关键方法调用:
displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus, false /updateInputWindows/);

先来看displayContent和getInputMonitor都分别指向什么类型的对象,才能知道displayContent.mCurrentFocus是什么类型.
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
final DisplayContent displayContent = win.getDisplayContent();

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/WindowState.java
    @Override
    DisplayContent getDisplayContent() {
        return mToken.getDisplayContent();
    }

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
                token = new WindowToken(this, client.asBinder(), type, false, displayContent, session.mCanAddInternalSystemWindow);

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java-WindowToken.class-getDisplayContent()方法:
            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    private DisplayContent getDisplayContentOrCreate(int displayId, IBinder token) {
        if (token != null) {
            final WindowToken wToken = mRoot.getWindowToken(token);
            if (wToken != null) {
                return wToken.getDisplayContent();
            }
        }
        // 创建或获取DisplayContent.
        return mRoot.getDisplayContentOrCreate(displayId);
    }

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
mRoot = new RootWindowContainer(this);

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
    /**
     * Get an existing instance of {@link DisplayContent} or create new if there is a
     * corresponding record in display manager.
     */
    // TODO: Look into consolidating with getDisplayContent()
    @Nullable DisplayContent getDisplayContentOrCreate(int displayId) {
        DisplayContent displayContent = getDisplayContent(displayId);
        if (displayContent != null) {
            return displayContent;
        }
        if (mDisplayManager == null) {
            // The system isn't fully initialized yet.
            return null;
        }

        // 根据displayId,获取display信息
        final Display display = mDisplayManager.getDisplay(displayId);
        if (display == null) {
            // The display is not registered in DisplayManager.
            return null;
        }
        // 根据displayId,创建新的displayContent。
        // The display hasn't been added to ActivityManager yet, create a new record now.
        displayContent = new DisplayContent(display, this);
        addChild(displayContent, POSITION_BOTTOM);
        return displayContent;
    }

可见displayContent就是跟displayId一一对应的DisplayContent对象。
DisplayContent.getInputMonitor返回的是什么对象呢?

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
mInputMonitor = new InputMonitor(mWmService, this);
InputMonitor是跟WMSDisplayContent相关的一个对象;
setInputFocusLw的入参是如下类型的WindowState对象,代表了一个交互的window,入参还包含一个false变量;
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
    /**
     * Window that is currently interacting with the user. This window is responsible for receiving
     * key events and pointer events from the user.
     */
    WindowState mCurrentFocus = null;

    // Current window with input focus for keys and other non-touch events.  May be null.
    private WindowState mInputFocus;

来分析1-1的函数调用:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
    /**
     * Called when the current input focus changes.
     * Layer assignment is assumed to be complete by the time this is called.
     * 当此方法调用后,层级分配就会完成。
     */
    public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
        ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "Input focus has changed to %s", newWindow);

        if (newWindow != mInputFocus) {
            if (newWindow != null && newWindow.canReceiveKeys()) {
                // Displaying a window implicitly causes dispatching to be unpaused.
                // This is to protect against bugs if someone pauses dispatching but
                // forgets to resume.
                newWindow.mToken.paused = false;
            }

// 更新当前输入焦点窗口,注意当前对象是跟某个屏幕对应的DisplayContent-InputMonitor对象;
            mInputFocus = newWindow;
            // 关键方法调用1-1-1;
            setUpdateInputWindowsNeededLw();
            if (updateInputWindows) { // 此处为false,不执行此处
                updateInputWindowsLw(false /*force*/);
            }
        }
    }

1-1-1,setUpdateInputWindowsNeededLw():

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
    void setUpdateInputWindowsNeededLw() {
        mUpdateInputWindowsNeeded = true;
    }

setUpdateInputWindowsNeededLw这个只是设置了一个变量mUpdateInputWindowsNeeded 为true,没有调用其他方法;

总结:
displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
false /updateInputWindows/);
以上方法的作用,为某个屏幕DisplayContent赋值了mInputFocus(WindowState类型),并且将mUpdateInputWindowsNeeded赋值为了true;

1-2,来分析WMS-updateFocusedWindowLocked方法.
updateFocusedWindowLocked方法会是更新焦点Window吗?

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
    ...
    boolean changed = mRoot.updateFocusedWindowLocked(mode, updateInputWindows);
    ...
    return changed;
}
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
    mTopFocusedAppByProcess.clear();
    boolean changed = false;
    int topFocusedDisplayId = INVALID_DISPLAY;
    for (int i = mChildren.size() - 1; i >= 0; --i) {
        final DisplayContent dc = mChildren.get(i);// dc是某个屏幕的代理?
// 让每个屏幕updateFocusedWindowLocked;
        changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows, topFocusedDisplayId);
        final WindowState newFocus = dc.mCurrentFocus;
        if (newFocus != null) {
            final int pidOfNewFocus = newFocus.mSession.mPid;
            if (mTopFocusedAppByProcess.get(pidOfNewFocus) == null) {
                mTopFocusedAppByProcess.put(pidOfNewFocus, newFocus.mActivityRecord);
            }
            if (topFocusedDisplayId == INVALID_DISPLAY) {
                topFocusedDisplayId = dc.getDisplayId();
            }
        } else if (topFocusedDisplayId == INVALID_DISPLAY && dc.mFocusedApp != null) {
            // The top-most display that has a focused app should still be the top focused
            // display even when the app window is not ready yet (process not attached or
            // window not added yet).
            topFocusedDisplayId = dc.getDisplayId();
        }
    }
// 遍历确认焦点屏幕topFocusedDisplayId
    if (topFocusedDisplayId == INVALID_DISPLAY) { 
        topFocusedDisplayId = DEFAULT_DISPLAY;
    }
    if (mTopFocusedDisplayId != topFocusedDisplayId) {
// 更新 mTopFocusedDisplayId .
        mTopFocusedDisplayId = topFocusedDisplayId;
        // 更新IMS-InputDispatcher中的mFocusedDisplayId;
        mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
        // 更新wms-PhoneWindowManager中的mTopFocusedDisplayId;
        mWmService.mPolicy.setTopFocusedDisplay(topFocusedDisplayId);
        ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d",
                topFocusedDisplayId);
    }
    return changed;
}

此处updateFocusedWindowLocked会去更新IMS和WMS里的mFocusedDisplayId和mTopFocusedDisplayId;

来看下setFocusedDisplay的流程;
此处会更新IMS-InputDispatcher中的mFocusedDisplayId:

mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public void setFocusedDisplay(int displayId) {
// jni调用
    nativeSetFocusedDisplay(mPtr, displayId);
}
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeSetFocusedDisplay(JNIEnv* env, jclass /* clazz /,
 jlong ptr, jint displayId) {
 NativeInputManager im = reinterpret_cast<NativeInputManager*>(ptr);
im->setFocusedDisplay(env, displayId);
}
// 通知InputDispatcher输入时间分发者更新焦点屏幕;
void NativeInputManager::setFocusedDisplay(JNIEnv* env, int32_t displayId) {
 mInputManager->getDispatcher()->setFocusedDisplay(displayId);
}


// 设置焦点屏幕,用于赋值给未指定屏幕id的输入事件的displayId;
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
/**
 * Sets the focused display, which is responsible for receiving focus-dispatched input events where
 * the display not specified.
 *
 * We track any unreleased events for each window. If a window loses the ability to receive the
 * released event, we will send a cancel event to it. So when the focused display is changed, we
 * cancel all the unreleased display-unspecified events for the focused window on the old focused
 * display. The display-specified events won't be affected.
 * 屏幕焦点变更时,对旧的焦点屏幕,取消所有未指定屏幕ID的事件,指定了ID的事件不受影响;
 */
void InputDispatcher::setFocusedDisplay(int32_t displayId) {
    if (DEBUG_FOCUS) {
        ALOGD("setFocusedDisplay displayId=%" PRId32, displayId);
    }
    { // acquire lock
        std::scoped_lock _l(mLock);

        if (mFocusedDisplayId != displayId) {
            sp<InputWindowHandle> oldFocusedWindowHandle =
                    getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
            // 对旧的windowHandle发送取消的消息;
            if (oldFocusedWindowHandle != nullptr) {
                sp<InputChannel> inputChannel =
                        getInputChannelLocked(oldFocusedWindowHandle->getToken());
                if (inputChannel != nullptr) {
                    CancelationOptions
                            options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
                                    "The display which contains this window no longer has focus.");
                    options.displayId = ADISPLAY_ID_NONE;
                    synthesizeCancelationEventsForInputChannelLocked(inputChannel, options);
                }
            }
            // 更新焦点屏幕Id-mFocusedDisplayId;
            mFocusedDisplayId = displayId;

            // Sanity check
            sp<InputWindowHandle> newFocusedWindowHandle =
                    getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
            // 通知焦点窗口变更;
            onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);

           // 此处判断只打印了一些log?
            if (newFocusedWindowHandle == nullptr) {
                ALOGW("Focused display #%" PRId32 " does not have a focused window.", displayId);
                if (!mFocusedWindowHandlesByDisplay.empty()) {
                    ALOGE("But another display has a focused window:");
                    for (auto& it : mFocusedWindowHandlesByDisplay) {
                        const int32_t displayId = it.first;
                        const sp<InputWindowHandle>& windowHandle = it.second;
                        ALOGE("Display #%" PRId32 " has focused window: '%s'\n", displayId,
                              windowHandle->getName().c_str());
                    }
                }
            }
        }

        if (DEBUG_FOCUS) {
            logDispatchStateLocked();
        }
    } // release lock

    // Wake up poll loop since it may need to make new input dispatching choices.
    mLooper->wake();
}

// 通知焦点窗口变更;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
                                           const sp<InputWindowHandle>& newFocus) {
    sp<IBinder> oldToken = oldFocus != nullptr ? oldFocus->getToken() : nullptr;
    sp<IBinder> newToken = newFocus != nullptr ? newFocus->getToken() : nullptr;
    std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
            &InputDispatcher::doNotifyFocusChangedLockedInterruptible);
    commandEntry->oldToken = oldToken;
    commandEntry->newToken = newToken;
    postCommandLocked(std::move(commandEntry));
}


/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) {
    sp<IBinder> oldToken = commandEntry->oldToken;
    sp<IBinder> newToken = commandEntry->newToken;
    mLock.unlock();
    // 调用NativeInputManagerService的notifyFocusChanged,通知到上层。
    mPolicy->notifyFocusChanged(oldToken, newToken);
    mLock.lock();
}

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
void NativeInputManager::notifyFocusChanged(const sp<IBinder>& oldToken,
        const sp<IBinder>& newToken) {
#if DEBUG_INPUT_DISPATCHER_POLICY
    ALOGD("notifyFocusChanged");
#endif
    ATRACE_CALL();

    JNIEnv* env = jniEnv();
    ScopedLocalFrame localFrame(env);

    jobject oldTokenObj = javaObjectForIBinder(env, oldToken);
    jobject newTokenObj = javaObjectForIBinder(env, newToken);
    // 调用上层IMS的notifyFocusChanged方法。
    env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyFocusChanged,
            oldTokenObj, newTokenObj);
    checkAndClearExceptionFromCallback(env, "notifyFocusChanged");
}


// 此处未看出跟IMS的关系,暂不跟进,暂时忽略此处的作用;
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    // Native callback
    private void notifyFocusChanged(IBinder oldToken, IBinder newToken) {
        final boolean requestConfigurationRefresh =
                mWindowManagerCallbacks.notifyFocusChanged(oldToken, newToken);
        if (requestConfigurationRefresh) {
            nativeSetPointerCapture(mPtr, false);
        }
    }

总结:
mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId);更新了InputDispatcher中的焦点屏幕;并通知了Java层window焦点变更的消息;

#来分析上面的1-3方法:
displayContent.getInputMonitor().updateInputWindowsLw(false /force/);

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
    /* Updates the cached window information provided to the input dispatcher. */
    void updateInputWindowsLw(boolean force) {
        if (!force && !mUpdateInputWindowsNeeded) {
            return;// mUpdateInputWindowsNeeded为true,则不会走到此处的return逻辑;
        }
        scheduleUpdateInputWindows();
    }
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
    private void scheduleUpdateInputWindows() {
        if (mDisplayRemoved) {
            return;
        }

        if (!mUpdateInputWindowsPending) { // 初始为false
            mUpdateInputWindowsPending = true;
            mHandler.post(mUpdateInputWindows);
        }
    }
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
    private final UpdateInputWindows mUpdateInputWindows = new UpdateInputWindows();

通过handler执行mUpdateInputWindows 此runable的run方法;

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
    private class UpdateInputWindows implements Runnable {
        @Override
        public void run() {
            synchronized (mService.mGlobalLock) {
                mUpdateInputWindowsPending = false;
                mUpdateInputWindowsNeeded = false;
                if (mDisplayRemoved) {
                    return;
                }

                // Populate the input window list with information about all of the windows that
                // could potentially receive input.
                // As an optimization, we could try to prune the list of windows but this turns
                // out to be difficult because only the native code knows for sure which window
                // currently has touch focus.

                // If there's a drag in flight, provide a pseudo-window to catch drag input
                final boolean inDrag = mService.mDragDropController.dragDropActiveLocked();

                // Add all windows on the default display.
                mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
            }
        }
    }


/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
        private void updateInputWindows(boolean inDrag) {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateInputWindows");

            mNavInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION);
            mPipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP);
            mWallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER);
            mRecentsAnimationInputConsumer = getInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);

            mAddNavInputConsumerHandle = mNavInputConsumer != null;
            mAddPipInputConsumerHandle = mPipInputConsumer != null;
            mAddWallpaperInputConsumerHandle = mWallpaperInputConsumer != null;
            mAddRecentsAnimationInputConsumerHandle = mRecentsAnimationInputConsumer != null;

            mTmpRect.setEmpty();
            mDisableWallpaperTouchEvents = false;
            mInDrag = inDrag;
            mWallpaperController = mDisplayContent.mWallpaperController;

            resetInputConsumers(mInputTransaction);

            // 重新计算层级?
            mDisplayContent.forAllWindows(this,
                    true /* traverseTopToBottom */);

            if (!mUpdateInputWindowsImmediately) {
                mDisplayContent.getPendingTransaction().merge(mInputTransaction);
                mDisplayContent.scheduleAnimation();
            }

            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/java/android/view/WindowManager.java
    /** @hide */
    String INPUT_CONSUMER_PIP = "pip_input_consumer";
    /** @hide */
    String INPUT_CONSUMER_NAVIGATION = "nav_input_consumer";
    /** @hide */
    String INPUT_CONSUMER_WALLPAPER = "wallpaper_input_consumer";
    /** @hide */
    String INPUT_CONSUMER_RECENTS_ANIMATION = "recents_animation_input_consumer";

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
    void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
        ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
        forAllWindows(wrapper, traverseTopToBottom); // wrapper, true
        wrapper.release();
    }

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
    /**
     * For all windows at or below this container call the callback.
     * @param   callback Calls the {@link ToBooleanFunction#apply} method for each window found and
     *                   stops the search if {@link ToBooleanFunction#apply} returns true.
     * @param   traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
     *                              z-order, else from bottom-to-top.
     * @return  True if the search ended before we reached the end of the hierarchy due to
     *          {@link ToBooleanFunction#apply} returning true.
     */
    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
        if (traverseTopToBottom) {
            for (int i = mChildren.size() - 1; i >= 0; --i) {
                // 调用mChildren中的每个WindowState的forAllWindows方法,callback在InputMonitor中,traverseTopToBottom为true;
                if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
                    return true;
                }
            }
        } else {
            final int count = mChildren.size();
            for (int i = 0; i < count; i++) {
                if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
                    return true;
                }
            }
        }
        return false;
    }

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/WindowState.java
    @Override
    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
        if (mChildren.isEmpty()) {
            // The window has no children so we just return it.
            return applyInOrderWithImeWindows(callback, traverseTopToBottom);// 假设无子window;
        }

        if (traverseTopToBottom) {
            return forAllWindowTopToBottom(callback);
        } else {
            return forAllWindowBottomToTop(callback);
        }
    }


/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/WindowState.java
    private boolean applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback,
            boolean traverseTopToBottom) {
        if (traverseTopToBottom) {
        // 调用applyImeWindowsIfNeeded 和 callback.apply(this),调用applyImeWindowsIfNeeded跟IME相关,暂不关注。
            if (applyImeWindowsIfNeeded(callback, traverseTopToBottom)
                    || callback.apply(this)) {
                return true;
            }
        } else {
            if (callback.apply(this)
                    || applyImeWindowsIfNeeded(callback, traverseTopToBottom)) {
                return true;
            }
        }
        return false;
    }

来分析ForAllWindowsConsumerWrapper-callback.apply(this)方法:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
        @Override
        public void accept(WindowState w) {
            final InputChannel inputChannel = w.mInputChannel; // windowState的InputChannel;
            final InputWindowHandle inputWindowHandle = w.mInputWindowHandle; // windowState的mInputWindowHandle
            final RecentsAnimationController recentsAnimationController =
                    mService.getRecentsAnimationController();
            final boolean shouldApplyRecentsInputConsumer = recentsAnimationController != null
                    && recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord);
            final int type = w.mAttrs.type;
            final boolean isVisible = w.isVisibleLw();
            if (inputChannel == null || inputWindowHandle == null || w.mRemoved
                    || (w.cantReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) {
                ......
                // Skip this window because it cannot possibly receive input.
                return;
            }

            final int flags = w.mAttrs.flags;
            final int privateFlags = w.mAttrs.privateFlags;
            final boolean hasFocus = w.isFocused();

            ......
            // 为inputWindowHandle赋予各种属性,如name,flag,type,canReceivekeys,displayId,left/right/top/bottom,surface,scale等属性。
            // 将InputMonitor的mFocusedInputWindowHandle指向此inputWindowHandle;
            populateInputWindowHandle(
                    inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);

            // 将KeyInterceptionInfo放入wms的一个map中;
            // register key interception info
            mService.mKeyInterceptionInfoForToken.put(inputWindowHandle.token,
                    w.getKeyInterceptionInfo());

            // 如果存在surface,则执行此信息;认为对事件传递影响不大,暂不跟进此流程;
            if (w.mWinAnimator.hasSurface()) {
                mInputTransaction.setInputWindowInfo(
                    w.mWinAnimator.mSurfaceController.getClientViewRootSurface(),
                    inputWindowHandle);
            }
        }
    }

总结:
WMS-addWindow-displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
false)方法的作用,是遍历WindowState,然后给每个InputWindowHandle赋值,并将InputMonitor的mFocusedInputWindowHandle指向唯一一个inputWindowHandle;

至此addWindow方法分析完毕!
系统在这里创建并关联了一对InputChannel,更新了IMS中的焦点displayId,更新了WMS-DisplayContent-InputMonitor中的焦点InputWIndowHandle。

4.2.5.4 openInputChannelPair流程

来看下openInputChannelPair方法,理解InputChannel的内部原理:

frameworks/base/core/java/android/view/InputChannel.java
    public static InputChannel[] openInputChannelPair(String name) {
        if (name == null) {
            throw new IllegalArgumentException("name must not be null");
        }

        if (DEBUG) {
            Slog.d(TAG, "Opening input channel pair '" + name + "'");
        }
        return nativeOpenInputChannelPair(name);
    }


frameworks/base/core/jni/android_view_InputChannel.cpp

static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
        jclass clazz, jstring nameObj) {
    ScopedUtfChars nameChars(env, nameObj);
    std::string name = nameChars.c_str();

    sp<InputChannel> serverChannel;
    sp<InputChannel> clientChannel;
    status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel); //   打开管道,创建InputChannel数组,并赋值给serverChannel和clientChannel

    if (result) {
        std::string message = android::base::StringPrintf(
                "Could not open input channel pair : %s", strerror(-result));
        jniThrowRuntimeException(env, message.c_str());
        return nullptr;
    }
    // 创建java object数组;
    jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, nullptr);
    if (env->ExceptionCheck()) {
        return nullptr;
    }

    jobject serverChannelObj = android_view_InputChannel_createInputChannel(env, serverChannel);
    if (env->ExceptionCheck()) {
        return nullptr;
    }

    jobject clientChannelObj = android_view_InputChannel_createInputChannel(env, clientChannel);
    if (env->ExceptionCheck()) {
        return nullptr;
    }

    env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
    env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
// 把服务端管道和客户端管道放在jobjectArray数组中并返回给java层;
    return channelPair; 
}

此处我们需要分析以下两个关键方法: 1,InputChannel::openInputChannelPair(name,
serverChannel, clientChannel);
2,android_view_InputChannel_createInputChannel(env, serverChannel);

InputChannel类的定义在以下.h文件中:
frameworks/native/include/input/InputTransport.h


```cpp
frameworks/native/libs/input/InputTransport.cpp
status_t InputChannel::openInputChannelPair(const std::string& name,
        sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
    int sockets[2];
// socketpair方法的注释如下,是在sockey.h中定义的通用方法:
/* Create two new sockets, of type TYPE in domain DOMAIN and using
protocol PROTOCOL, which are connected to each other, and put file
descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
one will be chosen automatically. Returns 0 on success, -1 for errors. */
// extern int socketpair (int __domain, int __type, int __protocol,int __fds[2]) __THROW;
// 创建可相互通信的socket0 和socket1,也就是我们常说的server和client。
// server传递给了IMS,client传递给了App.
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
        status_t result = -errno;
        ALOGE("channel '%s' ~ Could not create socket pair.  errno=%d",
                name.c_str(), errno);
        outServerChannel.clear();
        outClientChannel.clear();
        return result;
    }

// 设置socket的读写配置?
    int bufferSize = SOCKET_BUFFER_SIZE;
    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));
    // binder 对象;
    sp<IBinder> token = new BBinder();

    std::string serverChannelName = name + " (server)";
    android::base::unique_fd serverFd(sockets[0]);
// 创建InputChannelPair中的一个,入参是一个socket的fd;
    outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);

    std::string clientChannelName = name + " (client)";
    android::base::unique_fd clientFd(sockets[1]);
// 创建InputChannelPair中的另一个,入参是另一个socket的fd文件描述符;
// 实际是通过共享内容通信?
    outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);
    return OK;
}

frameworks/native/libs/input/InputTransport.cpp
sp<InputChannel> InputChannel::create(const std::string& name, android::base::unique_fd fd,
                                      sp<IBinder> token) {
// 设置文件标志为O_NONBLOCK
// 非阻塞I/O;如果read(2)调用没有可读取的数据,或者如果write(2)操作将阻塞
    const int result = fcntl(fd, F_SETFL, O_NONBLOCK); 
    if (result != 0) {
        LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket non-blocking: %s", name.c_str(), strerror(errno));
        return nullptr;
    }
    return new InputChannel(name, std::move(fd), token);
}

InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd, sp<IBinder> token)
      : mName(name), mFd(std::move(fd)), mToken(token) {
    ...
}

至此InputChannel::openInputChannelPair方法分析完成,此处创建了一对可以相互通信的socket,然后将两个socket的fd分别赋值给了两个InputChannel,这样两个InputChannel就可以依赖socket相互通信了。

来分析android_view_InputChannel_createInputChannel(env, serverChannel)创建java层对象的流程:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/jni/android_view_InputChannel.cpp
static jobject android_view_InputChannel_createInputChannel(JNIEnv* env,
        sp<InputChannel> inputChannel) {
    std::unique_ptr<NativeInputChannel> nativeInputChannel =
            std::make_unique<NativeInputChannel>(inputChannel);
    // 创建java层对象
    jobject inputChannelObj = env->NewObject(gInputChannelClassInfo.clazz,
            gInputChannelClassInfo.ctor);
    if (inputChannelObj) {
        android_view_InputChannel_setNativeInputChannel(env, inputChannelObj,
                 nativeInputChannel.release());
    }
    return inputChannelObj;
}

//NativeInputChannel的构造

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/jni/android_view_InputChannel.cpp
class NativeInputChannel {
public:
    explicit NativeInputChannel(const sp<InputChannel>& inputChannel);
    ~NativeInputChannel();

    inline sp<InputChannel> getInputChannel() { return mInputChannel; }

    void setDisposeCallback(InputChannelObjDisposeCallback callback, void* data);
    void invokeAndRemoveDisposeCallback(JNIEnv* env, jobject obj);

private:
    sp<InputChannel> mInputChannel;
    InputChannelObjDisposeCallback mDisposeCallback;
    void* mDisposeData;
};

// 给Java层InputChannel-mPtr赋值,将nativeInputChannel的地址,传给inputChannelObj-mPtr;
static void android_view_InputChannel_setNativeInputChannel(JNIEnv* env, jobject inputChannelObj, NativeInputChannel* nativeInputChannel) {
    env->SetLongField(inputChannelObj, gInputChannelClassInfo.mPtr,
             reinterpret_cast<jlong>(nativeInputChannel));
}

至此,我们知道了InputChannel.openInputChannelPair的原理,是在native层创建了一对可以相互通信的socket,然后又创建了一对InputChannel对象,每个InputChannel持有了一个socket的fd,依赖socket的能力来达到互相通信的目的!

4.2.5.5 App初始化InputEventReceiver流程

这里分析下ViewRootImpl-setView里,WindowSession.addToDisplayAsUser的后续流程;

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/java/android/view/ViewRootImpl.java
    /**
     * We have one child
     */
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
        synchronized (this) {
            if (mView == null) {
                mView = view;

                ......

                // Schedule the first layout -before- adding to the window
                // manager, to make sure we do the relayout before receiving
                // any other events from the system.
                requestLayout();
                InputChannel inputChannel = null;
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    inputChannel = new InputChannel(); // 创建一个空的InputChannel,在下面的addToDisplayAsUser方法中,会给此InputChannel赋值。
                }
                mForceDecorViewVisibility = (mWindowAttributes.privateFlags
                        & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    adjustLayoutParamsForCompatibility(mWindowAttributes);
                    res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mDisplayCutout, inputChannel,
                            mTempInsets, mTempControls);
                    setFrame(mTmpFrame);
                } catch (RemoteException e) {
                    ...
                } finally {
                ......
                if (inputChannel != null) {
                    if (mInputQueueCallback != null) {
                        mInputQueue = new InputQueue();
                        mInputQueueCallback.onInputQueueCreated(mInputQueue);
                    }
                    // 创建WindowInputEventReceiver对象,此对象会从inputChannel中读取输入事件数据,并传递给ViewRootImpl中的view对象;
                    mInputEventReceiver = new WindowInputEventReceiver(inputChannel, Looper.myLooper());
                }
    ....
    }

来看下WindowInputEventReceiver的构造和方法实现:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/java/android/view/ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {
    // 构造方法,继承自InputEventReceiver 
        public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
        }

        // 注意此处重写的onInputEvent方法!!
        @Override
        public void onInputEvent(InputEvent event) {
            ......
                // 开始传递InputEvent队列,注意参数;
                enqueueInputEvent(event, this, 0, true);
            }
        }

来分析InputEventReceiver 的构造方法:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/java/android/view/InputEventReceiver.java
    /**
     * Creates an input event receiver bound to the specified input channel.
     *
     * @param inputChannel The input channel.
     * @param looper The looper to use when invoking callbacks.
     */
    public InputEventReceiver(InputChannel inputChannel, Looper looper) {
        if (inputChannel == null) {
            throw new IllegalArgumentException("inputChannel must not be null");
        }
        if (looper == null) {
            throw new IllegalArgumentException("looper must not be null");
        }

        mInputChannel = inputChannel;
        mMessageQueue = looper.getQueue();
        // // 调用nativeInit,返回一个native层的NativeInputEventReceiver指针对象;
        mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
                inputChannel, mMessageQueue); 
        mCloseGuard.open("dispose");
    }

看下nativeInit的功能:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/jni/android_view_InputEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject inputChannelObj, jobject messageQueueObj) {
    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
            inputChannelObj); // 获取mPtr代表的native层InputChannel对象;
    if (inputChannel == nullptr) {
        jniThrowRuntimeException(env, "InputChannel is not initialized.");
        return 0;
    }

    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == nullptr) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

//创建NativeInputEventReceiver对象
    sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
            receiverWeak, inputChannel, messageQueue); 
//初始化,此处开始InputChannel的事件回调监听;
    status_t status = receiver->initialize();
    if (status) {
        String8 message;
        message.appendFormat("Failed to initialize input event receiver.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
        return 0;
    }

    receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
    return reinterpret_cast<jlong>(receiver.get());
}

来分析NativeInputEventReceiver的构造方法和initialize方法:

NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
        jobject receiverWeak, const sp<InputChannel>& inputChannel,
        const sp<MessageQueue>& messageQueue) :
        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
        mInputConsumer(inputChannel), mMessageQueue(messageQueue),
        mBatchedInputEventPending(false), mFdEvents(0) {
    if (kDebugDispatchCycle) {
        ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName().c_str());
    }
}

mInputConsumer(inputChannel);inputChannel赋值给了mInputConsumer;注意此处的进程是App进程;

// initialize 方法:
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/jni/android_view_InputEventReceiver.cpp
status_t NativeInputEventReceiver::initialize() {
    setFdEvents(ALOOPER_EVENT_INPUT);
    return OK;
}

// 通过ALOOPER_EVENT_INPUT消息,开始循环监听输入事件;
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/jni/android_view_InputEventReceiver.cpp 
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);
        } else {
            mMessageQueue->getLooper()->removeFd(fd);
        }
    }
}

NativeInputEventReceiver继承了LooperCallback,在以下方法中,回调ALOOPER_EVENT_INPUT事件;
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/jni/android_view_InputEventReceiver.cpp
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
        // This error typically occurs when the publisher has closed the input channel
        ......
        return 0; // remove the callback
    }
// 是Input事件,则通过consumeEvents方法开始接收事件;
// mInputConsumer(inputChannel)对象会读取到这些数据
    if (events & ALOOPER_EVENT_INPUT) { ;
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        status_t status = consumeEvents(env, false /*consumeBatches*/, -1, nullptr);
        mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
        return status == OK || status == NO_MEMORY ? 1 : 0;
}

// 异常msg
    if (events & ALOOPER_EVENT_OUTPUT) { 
        ......
        mFinishQueue.clear();
        setFdEvents(ALOOPER_EVENT_INPUT);
        return 1;
    }

    ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
            "events=0x%x", getInputChannelName().c_str(), events);
    return 1;
}

关键的consumeEvents方法:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/core/jni/android_view_InputEventReceiver.cpp
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
    if (kDebugDispatchCycle) {
        ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%" PRId64,
              getInputChannelName().c_str(), toString(consumeBatches), frameTime);
    }

    if (consumeBatches) {
        mBatchedInputEventPending = false;
    }
    if (outConsumedBatch) {
        *outConsumedBatch = false;
    }

    ScopedLocalRef<jobject> receiverObj(env, nullptr);
    bool skipCallbacks = false;
    // 循环接收InputChannel中的数据,并发给上层逻辑;
    for (;;) {
        uint32_t seq;
        InputEvent* inputEvent; // inputEvent指针
        // InputChannel的consume方法,将输入事件读取到inputEvent中;
        status_t status = mInputConsumer.consume(&mInputEventFactory,
                consumeBatches, frameTime, &seq, &inputEvent);
        if (status != OK && status != WOULD_BLOCK) {
            ALOGE("channel '%s' ~ Failed to consume input event.  status=%d",
                  getInputChannelName().c_str(), status);
            return status;
        }

        if (status == WOULD_BLOCK) {
            ......
            return OK;
        }
        assert(inputEvent);

        if (!skipCallbacks) {
            if (!receiverObj.get()) {
                ......
            }

            jobject inputEventObj;
            // 判断输入事件类型,motion事件,key事件,focus事件等类型。
            switch (inputEvent->getType()) {
            case AINPUT_EVENT_TYPE_KEY:
                if (kDebugDispatchCycle) {
                    ALOGD("channel '%s' ~ Received key event.", getInputChannelName().c_str());
                }
                // 将inputEvent转化为java的KeyEvent类型object按键对象;
                inputEventObj = android_view_KeyEvent_fromNative(env,
                        static_cast<KeyEvent*>(inputEvent));
                break;

            case AINPUT_EVENT_TYPE_MOTION: {
                if (kDebugDispatchCycle) {
                    ALOGD("channel '%s' ~ Received motion event.", getInputChannelName().c_str());
                }
                MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent);
                if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch) {
                    *outConsumedBatch = true;
                }
                inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
                break;
            }
            case AINPUT_EVENT_TYPE_FOCUS: {
                FocusEvent* focusEvent = static_cast<FocusEvent*>(inputEvent);
                if (kDebugDispatchCycle) {
                    ALOGD("channel '%s' ~ Received focus event: hasFocus=%s, inTouchMode=%s.", getInputChannelName().c_str(), toString(focusEvent->getHasFocus()), toString(focusEvent->getInTouchMode()));
                }
                env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.onFocusEvent, jboolean(focusEvent->getHasFocus()), jboolean(focusEvent->getInTouchMode()));
                finishInputEvent(seq, true /* handled */);
                continue;
            }

            default:
                assert(false); // InputConsumer should prevent this from ever happening
                inputEventObj = nullptr;
            }

            // 若inputEventObj不为空,则通过CallVoidMethod方法,
// 调用上层的gInputEventReceiverClassInfo.dispatchInputEvent方法,
// 来将输入事件传递到java层。
            if (inputEventObj) {
                ...
                env->CallVoidMethod(receiverObj.get(),
                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
                if (env->ExceptionCheck()) {
                    ALOGE("Exception dispatching input event.");
                    skipCallbacks = true;
                }
                env->DeleteLocalRef(inputEventObj);
            } else {
                ALOGW("channel '%s' ~ Failed to obtain event object.",
                        getInputChannelName().c_str());
                skipCallbacks = true;
            }
        }

        if (skipCallbacks) {
            mInputConsumer.sendFinishedSignal(seq, false);
        }
    }
}

这里我们只分析mInputConsumer.consume方法,看App是如何读取到输入事件数据的;
其他流程如android_view_KeyEvent_fromNative和dispatchInputEvent,会在其他章节会进行分析;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/libs/input/InputTransport.cpp
status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consumeBatches,
                                nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
    if (DEBUG_TRANSPORT_ACTIONS) {
        ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64,
              mChannel->getName().c_str(), toString(consumeBatches), frameTime);
    }

    *outSeq = 0;
    *outEvent = nullptr;

    // Fetch the next input message.
    // Loop until an event can be returned or no additional events are received.
    while (!*outEvent) {
        if (mMsgDeferred) {
            // mMsg contains a valid input message from the previous call to consume
            // that has not yet been processed.
            mMsgDeferred = false;
        } else {
            // system_server进程会通过对端InputChannel的sendMessage方法发送数据;
// 这里app进程中的InputChannel,通过receiveMessage方法读取输入事件;
            // Receive a fresh message.
            status_t result = mChannel->receiveMessage(&mMsg);
            if (result) {
                // Consume the next batched event unless batches are being held for later.
                if (consumeBatches || result != WOULD_BLOCK) {
                    // 调用consumeBatch方法,将
                    result = consumeBatch(factory, frameTime, outSeq, outEvent);
                    if (*outEvent) {
                        if (DEBUG_TRANSPORT_ACTIONS) {
                            ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u",
                                  mChannel->getName().c_str(), *outSeq);
                        }
                        break;
                    }
                }
                return result;
            }
        }

        // 判断输入事件类型,将InputMessage数据转换为keyEvent等数据类型;
        switch (mMsg.header.type) {
            case InputMessage::Type::KEY: {
                KeyEvent* keyEvent = factory->createKeyEvent();
                if (!keyEvent) return NO_MEMORY;
                // 将mMsg数据,转换为KeyEvent数据,并存入outEvent;
                initializeKeyEvent(keyEvent, &mMsg);
                *outSeq = mMsg.body.key.seq;
                *outEvent = keyEvent;
                if (DEBUG_TRANSPORT_ACTIONS) {
                    ALOGD("channel '%s' consumer ~ consumed key event, seq=%u",
                          mChannel->getName().c_str(), *outSeq);
                }
            break;
            }

            case InputMessage::Type::MOTION: {
                .........
                break;
            }

            case InputMessage::Type::FINISHED: {
                LOG_ALWAYS_FATAL("Consumed a FINISHED message, which should never be seen by "
                                 "InputConsumer!");
                break;
            }

            case InputMessage::Type::FOCUS: {
                FocusEvent* focusEvent = factory->createFocusEvent();
                if (!focusEvent) return NO_MEMORY;

                initializeFocusEvent(focusEvent, &mMsg);
                *outSeq = mMsg.body.focus.seq;
                *outEvent = focusEvent;
                break;
            }
        }
    }
    return OK;
}

InputChannel读取数据:

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/libs/input/InputTransport.cpp
status_t InputChannel::receiveMessage(InputMessage* msg) {
    ssize_t nRead;
do {
    // 从socket的mFd共享内存中读取数据,应该是阻塞在此处;
        nRead = ::recv(mFd.get(), msg, sizeof(InputMessage), MSG_DONTWAIT);
    } while (nRead == -1 && errno == EINTR);

    if (nRead < 0) {
        int error = errno;
#if DEBUG_CHANNEL_MESSAGES
        ALOGD("channel '%s' ~ receive message failed, errno=%d", mName.c_str(), errno);
#endif
        if (error == EAGAIN || error == EWOULDBLOCK) {
            return WOULD_BLOCK;
        }
        if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) {
            return DEAD_OBJECT;
        }
        return -error;
    }

    if (nRead == 0) { // check for EOF
#if DEBUG_CHANNEL_MESSAGES
        ALOGD("channel '%s' ~ receive message failed because peer was closed", mName.c_str());
#endif
        return DEAD_OBJECT;
    }

    if (!msg->isValid(nRead)) {
#if DEBUG_CHANNEL_MESSAGES
        ALOGD("channel '%s' ~ received invalid message", mName.c_str());
#endif
        return BAD_VALUE;
    }

#if DEBUG_CHANNEL_MESSAGES
    ALOGD("channel '%s' ~ received message of type %d", mName.c_str(), msg->header.type);
#endif
    return OK;
}

总结下,此流程从Activity的onResume声明周期开始,在system_server进程中创建InputChannel对,在App进程中初始化WindowInputEventReceiver,然后尝试从InputChannel-mFd中读取数据,最终会将输入数据抛到View层进行处理;
至此,我们看到了App端接收InputChannel数据的具体流程; 输入数据的类型转换和传递流程,会在4.5章节进行详细介绍;

4.3 IMS读取和传递Input事件流程

4.3.1 流程介绍

这个流程,介绍了InputReader线程,从EventHub读取输入事件,并将事件通过InputDispatcher传递给InputChannel的流程;
事件传递给InputChannel后,存在于App进程中的对端InputChannel就可以读取到输入事件.

4.3.2 相关模块图示

4.3.2.1 模块架构图

在这里插入图片描述

4.3.2.2 dev/input驱动文件位置

在这里插入图片描述

####4.3.2.3 Idc/kl/kcm文件位置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.3.3 类图

以下类图可以从InputReader出发,按照输入事件读取和传递流程来查看相关类的依赖关联关系。
在这里插入图片描述

4.3.4 时序图

4.3.4.1 EventHub扫描Device数据流程在这里插入图片描述
4.3.4.2 InputReader读取和传输数据流程

在这里插入图片描述

4.3.4.3 InputDispatcher传递事件流程

在这里插入图片描述

4.3.5 代码解读

此章节,从InputReader从驱动文件读取输入数据开始分析,直到按键事件数据传入某个Window对应的InputChannel中为止,是这个章节的完成流程;

4.3.5.1 InputReader读取数据流程

先来回顾下,PMS的nativeInit方法创建了InputReader和InputDispatcher对象,nativeStart方法启动了两个相关线程,来循环调用loopOnce和diapatchOnce方法;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
                                           const sp<InputListenerInterface>& listener) {
    return new InputReader(std::make_unique<EventHub>(), policy, listener);
}


/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/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),
        mGeneration(1),
        mNextInputDeviceId(END_RESERVED_ID),
        mDisableVirtualKeysTimeout(LLONG_MIN),
        mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    // mQueuedListener 持有InputClassifier的对象listener,listener持有InputDispatcher的对象;
    mQueuedListener = new QueuedInputListener(listener);

    { // acquire lock
        AutoMutex _l(mLock);

        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    } // release lock
}
InputReader.h里的关键数据:
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/include/InputReader.h
    // The event queue.
    static const int EVENT_BUFFER_SIZE = 256;
    RawEvent mEventBuffer[EVENT_BUFFER_SIZE];

    // An input device can represent a collection of EventHub devices. This map provides a way
    // to lookup the input device instance from the EventHub device id.
    std::unordered_map<int32_t /*eventHubId*/, std::shared_ptr<InputDevice>> mDevices;

循环调用loopOnce方法,开始读取输入设备和输入事件;猜测跟mEventHub有关;
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/InputReader.cpp
void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    std::vector<InputDeviceInfo> inputDevices;
    ...
    // 从EventHub读取事件到mEventBuffer数组中,返回值为count数量;
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

    { // acquire lock
        AutoMutex _l(mLock);
        mReaderIsAliveCondition.broadcast();

        if (count) {
            // 若读取到了输入事件,则处理mEventBuffer中的输入事件;
            processEventsLocked(mEventBuffer, count); 
        }

        if (mNextTimeout != LLONG_MAX) {
            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            // 当前时间大于超时时间,处理超时问题;
            if (now >= mNextTimeout) {
                ...
                mNextTimeout = LLONG_MAX;
                timeoutExpiredLocked(now); // 处理超时;
            }
        }

        // mGeneration在mEventHub->getEvents或processEventsLocked时发生了变化,说明inputDevicesChanged,需要更新inputDevices列表;
        if (oldGeneration != mGeneration) {
            inputDevicesChanged = true;
            getInputDevicesLocked(inputDevices);
        }
    } // release lock

    // 通知java层IMS端Input设备变化了,如游戏可能在监听输入设备(游戏手柄、鼠标键盘等)的连接、断开等行为
    // Send out a message that the describes the changed input devices.
    if (inputDevicesChanged) {
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }

    // Flush queued events out to the listener.
    // This must happen outside of the lock because the listener could potentially call
    // back into the InputReader's methods, such as getScanCodeState, or become blocked
    // on another thread similarly waiting to acquire the InputReader lock thereby
    // resulting in a deadlock.  This situation is actually quite plausible because the
    // listener is actually the input dispatcher, which calls into the window manager,
    // which occasionally calls into the input reader.
    mQueuedListener->flush(); // 通知listener输入事件到来?不清楚干啥用的,待会儿看下。
}

此处的关键方法调用; 1,size_t count = mEventHub->getEvents(timeoutMillis,
mEventBuffer, EVENT_BUFFER_SIZE); 2,processEventsLocked(mEventBuffer,
count); 3,mPolicy->notifyInputDevicesChanged(inputDevices);
4,mQueuedListener->flush();

来看下mEventHub->getEvents这个关键方法:

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/EventHub.cpp
// 构造方法中,数据初始化状态:
      : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
        mNextDeviceId(1),
        mControllerNumbers(),
        mOpeningDevices(nullptr),
        mClosingDevices(nullptr),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false),
        mNeedToScanDevices(true), // 注意赋值
        mPendingEventCount(0),
        mPendingEventIndex(0),
        mPendingINotify(false)
// 构造方法 end.

getEvents方法会从驱动节点读取驱动数据,并转换为输入事件或输入设备的插入等相关事件,如InputDevice就绪、注销、输入事件等信息;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/EventHub.cpp
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    ALOG_ASSERT(bufferSize >= 1);
    AutoMutex _l(mLock);
    // 创建input_event数组,bufferSize是EVENT_BUFFER_SIZE=256;
    struct input_event readBuffer[bufferSize];

    RawEvent* event = buffer; // 要存储的数据容器
    size_t capacity = bufferSize; // 最大数量
    bool awoken = false;
    // 无限循环,直到遇到return或break;
    for (;;) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        // mNeedToReopenDevices初始化为false,没有要关闭的设备;
        // Reopen input devices if needed.
        if (mNeedToReopenDevices) {
            mNeedToReopenDevices = false;
            ALOGI("Reopening all input devices due to a configuration change.");
            closeAllDevicesLocked();
            mNeedToScanDevices = true;
            break; // return to the caller before we actually rescan
        }

        // 初始化为null,没有要关闭的设备;
        // Report any devices that had last been added/removed.
        while (mClosingDevices) {
            Device* device = mClosingDevices;
            ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
            mClosingDevices = device->next;
            event->when = now;
            event->deviceId = (device->id == mBuiltInKeyboardId)
                    ? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
                    : device->id;
            event->type = DEVICE_REMOVED;
            event += 1;
            delete device;
            mNeedToSendFinishedDeviceScan = true;
            if (--capacity == 0) {
                break;
            }
        }

        // 初始化为true,第一次loopOnce要扫描设备,确认有哪些输入设备,确认输入设备有什么样的特性。
        if (mNeedToScanDevices) {
            mNeedToScanDevices = false;
            // 关键方法!扫描/dev/input/下的驱动文件节点,并添加到EventHub的mDevices中;
            scanDevicesLocked();
            mNeedToSendFinishedDeviceScan = true;
        }

        // 上面的scanDevicesLocked方法,会给mOpeningDevices赋值;
        // 开机过程中扫描的设备,或新加入的输入设备,都会添加到mOpeningDevices里。
        while (mOpeningDevices != nullptr) {
            Device* device = mOpeningDevices;
            ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
            // mOpeningDevices是链表数据类型
            mOpeningDevices = device->next; 
            event->when = now;
            event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
            event->type = DEVICE_ADDED;
            event += 1;// event指针数组后移一位
            mNeedToSendFinishedDeviceScan = true;
            if (--capacity == 0) { // capacity -1,即事件容量-1;
                break;
            }
        }

        // 扫描输入设备结束,开机扫描时为true;
        if (mNeedToSendFinishedDeviceScan) {
            mNeedToSendFinishedDeviceScan = false;
            event->when = now;
            event->type = FINISHED_DEVICE_SCAN;
            event += 1;
            // 如果getEvents读取到的事件数量超过了256,则退出外面的for(;;)循环,上报当前的事件;
            if (--capacity == 0) {
                break;
            }
        }

        // 首次loop,mPendingEventIndex和mPendingEventCount都是0,不进入此循环;
        // 等读取到输入事件后,上面的for(;;)会重新循环一次,此时mPendingEventCount就是大于0了,mPendingEventItems也从驱动读取到了各种事件;
        // Grab the next input event.
        bool deviceChanged = false;
        while (mPendingEventIndex < mPendingEventCount) {
            // 驱动数据原始数据类型:epoll_event!!!
            const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
            if (eventItem.data.fd == mINotifyFd) {
                if (eventItem.events & EPOLLIN) {
                    mPendingINotify = true;
                } else {
                    ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
                }
                continue;
            }

            if (eventItem.data.fd == mWakeReadPipeFd) {
                if (eventItem.events & EPOLLIN) {
                    ALOGV("awoken after wake()");
                    awoken = true;
                    char buffer[16];
                    ssize_t nRead;
                    do {
                        nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
                    } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
                } else {
                    ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
                          eventItem.events);
                }
                continue;
            }

            Device* device = getDeviceByFdLocked(eventItem.data.fd);
            if (!device) {
                ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.", eventItem.events,
                      eventItem.data.fd);
                ALOG_ASSERT(!DEBUG);
                continue;
            }
            // video类型,此处不进行分析;
            if (device->videoDevice && eventItem.data.fd == device->videoDevice->getFd()) {
                if (eventItem.events & EPOLLIN) {
                    size_t numFrames = device->videoDevice->readAndQueueFrames();
                    if (numFrames == 0) {
                        ALOGE("Received epoll event for video device %s, but could not read frame",
                              device->videoDevice->getName().c_str());
                    }
                } else if (eventItem.events & EPOLLHUP) {
                    // TODO(b/121395353) - consider adding EPOLLRDHUP
                    ALOGI("Removing video device %s due to epoll hang-up event.",
                          device->videoDevice->getName().c_str());
                    unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
                    device->videoDevice = nullptr;
                } else {
                    ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
                          device->videoDevice->getName().c_str());
                    ALOG_ASSERT(!DEBUG);
                }
                continue;
            }

            // 确定是Input输入设备,可能输入物理按键、触屏、游戏手柄、键盘等等类型的输入事件;
            // This must be an input event
            if (eventItem.events & EPOLLIN) {
                // 从此设备读取输入事件;驱动数据原始数据类型:input_event
                int32_t readSize =
                        read(device->fd, readBuffer, sizeof(struct input_event) * capacity);
                if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
                    // Device was removed before INotify noticed.
                    ALOGW("could not get event, removed? (fd: %d size: %" PRId32
                          " bufferSize: %zu capacity: %zu errno: %d)\n",
                          device->fd, readSize, bufferSize, capacity, errno);
                    deviceChanged = true;
                    closeDeviceLocked(device);
                } else if (readSize < 0) {
                    if (errno != EAGAIN && errno != EINTR) {
                        ALOGW("could not get event (errno=%d)", errno);
                    }
                } else if ((readSize % sizeof(struct input_event)) != 0) {
                    // 读取数据量错误;
                    ALOGE("could not get event (wrong size: %d)", readSize);
                } 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++) {
                        // 存入readBuffer中,i从0开始,说明一次for循环只能处理一个输入设备的事件。;
                        struct input_event& iev = readBuffer[i];
                        // 将读取到的iev中的数据,读取到event中;
                        event->when = processEventTimestamp(iev);
                        event->deviceId = deviceId;
                        event->type = iev.type;
                        event->code = iev.code;
                        event->value = iev.value;
                        event += 1;//event指针++,后移;
                        capacity -= 1;// event中可用容量-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;
                    }
                }
            } else if (eventItem.events & EPOLLHUP) {
                ALOGI("Removing device %s due to epoll hang-up event.",
                      device->identifier.name.c_str());
                deviceChanged = true;
                closeDeviceLocked(device);
            } else {
                ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
                      device->identifier.name.c_str());
            }
        }

        // readNotify() will modify the list of devices so this must be done after
        // processing all other events to ensure that we read all remaining events
        // before closing the devices.
        if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
            mPendingINotify = false;
            readNotifyLocked();
            deviceChanged = true;
        }

        // Report added or removed devices immediately.
        if (deviceChanged) {
            continue;
        }

        // Return now if we have collected any events or if we were explicitly awoken.
        if (event != buffer || awoken) {
            break;
        }

        // Poll for events.
        // When a device driver has pending (unread) events, it acquires
        // a kernel wake lock.  Once the last pending event has been read, the device
        // driver will release the kernel wake lock, but the epoll will hold the wakelock,
        // since we are using EPOLLWAKEUP. The wakelock is released by the epoll when epoll_wait
        // is called again for the same fd that produced the event.
        // Thus the system can only sleep if there are no events pending or
        // currently being processed.
        //
        // The timeout is advisory only.  If the device is asleep, it will not wake just to
        // service the timeout.
        mPendingEventIndex = 0; // index归零;

        mLock.unlock(); // release lock before poll

        // 等待输入事件,将数据读取到mPendingEventItems中, pollResult是读取到的事件数量;
        int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);

        mLock.lock(); // reacquire lock after poll

        // 未读取到数据,重新for循环
        if (pollResult == 0) {
            // Timed out.
            mPendingEventCount = 0;
            break;
        }

        if (pollResult < 0) {
            // An error occurred.
            ......
        } else {
            // 读取到了数据,赋值读取到的数量到mPendingEventCount,读取到的数据在mPendingEventItems中;
            // Some events occurred.
            mPendingEventCount = size_t(pollResult);
        }
    }

    // 指针数量相减,得到需要处理的事件的数量;
    // All done, return the number of events we read.
    return event - buffer;
}

接着上面的关键方法,插入这里发现的关键方法; 1,size_t count =
mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
1.1,扫描设备:scanDevicesLocked()
1.2,读取到输入事件:struct input_event& iev = readBuffer[i]; 2,processEventsLocked(mEventBuffer, count);
3,mPolicy->notifyInputDevicesChanged(inputDevices);
4,mQueuedListener->flush();

来分析1.1 scanDevicesLocked;
此处会从/dev/input/中读取设备驱动文件,并从驱动文件中读取部分信息,如version号,是否支持vendor/product,支持的按键scancode和设备类型等数据;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/EventHub.cpp
void EventHub::scanDevicesLocked() {
    // 扫描DEVICE_PATH
    // static const char* DEVICE_PATH = "/dev/input";
    status_t result = scanDirLocked(DEVICE_PATH);
    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.indexOfKey(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) < 0) {
        createVirtualKeyboardLocked();
    }
}
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/EventHub.cpp
status_t EventHub::scanDirLocked(const char* dirname) {
    char devname[PATH_MAX];
    char* filename;
    DIR* dir;
    struct dirent* de;
    dir = opendir(dirname);// 打开文件夹
    if (dir == nullptr) return -1;
    strcpy(devname, dirname); // 复制dirname到devname
    filename = devname + strlen(devname); // 赋值为/dev/input10,为什么?
    *filename++ = '/'; /dev/input10/???
    // 从dir中读取到文件;
    while ((de = readdir(dir))) {
        if (de->d_name[0] == '.' &&
            (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
            continue;
        // 复制文件名称
        strcpy(filename, de->d_name);
        // 打开文件,每个文件对应了一个输入设备;
        openDeviceLocked(devname);
    }
    closedir(dir);
    return 0;
}

打开文件,读取各种信息,并保存到输入设备列表,方便后续从这些文件节点读取输入事件;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/EventHub.cpp
status_t EventHub::openDeviceLocked(const char* devicePath) {
    char buffer[80];

    ALOGV("Opening device: %s", devicePath);

    int fd = open(devicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK); // 打开文件;
    if (fd < 0) {
        ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
        return -1;
    }

    InputDeviceIdentifier identifier;

    // 从驱动读取设备名称。
    // Get device name.
    if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
        ALOGE("Could not get device name for %s: %s", devicePath, strerror(errno));
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.name = buffer;
    }

    // 是否是需要排除的设备,好像在fw的config里定义,从InputManagerService读取;
    // Check to see if the device is on our excluded list
    for (size_t i = 0; i < mExcludedDevices.size(); i++) {
        const std::string& item = mExcludedDevices[i];
        if (identifier.name == item) {
            ALOGI("ignoring event id %s driver %s\n", devicePath, item.c_str());
            close(fd);
            return -1;
        }
    }

    // 驱动版本号;
    // Get device driver version.
    int driverVersion;
    if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
        ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
        close(fd);
        return -1;
    }

    // input_id信息,如bustype, product, vendor,version;
    // Get device identifier.
    struct input_id inputId;
    if (ioctl(fd, EVIOCGID, &inputId)) {
        ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
        close(fd);
        return -1;
    }
    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;
    }

    // 读取uniqueId信息;
    // 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;
    }

    // 用上面读取的信息拼凑成Descriptor信息字符串;
    // Fill in the descriptor.
    assignDescriptorLocked(identifier);

    // Allocate device.  (The device object takes ownership of the fd at this point.)
    int32_t deviceId = mNextDeviceId++;
// 注意此处!EventHub里的是Device对象,
// InputReader里还有一个InputDevice,注意不要弄混淆;
    Device* device = new Device(fd, deviceId, devicePath, identifier);
     ......
    // 重要!从磁盘配置文件中读取scanCode和KeyCode的对应配置信息;
    // 配置文件为×××.kl和×××.kcm,默认配置在frameworks/base/data/keyboards下;
    // Load the configuration file for the device.
    loadConfigurationLocked(device);

    /*
     *从驱动读取此输入设备支持的输入事件类型;
     *注意此处在.h文件里的声明,是int[]数组类型;
     *uint8_t keyBitmask[(KEY_MAX + 1) / 8];
     *uint8_t absBitmask[(ABS_MAX + 1) / 8];
     *uint8_t relBitmask[(REL_MAX + 1) / 8];
     *uint8_t swBitmask[(SW_MAX + 1) / 8];
     *uint8_t ledBitmask[(LED_MAX + 1) / 8];
     *uint8_t ffBitmask[(FF_MAX + 1) / 8];
     *uint8_t propBitmask[(INPUT_PROP_MAX + 1) / 8];
    */
    // Figure out the kinds of events the device reports.
    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
    ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
    ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
    ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
    ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask);
    ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);

    // 下面的逻辑,是根据上面读取到的设备支持的类型,给device-classes打上分类标签,方便fw层来区分不同类型的输入设备,如游戏手柄支持abxy按键,鼠标是不是支持relBitmast相关输入?
    // See if this is a keyboard.  Ignore everything in the button range except for
    // joystick and gamepad buttons which are handled like keyboards for the most part.
    bool haveKeyboardKeys =
            containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC)) ||
            containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_WHEEL),
                                sizeof_bit_array(KEY_MAX + 1));
    bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC), sizeof_bit_array(BTN_MOUSE)) || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK), sizeof_bit_array(BTN_DIGI));
    if (haveKeyboardKeys || haveGamepadButtons) {
        device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
    }

    // See if this is a cursor device such as a trackball or mouse.
    if (test_bit(BTN_MOUSE, device->keyBitmask) && test_bit(REL_X, device->relBitmask) &&
        test_bit(REL_Y, device->relBitmask)) {
        device->classes |= INPUT_DEVICE_CLASS_CURSOR;
    }

    // See if this is a rotary encoder type device.
    String8 deviceType = String8();
    if (device->configuration &&
        device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
        if (!deviceType.compare(String8("rotaryEncoder"))) {
            device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
        }
    }

    // See if this is a touch pad.
    // Is this a new modern multi-touch driver?
    if (test_bit(ABS_MT_POSITION_X, device->absBitmask) &&
        test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
        // Some joysticks such as the PS3 controller report axes that conflict
        // with the ABS_MT range.  Try to confirm that the device really is
        // a touch screen.
        if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) {
            device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
        }
        // Is this an old style single-touch driver?
    } else if (test_bit(BTN_TOUCH, device->keyBitmask) && test_bit(ABS_X, device->absBitmask) &&
               test_bit(ABS_Y, device->absBitmask)) {
        device->classes |= INPUT_DEVICE_CLASS_TOUCH;
        // Is this a BT stylus?
    } else if ((test_bit(ABS_PRESSURE, device->absBitmask) ||
                test_bit(BTN_TOUCH, device->keyBitmask)) &&
               !test_bit(ABS_X, device->absBitmask) && !test_bit(ABS_Y, device->absBitmask)) {
        device->classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
        // Keyboard will try to claim some of the buttons but we really want to reserve those so we
        // can fuse it with the touch screen data, so just take them back. Note this means an
        // external stylus cannot also be a keyboard device.
        device->classes &= ~INPUT_DEVICE_CLASS_KEYBOARD;
    }

    // See if this device is a joystick.
    // Assumes that joysticks always have gamepad buttons in order to distinguish them
    // from other devices such as accelerometers that also have absolute axes.
    if (haveGamepadButtons) {
        uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
        for (int i = 0; i <= ABS_MAX; i++) {
            if (test_bit(i, device->absBitmask) &&
                (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
                device->classes = assumedClasses;
                break;
            }
        }
    }

    // Check whether this device has switches.
    for (int i = 0; i <= SW_MAX; i++) {
        if (test_bit(i, device->swBitmask)) {
            device->classes |= INPUT_DEVICE_CLASS_SWITCH;
            break;
        }
    }

    // Check whether this device supports the vibrator.
    if (test_bit(FF_RUMBLE, device->ffBitmask)) {
        device->classes |= INPUT_DEVICE_CLASS_VIBRATOR;
    }

    // Configure virtual keys.
    if ((device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
        // Load the virtual keys for the touch screen, if any.
        // We do this now so that we can make sure to load the keymap if necessary.
        bool success = loadVirtualKeyMapLocked(device);
        if (success) {
            device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
        }
    }

    // 注意此处,是加载按键信息到内存中,用到了刚才loadConfigurationLocked里的.kl等配置文件;此处比较重要,待会儿分析
    // Load the key map.
    // We need to do this for joysticks too because the key layout may specify axes.
    status_t keyMapStatus = NAME_NOT_FOUND;
    if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
        // Load the keymap for the device.
        keyMapStatus = loadKeyMapLocked(device);// 重要!!!
    }

    // Configure the keyboard, gamepad or virtual keyboard.
    if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
        // Register the keyboard as a built-in keyboard if it is eligible.
        if (!keyMapStatus && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD &&
            isEligibleBuiltInKeyboard(device->identifier, device->configuration, &device->keyMap)) {
            mBuiltInKeyboardId = device->id;
        }

        // 'Q' key support = cheap test of whether this is an alpha-capable kbd
        if (hasKeycodeLocked(device, AKEYCODE_Q)) {
            device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
        }

        // See if this device has a DPAD.
        if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
            hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
            hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
            hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
            hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
            device->classes |= INPUT_DEVICE_CLASS_DPAD;
        }

        // See if this device has a gamepad.
        for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES) / sizeof(GAMEPAD_KEYCODES[0]); i++) {
            if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
                device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
                break;
            }
        }
    }

    // If the device isn't recognized as something we handle, don't monitor it.
    if (device->classes == 0) {
        ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath,
              device->identifier.name.c_str());
        delete device;
        return -1;
    }

    // Determine whether the device has a mic.
    if (deviceHasMicLocked(device)) {
        device->classes |= INPUT_DEVICE_CLASS_MIC;
    }

    // Determine whether the device is external or internal.
    if (isExternalDeviceLocked(device)) {
        device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
    }

    if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD) &&
        device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
        device->controllerNumber = getNextControllerNumberLocked(device);
        setLedForControllerLocked(device);
    }

    // Find a matching video device by comparing device names
    // This should be done before registerDeviceForEpollLocked, so that both fds are added to epoll
    for (std::unique_ptr<TouchVideoDevice>& videoDevice : mUnattachedVideoDevices) {
        if (device->identifier.name == videoDevice->getName()) {
            device->videoDevice = std::move(videoDevice);
            break;
        }
    }
    mUnattachedVideoDevices
            .erase(std::remove_if(mUnattachedVideoDevices.begin(), mUnattachedVideoDevices.end(), [](const std::unique_ptr<TouchVideoDevice>& videoDevice) {
                                      return videoDevice == nullptr;
                                  }),
                   mUnattachedVideoDevices.end());

    if (registerDeviceForEpollLocked(device) != OK) {
        delete device;
        return -1;
    }

    configureFd(device);

    ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
          "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
          deviceId, fd, devicePath, device->identifier.name.c_str(), device->classes,
          device->configurationFile.c_str(), device->keyMap.keyLayoutFile.c_str(),
          device->keyMap.keyCharacterMapFile.c_str(), toString(mBuiltInKeyboardId == deviceId));
    // 重要,添加device到集合中,需要分析。
    addDeviceLocked(device);
    return OK;
}

我们看到1.1-openDeviceLocked方法中,读取了输入设备驱动节点的一些版本号、name等信息,以及支持的输入类型等信息;
来分析openDeviceLocked用到的以下关键方法:
1.1.1,EventHub-openDeviceLocked-loadConfigurationLocked(device);
1.1.2,EventHub-openDeviceLocked-keyMapStatus = loadKeyMapLocked(device);
1.1.3,EventHub-openDeviceLocked-addDeviceLocked(device);

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/EventHub.cpp
void EventHub::loadConfigurationLocked(Device* device) {
    /*查找配置文件路径字符串,返回值赋值给了此device的configurationFile;
     *enum InputDeviceConfigurationFileType {
     *    INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION = 0,     /* .idc file */
     *    INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT = 1,        /* .kl file */
     *    INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP = 2, /* .kcm file */
     *};
     */
    device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
            device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
    if (device->configurationFile.empty()) {
        ALOGD("No input device configuration file found for device '%s'.",
              device->identifier.name.c_str());
    } else {
        // 配置文件不为空,加载配置信息到此device的configuration中;
        status_t status = PropertyMap::load(String8(device->configurationFile.c_str()),
                                            &device->configuration);
        if (status) {
            ALOGE("Error loading input device configuration file for device '%s'.  "
                  "Using default configuration.",
                  device->identifier.name.c_str());
        }
    }
}

查找此设备对应的配置文件

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/EventHub.cpp
std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(
        const InputDeviceIdentifier& deviceIdentifier,
        InputDeviceConfigurationFileType type) {
    // 若驱动层vendor和product信息不为0
    if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
        // 版本号不为0
        if (deviceIdentifier.version != 0) {
            // 拼凑字符串为配置文件路径,并返回string,%04x代表按照16进制转化,若不够4位,则前面补0;
            // Vendor_#VENDOR#_Product_#PRODUCT#_Version_#VERSION#
            // Try vendor product version.
            std::string versionPath = getInputDeviceConfigurationFilePathByName(
                    StringPrintf("Vendor_%04x_Product_%04x_Version_%04x",
                            deviceIdentifier.vendor, deviceIdentifier.product,
                            deviceIdentifier.version),
                    type);
            if (!versionPath.empty()) {
                return versionPath;
            }
        }

        // Version号==0,则不用Version来拼凑配置文件;
        // Try vendor product.
        std::string productPath = getInputDeviceConfigurationFilePathByName(
                StringPrintf("Vendor_%04x_Product_%04x",
                        deviceIdentifier.vendor, deviceIdentifier.product),
                type);
        if (!productPath.empty()) {
            return productPath;
        }
    }

    // 用deviceName拼凑字符串,name若包含非法字符,则用_替换;
    // Try device name.
    return getInputDeviceConfigurationFilePathByName(deviceIdentifier.getCanonicalName(), type);
}

std::string getInputDeviceConfigurationFilePathByName(
        const std::string& name, InputDeviceConfigurationFileType type) {
    // Search system repository.
    std::string path;

    // 三个路径,最后一个ANDROID_ROOT是/system;
    // Treblized input device config files will be located /odm/usr or /vendor/usr.
    const char *rootsForPartition[] {"/odm", "/vendor", getenv("ANDROID_ROOT")};
    for (size_t i = 0; i < size(rootsForPartition); i++) {
        if (rootsForPartition[i] == nullptr) {
            continue;
        }
        path = rootsForPartition[i];
        // 拼凑路径为/***/usr/
        path += "/usr/";
        // 拼凑路径为/odm Or vendor/usr/idc/#NAME#.idc
        appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
        ALOGD("Probing for system provided input device configuration file: path='%s'",
              path.c_str());
#endif
        if (!access(path.c_str(), R_OK)) {
#if DEBUG_PROBE
            ALOGD("Found");
#endif
            // 若文件存在,则使用此配置文件,注意此处相当于存在一个优先级顺序,odm > vendor > #root#;
            return path;
        }
    }

    // 上面的路径里没有找到配置文件,从以下逻辑中查找;
    // Search user repository.
    // TODO Should only look here if not in safe mode.
    path = "";
    // androidData是/data目录
    char *androidData = getenv("ANDROID_DATA");
    if (androidData != nullptr) {
        path += androidData;
    }
    path += "/system/devices/";
    // 拼凑文件目录:/data/system/devices/#NAME#.idc
    appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
    ALOGD("Probing for system user input device configuration file: path='%s'", path.c_str());
#endif
    if (!access(path.c_str(), R_OK)) {
#if DEBUG_PROBE
        ALOGD("Found");
#endif
        return path;
    }

    // Not found. // 若不存在,返回空"";
#if DEBUG_PROBE
    ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
            name.c_str(), type);
#endif
    return "";
}

来看下配置文件的样式,从配置文件中读取到了哪些信息:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/data/keyboards/qwerty.idc:
touch.deviceType = touchScreen
touch.orientationAware = 1
// 注意layout和characterMap配置,分别对应了qwerty.kl和qwerty.kcm
keyboard.layout = qwerty
keyboard.characterMap = qwerty
keyboard.orientationAware = 1
keyboard.builtIn = 1

cursor.mode = navigation
cursor.orientationAware = 1

以下load方法就是将以上数据读取到device的configuration键值对中,此处不再分析;
PropertyMap::load(String8(device->configurationFile.c_str()), &device->configuration);

先来看下qwerty.kl中的一部分配置,每一行代表了一个按键属性+scanCode+按键字符串,按键字符串对应的键值,在一个.h文件中定义,后续会提到:

/home/chen/disk2/project/aosp/r_aosp/frameworks/base/data/keyboards/qwerty.kl
key 217   SEARCH
key 228   POUND
key 227   STAR
key 231   CALL
key 61    CALL
key 232   DPAD_CENTER
key 108   DPAD_DOWN
key 103   DPAD_UP
key 102   HOME
key 105   DPAD_LEFT
key 106   DPAD_RIGHT
key 115   VOLUME_UP
key 114   VOLUME_DOWN
key 116   POWER
key 212   CAMERA

以下配置文件更具备代表性,包含了key,usage,axis三种配置类型;
/home/chen/disk2/project/aosp/r_aosp/frameworks/base/data/keyboards/Generic.kl
key 522   STAR
key 523   POUND
key 580   APP_SWITCH
key 582   VOICE_ASSIST
// Linux KEY_ASSISTANT
key 583   ASSIST

//Keys defined by HID usages
key usage 0x0c006F BRIGHTNESS_UP
key usage 0x0c0070 BRIGHTNESS_DOWN

//Joystick and game controller axes.
//Axes that are not mapped will be assigned generic axis numbers by the input subsystem.
axis 0x00 X
axis 0x01 Y
axis 0x02 Z
axis 0x03 RX
这里好像定义了一些组合按键的信息:
key A {
    label:                              'A'
    number:                             '2'
    base:                               'a'
    shift, capslock:                    'A'
    alt:                                '#'
    shift+alt, capslock+alt:            none
}

key B {
    label:                              'B'
    number:                             '2'
    base:                               'b'
    shift, capslock:                    'B'
    alt:                                '<'
    shift+alt, capslock+alt:            none
}

loadConfigurationLocked其实是查找并读取.idc配置文件信息,并将数据加载到device的configuration中;
接下来分析下后续的流程,猜测此处loadKeyMapLocked是加载刚才读到的.kl和kcm信息到device中,上报上来scancode后,就可以转换为对应的keyCode:

1.1.2,EventHub-openDeviceLocked-keyMapStatus = loadKeyMapLocked(device);

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/EventHub.cpp
status_t EventHub::loadKeyMapLocked(Device* device) {
    // 通过device的keyMap对象,加载device的configuration,到device的identifier中;
    return device->keyMap.load(device->identifier, device->configuration);
}

// 注意此处拿的是device的keyMap对象;
// 上面的idc文件里配置了keyboard.layout = qwerty;keyboard.characterMap = qwerty
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/libs/input/Keyboard.cpp
status_t KeyMap::load(const InputDeviceIdentifier& deviceIdentifier,
        const PropertyMap* deviceConfiguration) {
    // 若device有自己的配置文件
    // Use the configured key layout if available.
    if (deviceConfiguration) {
        String8 keyLayoutName;
        // 若配置了keyboard.layout属性
        if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
                keyLayoutName)) {
            // 加载.kl文件,若不存在则返回NAME_NOT_FOUND
            status_t status = loadKeyLayout(deviceIdentifier, keyLayoutName.c_str());
            if (status == NAME_NOT_FOUND) {
                ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
                        "it was not found.",
                        deviceIdentifier.name.c_str(), keyLayoutName.string());
            }
        }

        // 加载keyboard.characterMap文件
        String8 keyCharacterMapName;
        if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),
                keyCharacterMapName)) {
            status_t status = loadKeyCharacterMap(deviceIdentifier, keyCharacterMapName.c_str());
            if (status == NAME_NOT_FOUND) {
                ALOGE("Configuration for keyboard device '%s' requested keyboard character "
                        "map '%s' but it was not found.",
                        deviceIdentifier.name.c_str(), keyCharacterMapName.string());
            }
        }

        if (isComplete()) {
            return OK;
        }
    }

    // Try searching by device identifier.
    if (probeKeyMap(deviceIdentifier, "")) {
        return OK;
    }

    // 上面没有自己的.idc文件,则使用通用的Generic.kl和Generic.kcm配置文件;
    // 此处读取并解析Generic.kl,加载到device中;
    // Fall back on the Generic key map.
    // TODO Apply some additional heuristics here to figure out what kind of
    //      generic key map to use (US English, etc.) for typical external keyboards.
    if (probeKeyMap(deviceIdentifier, "Generic")) {
        return OK;
    }

    ......
    return NAME_NOT_FOUND;
}

来看下probeKeyMap方法,在没有专用配置文件时,使用默认的Generic配置文件;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/libs/input/Keyboard.cpp
bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,
        const std::string& keyMapName) {
    // 若keyLayoutFile为空,则加载Generic.kl
    if (!haveKeyLayout()) {
        loadKeyLayout(deviceIdentifier, keyMapName);
    }
    // 若keyCharacterMapFile为空,则加载Generic.kcm
    if (!haveKeyCharacterMap()) {
        loadKeyCharacterMap(deviceIdentifier, keyMapName);
    }
    return isComplete();
}
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/libs/input/Keyboard.cpp
status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,
        const std::string& name) {
    // name不为空,则通过getInputDeviceConfigurationFilePathByName方法查找配置文件,并KeyLayoutMap::load;
    // 上面查找的是.idc文件,这次查找的是kl文件和kcm文件。
    // 在设备里应该是/system/usr/****/Generic.kl文件
    std::string path(getPath(deviceIdentifier, name,
            INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
    if (path.empty()) {
        return NAME_NOT_FOUND;
    }

    // 加载到keyLayoutMap中;
    status_t status = KeyLayoutMap::load(path, &keyLayoutMap);
    if (status) {
        return status;
    }

    keyLayoutFile = path;
    return OK;
}

keyLayoutMap是device-KeyMap中的一个sp keyLayoutMap指针;
需要分析以下方法:
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/libs/input/KeyLayoutMap.cpp-KeyLayoutMap::load(path, &keyLayoutMap);
先来看下KeyLayoutMap数据结构,就知道要从配置文件中读取什么数据了!

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/include/input/KeyLayoutMap.h	
class KeyLayoutMap : public RefBase {
public:
    static status_t load(const std::string& filename, sp<KeyLayoutMap>* outMap);

    status_t mapKey(int32_t scanCode, int32_t usageCode,
            int32_t* outKeyCode, uint32_t* outFlags) const;
    status_t findScanCodesForKey(int32_t keyCode, std::vector<int32_t>* outScanCodes) const;
    status_t findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const;
    status_t findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const;

    status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const;

protected:
    virtual ~KeyLayoutMap();

private:
    // key 数据结构
    struct Key {
        int32_t keyCode;
        uint32_t flags;
    };
    // led的数据结构
    struct Led {
        int32_t ledCode;
    };


    KeyedVector<int32_t, Key> mKeysByScanCode; // scancode 和key的匹配关系
    KeyedVector<int32_t, Key> mKeysByUsageCode; // usageCode和key的匹配关系
    KeyedVector<int32_t, AxisInfo> mAxes;
    KeyedVector<int32_t, Led> mLedsByScanCode; // scancode和led数据的匹配关系
    KeyedVector<int32_t, Led> mLedsByUsageCode;

    KeyLayoutMap();

    const Key* getKey(int32_t scanCode, int32_t usageCode) const;

    class Parser {
        KeyLayoutMap* mMap;
        Tokenizer* mTokenizer;

    public:
        Parser(KeyLayoutMap* map, Tokenizer* tokenizer);
        ~Parser();
        status_t parse();

    private:
        status_t parseKey();
        status_t parseAxis();
        status_t parseLed();
    };
};

} 

继续分析KKeyLayoutMap::load方法:

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/libs/input/Keyboard.cpp
status_t KeyLayoutMap::load(const std::string& filename, sp<KeyLayoutMap>* outMap) {
    outMap->clear();

    Tokenizer* tokenizer;
    status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer);
    if (status) {
        ALOGE("Error %d opening key layout map file %s.", status, filename.c_str());
    } else {
        sp<KeyLayoutMap> map = new KeyLayoutMap();
        if (!map.get()) {
            ALOGE("Error allocating key layout map.");
            status = NO_MEMORY;
        } else {
#if DEBUG_PARSER_PERFORMANCE
            nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
#endif
            // 将文件中的数据解析到map中
            Parser parser(map.get(), tokenizer);
            status = parser.parse();
#if DEBUG_PARSER_PERFORMANCE
            nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
            ALOGD("Parsed key layout map file '%s' %d lines in %0.3fms.",
                    tokenizer->getFilename().string(), tokenizer->getLineNumber(),
                    elapsedTime / 1000000.0);
#endif
            if (!status) {
                // outMap解应用,赋值为map;
                *outMap = map;
            }
        }
        delete tokenizer;
    }
    return status;
}

来看下parse方法:

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/libs/input/KeyLayoutMap.cpp
status_t KeyLayoutMap::Parser::parse() {
    while (!mTokenizer->isEof()) {
#if DEBUG_PARSER
        ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
                mTokenizer->peekRemainderOfLine().string());
#endif

        mTokenizer->skipDelimiters(WHITESPACE);

        if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
            String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
            if (keywordToken == "key") {
                mTokenizer->skipDelimiters(WHITESPACE);
                status_t status = parseKey(); // 解析key
                if (status) return status;
            } else if (keywordToken == "axis") {
                mTokenizer->skipDelimiters(WHITESPACE);
                status_t status = parseAxis();// 解析axis
                if (status) return status;
            } else if (keywordToken == "led") {
                mTokenizer->skipDelimiters(WHITESPACE);
                status_t status = parseLed();// 解析led事件
                if (status) return status;
            } else {
                ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),
                        keywordToken.string());
                return BAD_VALUE;
            }

            mTokenizer->skipDelimiters(WHITESPACE);
            if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
                ALOGE("%s: Expected end of line or trailing comment, got '%s'.",
                        mTokenizer->getLocation().string(),
                        mTokenizer->peekRemainderOfLine().string());
                return BAD_VALUE;
            }
        }

        mTokenizer->nextLine(); // 每次解析一行,每行代表一个配置信息;
    }
    return NO_ERROR;
}

解析key的方法:

status_t KeyLayoutMap::Parser::parseKey() {
    String8 codeToken = mTokenizer->nextToken(WHITESPACE); // scanCode,数据示例:key 583   ASSIST

    bool mapUsage = false;
    if (codeToken == "usage") {// 是否为usage
        mapUsage = true;
        mTokenizer->skipDelimiters(WHITESPACE);
        codeToken = mTokenizer->nextToken(WHITESPACE); // 若为usage,则scanCode需要再读一位,数据示例:key usage 0x0c006F BRIGHTNESS_UP
    }

    char* end;
    int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); // String转为int;
    if (*end) {
        ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
                mapUsage ? "usage" : "scan code", codeToken.string());
        return BAD_VALUE;
    }
    KeyedVector<int32_t, Key>& map = mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode; // 如果是usage,则用mKeysByUsageCode,否则用正常的mKeysByScanCode
    if (map.indexOfKey(code) >= 0) { // 已有此scanCode对应配置,则不需要再解析
        ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
                mapUsage ? "usage" : "scan code", codeToken.string());
        return BAD_VALUE;
    }

    mTokenizer->skipDelimiters(WHITESPACE);
    String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); // 获取keyCode对应字符串,如BRIGHTNESS_UP、VOLUME_DOWN、F11、A、B等样式
    int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); // 将keyCode字符串转换为对应的keyCode,需要分析下getKeyCodeByLabel方法;
    if (!keyCode) {
        ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
                keyCodeToken.string());
        return BAD_VALUE;
    }

    uint32_t flags = 0;
    for (;;) { // 获取flag定义,猜测可能是这样的数据配置:key 583   ASSIST FUNCTION,暂不分析,一般为null
        mTokenizer->skipDelimiters(WHITESPACE);
        if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') break;

        String8 flagToken = mTokenizer->nextToken(WHITESPACE);
        uint32_t flag = getKeyFlagByLabel(flagToken.string()); 

        if (!flag) {
            ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(),
                    flagToken.string());
            return BAD_VALUE;
        }
        if (flags & flag) {
            ALOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().string(),
                    flagToken.string());
            return BAD_VALUE;
        }
        flags |= flag;
    }

#if DEBUG_PARSER
    ALOGD("Parsed key %s: code=%d, keyCode=%d, flags=0x%08x.",
            mapUsage ? "usage" : "scan code", code, keyCode, flags);
#endif
    Key key;
    key.keyCode = keyCode;
    key.flags = flags;
    // 将scanCode和Key对象的对应关系,添加到mKeysByScanCode中;
    // 这样的话,从驱动上报上来的keyScanCode值,就可以找到对应的keyCode数据了;
    map.add(code, key);
    return NO_ERROR;
}
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/include/input/InputEventLabels.h
static inline int32_t getKeyCodeByLabel(const char* label) {
    return int32_t(lookupValueByLabel(label, KEYCODES)); // 从KEYCODES中找label数据
}

static int lookupValueByLabel(const char* literal, const InputEventLabel *list) {
    while (list->literal) {
        if (strcmp(literal, list->literal) == 0) {
            return list->value;
        }
        list++;
    }
    return list->value;
}

// KEYCODES是一组递增的常量值;
// UNKNOWN是、SOFT_LEFT等是在keycodes.h中定义的int类型数据;
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/include/input/InputEventLabels.h
#define DEFINE_KEYCODE(key) { #key, AKEYCODE_##key }//宏定义键值对;

struct InputEventLabel {
    const char *literal;//名称
    int value;// keycode
};

static const InputEventLabel KEYCODES[] = {
    // NOTE: If you add a new keycode here you must also add it to several other files.
    //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
    DEFINE_KEYCODE(UNKNOWN),
    DEFINE_KEYCODE(SOFT_LEFT),
    DEFINE_KEYCODE(SOFT_RIGHT),
    DEFINE_KEYCODE(HOME),
    DEFINE_KEYCODE(BACK),
    DEFINE_KEYCODE(CALL),
    DEFINE_KEYCODE(ENDCALL),
    DEFINE_KEYCODE(0),
    DEFINE_KEYCODE(1),

    ......

    DEFINE_KEYCODE(SYSTEM_NAVIGATION_DOWN),
    DEFINE_KEYCODE(SYSTEM_NAVIGATION_LEFT),
    DEFINE_KEYCODE(SYSTEM_NAVIGATION_RIGHT),
    DEFINE_KEYCODE(ALL_APPS),
    DEFINE_KEYCODE(REFRESH),
    DEFINE_KEYCODE(THUMBS_UP),
    DEFINE_KEYCODE(THUMBS_DOWN),
    DEFINE_KEYCODE(PROFILE_SWITCH),

    { nullptr, 0 }
};

// 真正的keyCode定义的地方:

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/include/android/keycodes.h
enum {
    /** Unknown key code. */
    AKEYCODE_UNKNOWN         = 0,
    /** Soft Left key.
     * Usually situated below the display on phones and used as a multi-function
     * feature key for selecting a software defined function shown on the bottom left
     * of the display. */
    AKEYCODE_SOFT_LEFT       = 1,
    /** Soft Right key.
     * Usually situated below the display on phones and used as a multi-function
     * feature key for selecting a software defined function shown on the bottom right
     * of the display. */
    AKEYCODE_SOFT_RIGHT      = 2,
    /** Home key.
     * This key is handled by the framework and is never delivered to applications. */
    AKEYCODE_HOME            = 3,
    /** Back key. */
    AKEYCODE_BACK            = 4,
    /** Call key. */
    AKEYCODE_CALL            = 5,
    /** End Call key. */
    AKEYCODE_ENDCALL         = 6,

    ......

    AKEYCODE_THUMBS_DOWN = 287,
    /** Used to switch current account that is consuming content.
     * May be consumed by system to switch current viewer profile. */
    AKEYCODE_PROFILE_SWITCH = 288

    // NOTE: If you add a new keycode here you must also add it to several other files.
    //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
};

scanDevicesLocked-loadKeyMapLocked方法结束,这部分代码比较长,主要是将按键相关配置信息读取到内存中;
接下来看1.1.3-scanDevicesLocked-addDeviceLocked(device)方法;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/EventHub.cpp

// KeyedVector<int32_t, Device*> mDevices;
// Device* mOpeningDevices;
// Device* mClosingDevices;

void EventHub::addDeviceLocked(Device* device) {
    mDevices.add(device->id, device); // 将设备加入EventHub的mDevices中;
    device->next = mOpeningDevices;
    mOpeningDevices = device; // 将此device加入mOpeningDevices
}

至此scanDevicesLocked方法完成,device的各种驱动信息设备信息、配置信息都已加载到内存中;
来分析InputReader处理读取到的数据的流程,以按键信息为例; 根据之前的分析可知,input_event中的信息,包含以下数据:
event->when = processEventTimestamp(iev);
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/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;
        // 若type小于FIRST_SYNTHETIC_EVENT,则是输入事件;
        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;
                    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;
    }
}

此处有两个关键方法,设备开机后,会扫描设备,并触发addDeviceLocked,等有输入事件后,会执行processEventsForDeviceLocked方法:
2.1,processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
2.2,addDeviceLocked(rawEvent->when, rawEvent->deviceId);

先来分析addDeviceLocked方法,会将EventHub中的mDevices转化为InputDevice;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/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);
    // 根据EventHub中的Device的identifier,创建InputReader中的InputDevice对象;
    // eventHubId是EventHud中的deviceId;
    // 此处会创建InputDevice对象,并将device中的classes赋值给InputDevice,然后在InputDevice中创建了处理各种输入事件的mapper对象;
    std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
    // 从EventHub-device中读取配置信息,并赋值给InputDevice,此处不进行分析;
    device->configure(when, &mConfig, 0);
    // 重置mapper信息,此处不进行分析
    device->reset(when);

    if (device->isIgnored()) {
        ...
    } else {
        ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s',sources=0x%08x",
              device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str(),
              device->getSources());
    }

    // 将创建的InputDevice-device和eventHubId进行关联,上报上来的RawEvent里,包含了eventHubId;
    // 根据eventHubId查找InputDevice的map;
    mDevices.emplace(eventHubId, device);
    // 根据InputDevice查找eventHubId的数据结构,相当于可以双向查找,比较快速;
    // 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);
    }
    // return ++mGeneration;
    bumpGenerationLocked();

    if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
        notifyExternalStylusPresenceChanged();
    }
}

来分析InputReader-addDeviceLocked-createDeviceLocked方法:

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/include/InputReader.h
std::unordered_map<int32_t /*eventHubId*/, std::shared_ptr<InputDevice>> mDevices; // eventHubId和InputDevice的对应关系;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/InputReader.cpp
std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
        int32_t eventHubId, const InputDeviceIdentifier& identifier) {
    // 查找此设备是否已存在于InputReader-mDevices中;
    auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
        return devicePair.second->getDescriptor().size() && identifier.descriptor.size() &&
                devicePair.second->getDescriptor() == identifier.descriptor;
    });

    std::shared_ptr<InputDevice> device;
    if (deviceIt != mDevices.end()) { // 若deviceIt不为空
        device = deviceIt->second; // devce指向deviceIt的值
    } else {
        // deviceId递增,mContext是InputReaderContext对象,持有InputReader的引用;
        int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();
        device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),
                                               identifier);
    }
// 注意此处关键方法,创建了多个种类的输入事件对应的mapper;
// 待会儿处理事件的时候会用得到;
    device->addEventHubDevice(eventHubId);
    return device;
}

InputDevice构造方法:
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/InputDevice.cpp
InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
                         const InputDeviceIdentifier& identifier)
      : mContext(context),
        mId(id),
        mGeneration(generation),
        mControllerNumber(0),
        mIdentifier(identifier), // EventHub里的InputDeviceIdentifier
        mClasses(0),
        mSources(0),
        mIsExternal(false),
        mHasMic(false),
        mDropUntilNextSync(false) {}

addEventHubDevice关键方法:
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/InputDevice.cpp
void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
    // 若存在eventHubId对应的InputDevice,则不进行重复添加;
    if (mDevices.find(eventHubId) != mDevices.end()) {
        return;
    }
    // 创建InputDeviceContext,保存了当前InputDevice,以及eventHubId;
    /* 注意此处构造方法,InputDeviceContext中的mContext,指向的是device.getContext(),也就是InputReader中的ContextImpl,InputDeviceContext的构造方法如下;
      InputDeviceContext::InputDeviceContext(InputDevice& device, int32_t eventHubId)
      : mDevice(device),
        mContext(device.getContext()),
        // 从InputReader中获取EventHub对象;
        mEventHub(device.getContext()->getEventHub()),
        mId(eventHubId),
        mDeviceId(device.getId()) {}
    */
    std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
    // 输入设备的类型,如鼠标,键盘,蓝牙手柄等类型;
    uint32_t classes = contextPtr->getDeviceClasses();
    // 根据以上的classes类型,创建各种类型的***Mapper对象,并保存到mappers中
    std::vector<std::unique_ptr<InputMapper>> mappers;

    // populateMappers默认为true,声明:void addEventHubDevice(int32_t eventHubId, bool populateMappers = true);
    // Check if we should skip population
    if (!populateMappers) {
        // 创建了一个DevicePair,contextPtr+mappers对应关系,然后通过eventHubId跟此DevicePair进行一一关联;
        mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
        return;
    }

    // 创建Switch类型的mapper,并保存早mappers中;
    // Switch-like devices.
    if (classes & INPUT_DEVICE_CLASS_SWITCH) {
        mappers.push_back(std::make_unique<SwitchInputMapper>(*contextPtr));
    }

    // 创建Rotary滚轮类型的mapper,并保存早mappers中;
    // Scroll wheel-like devices.
    if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
        mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(*contextPtr));
    }

    // Vibrator-like devices.
    if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
        mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
    }

    // Keyboard-like devices.
    uint32_t keyboardSource = 0;
    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
        keyboardSource |= AINPUT_SOURCE_KEYBOARD;
    }
    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
    }
    if (classes & INPUT_DEVICE_CLASS_DPAD) {
        keyboardSource |= AINPUT_SOURCE_DPAD;
    }
    if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
        keyboardSource |= AINPUT_SOURCE_GAMEPAD;
    }

    // 创Key按键类型的mapper,并保存早mappers中;
    if (keyboardSource != 0) {
        mappers.push_back(
                std::make_unique<KeyboardInputMapper>(*contextPtr, keyboardSource, keyboardType));
    }

    // Cursor-like devices.
    if (classes & INPUT_DEVICE_CLASS_CURSOR) {
        mappers.push_back(std::make_unique<CursorInputMapper>(*contextPtr));
    }

    // Touchscreens and touchpad devices.
    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
        mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
        mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
    }

    // Joystick-like devices.
    if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
        mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr));
    }

    // External stylus-like devices.
    if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
        mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr));
    }

    // .h中,mDevices相关的声明如下;
    // std::make_pair创建了一个DevicePair对,contextPtr+mappers对应关系,然后通过eventHubId跟此DevicePair进行一一关联;
    // map from eventHubId to device context and mappers
    // using MapperVector = std::vector<std::unique_ptr<InputMapper>>;
    // using DevicePair = std::pair<std::unique_ptr<InputDeviceContext>, MapperVector>;
    // std::unordered_map<int32_t, DevicePair> mDevices;
    // 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();
}

来看下待会儿要分析的KeyboardInputMapper的构造方法:

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.h
class KeyboardInputMapper : public InputMapper {
namespace android {

class KeyboardInputMapper : public InputMapper {
public:
    KeyboardInputMapper(InputDeviceContext& deviceContext, uint32_t source, int32_t keyboardType);
    virtual ~KeyboardInputMapper();

    virtual uint32_t getSources() override;
    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo) override;
    virtual void dump(std::string& dump) override;
    virtual void configure(nsecs_t when, const InputReaderConfiguration* config,
                           uint32_t changes) override;
    virtual void reset(nsecs_t when) override;
    virtual void process(const RawEvent* rawEvent) override; // 处理事件

......

private:
    // The current viewport.
    std::optional<DisplayViewport> mViewport;

    struct KeyDown {
        int32_t keyCode;
        int32_t scanCode;
    };

    uint32_t mSource;
    int32_t mKeyboardType;

    std::vector<KeyDown> mKeyDowns; // keys that are down
    int32_t mMetaState;
    nsecs_t mDownTime; // time of most recent key down
    ......
    void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode); // 处理按键
};

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext, uint32_t source, int32_t keyboardType)
      : InputMapper(deviceContext), mSource(source), mKeyboardType(keyboardType) {}

来看下父类InputMapper的构造;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/mapper/InputMapper.h
// 此处返回的是InputReaderContext中的mContext对象,也就是InputReader对象;
inline InputReaderContext* getContext() { return mDeviceContext.getContext(); }
// 调用的是InputReader中的getListener方法;
// 此listener-QueuedInputListener方法封装了InputClassifier对象,而InputClassifier对象持有InputDispatcher对象的应用;
// 通过这样的联系,将InputReader和InputDispatcher两个关键对象联系了起来;
inline InputListenerInterface* getListener() { return getContext()->getListener(); }

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/mapper/InputMapper.cpp
InputMapper::InputMapper(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {}

至此addDeviceLocked方法分析完毕;
总结一下,此方法是根据EventHub中的device信息,创建了InputDevice对象,此对象中持有EventHubId,还有process和processKey等关键方法;
InputDevice持有的context,还持有InputReader的对象,以及InputClassifier对象,可以将输入事件传递给InputDispatcher!
此处逻辑的结束是个分水岭,上面相当于IMS的初始化流程! 下面的代码,涉及事件分发和处理的关键流程!

4.3.5.2 InputReader处理和传递输入数据流程

来分析重要的processEventsForDeviceLocked(deviceId, rawEvent, batchSize);方法,此处涉及将输入事件交给InputDispatcher进行处理的关键流程;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/InputReader.cpp
void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents, size_t count) {
    auto deviceIt = mDevices.find(eventHubId); // 根据eventHubId找到对应的InputDevice;
    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;
    }
    // 使用每个InputDevice的process方法,来处理此设备的对应事件;
    device->process(rawEvents, count);
}

InputReader中的InputDevice,处理事件的方法如下:

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/InputDevice.cpp
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    // Process all of the events in order for each mapper.
    // We cannot simply ask each mapper to process them in bulk because mappers may
    // have side-effects that must be interleaved.  For example, joystick movement events and
    // gamepad button presses are handled by different mappers but they should be dispatched
    // in the order received.
    // 遍历每一个RawEvent对象;
    for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
        .......

        if (mDropUntilNextSync) {
            ......
        } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
            ......
        } else {
            // 上面根据InputDevice的类型,创建了多个mapper对象,此处会循环调用mapper的process方法,来处理对应事件;
            // 这里process方法为什么不取返回值?如果一个mapper处理成功后,还需要另一个mapper处理吗
            for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
                mapper.process(rawEvent);
            });
        }
        --count;
    }
}

根据之前创建InputDevice的代码可知,InputMapper有多个子类方法;
我们这里查看的是按键事件的处理,来看下KeyboardInputMapper的process方法:

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/mapper/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->value != 0, scanCode, usageCode);
            }
            break;
        }
        case EV_MSC: {
            if (rawEvent->code == MSC_SCAN) {
                mCurrentHidUsage = rawEvent->value;
            }
            break;
        }
        case EV_SYN: {
            if (rawEvent->code == SYN_REPORT) {
                mCurrentHidUsage = 0;
            }
        }
    }
}

bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
    return scanCode < BTN_MOUSE || scanCode >= BTN_WHEEL ||
            (scanCode >= BTN_MISC && scanCode < BTN_MOUSE) ||
            (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
}

继续分析processKey方法:

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode) {
    int32_t keyCode; // 待确认的keyCode;
    int32_t keyMetaState;
    uint32_t policyFlags;

    // 根据scanCode或usageCode,获取keyCode,还记得我们查看的.idc,.kl等配置信息吗,这里就派上了用场;
    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);
            }

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

    if (updateMetaStateIfNeeded(keyCode, down)) {
        // If global meta state changed send it along with the key.
        // If it has not changed then we'll use what keymap gave us,
        // since key replacement logic might temporarily reset a few
        // meta bits for given key.
        keyMetaState = mMetaState;
    }

    nsecs_t downTime = mDownTime;

    // Key down on external an keyboard should wake the device.
    // We don't do this for internal keyboards to prevent them from waking up in your pocket.
    // For internal keyboards and devices for which the default wake behavior is explicitly
    // prevented (e.g. TV remotes), the key layout file should specify the policy flags for each
    // wake key individually.
    // TODO: Use the input device configuration to control this behavior more finely.
    if (down && getDeviceContext().isExternal() && !mParameters.doNotWakeByDefault &&
        !isMediaKey(keyCode)) {
        policyFlags |= POLICY_FLAG_WAKE;
    }

    if (mParameters.handlesKeyRepeat) {
        policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
    }

    // 注意此处的继承关系,struct NotifyKeyArgs : public NotifyArgs
    // NotifyArgs的函数实现在此目录:
    //  frameworks/native/services/inputflinger/InputListener.cpp
    //  frameworks/native/services/inputflinger/include/InputListener.h
    NotifyKeyArgs args(getContext()->getNextId(), when, 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);
}

上面有两个关键调用,mapKey是获取scanCode对应的keyCode,notifyKey会将NotifyKeyArgs分发给InputDispatcher:

2.1.1:getDeviceContext().mapKey(…);
2.1.2:NotifyKeyArgs args(…);getListener()->notifyKey(&args);

先来分析mapKey方法,再去分析getListener()->notifyKey(&args);

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/include/InputDevice.h
    inline status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
        return mEventHub->mapKey(mId, scanCode, usageCode, metaState, outKeycode, outMetaState, outFlags);
    }

此处兜兜转转,又回到了EventHub中,因为只有EventHub中的device,才持有此输入设备对应的kl和kcm配置信息;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/EventHub.cpp
status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
    AutoMutex _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    status_t status = NAME_NOT_FOUND;

    if (device) {
        // Check the key character map first.
        sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();
        if (kcm != nullptr) {
            if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
                *outFlags = 0;
                status = NO_ERROR;
            }
        }

        // 通过.kl文件的配置,通过scancode找到keycode
        // Check the key layout next.
        if (status != NO_ERROR && device->keyMap.haveKeyLayout()) {
            if (!device->keyMap.keyLayoutMap->mapKey(scanCode, usageCode, outKeycode, outFlags)) {
                status = NO_ERROR;
            }
        }

        if (status == NO_ERROR) {
            if (kcm != nullptr) {
                kcm->tryRemapKey(*outKeycode, metaState, outKeycode, outMetaState);
            } else {
                *outMetaState = metaState;
            }
        }
    }

    if (status != NO_ERROR) {
        *outKeycode = 0;
        *outFlags = 0;
        *outMetaState = metaState;
    }

    return status;
}
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/libs/input/KeyLayoutMap.cpp

status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode,
        int32_t* outKeyCode, uint32_t* outFlags) const {
    const Key* key = getKey(scanCode, usageCode); // 查找keycode
    if (!key) {
        ....
    }

    *outKeyCode = key->keyCode; // 将keyCode赋值给outKeyCode
    *outFlags = key->flags;

    ......
    return NO_ERROR;
}
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/libs/input/KeyLayoutMap.cpp
const KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCode) const {
    if (usageCode) {
        ...
    }
    if (scanCode) {
        // 从mKeysByScanCode中查找scanCode,若找到,则返回Key对象,mKeysByUsageCode的类型为:KeyedVector<int32_t, Key> mKeysByUsageCode;
        ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
        if (index >= 0) {
            return &mKeysByScanCode.valueAt(index);
        }
    }
    return nullptr;
}

至此,key的各种参数都已经拿到了,包括:scanCode,keyCode,action,deviceId,displayId等信息;
接下来分析key数据是如何传递到app层的;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode) {
    int32_t keyCode;
    int32_t keyMetaState;
    uint32_t policyFlags;

    if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,
                                  &policyFlags)) {
        keyCode = AKEYCODE_UNKNOWN;
        keyMetaState = mMetaState;
        policyFlags = 0;
    }

    ......

    if (mParameters.handlesKeyRepeat) {
        policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
    }

    NotifyKeyArgs args(getContext()->getNextId(), when, 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);
}
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/mapper/InputMapper.h
inline InputListenerInterface* getListener() { return getContext()->getListener(); }

// 这里getContext指向的是ContextImpl对象;
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/mapper/InputMapper.h
inline InputReaderContext* getContext() { return mDeviceContext.getContext(); }
inline InputListenerInterface* getListener() { return getContext()->getListener(); }

// 拿到QueuedInputListener-mQueuedListener对象
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/reader/InputReader.cpp
InputListenerInterface* InputReader::ContextImpl::getListener() {
    return mReader->mQueuedListener.get();
}

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/InputListener.cpp
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
    traceEvent(__func__, args->id);
    // 将NotifyKeyArgs加入mArgsQueue队列,等待消费;
    mArgsQueue.push_back(new NotifyKeyArgs(*args)); 
}

#至此InputReader-loopOnce-processEventsLocked(mEventBuffer, count)方法完成;
这里对mEventBuffer中的原始数据进行了解析,将如按键数据解析为Key对应的上层数据,并加入了QueuedInputListener-mQueuedListener的mArgsQueue中,等待消费;

loopOnce中还有以下两处关键方法,notifyInputDevicesChanged方法不再分析,来看下关键流程mQueuedListener->flush().

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/InputListener.cpp
void QueuedInputListener::flush() {
    size_t count = mArgsQueue.size();
    // 循环调用mArgsQueue中的每一个NotifyArgs的notify方法,注意mInnerListener参数,是QueuedInputListener构造的入参,也就是InputClassifier对象;
    for (size_t i = 0; i < count; i++) {
        NotifyArgs* args = mArgsQueue[i];
        args->notify(mInnerListener);
        delete args;
    }
    mArgsQueue.clear();
}

QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
        mInnerListener(innerListener) {
}

NotifyArgs有多个子类,其中就有之前创建的NotifyKeyArgs,所以此处notify调用的是NotifyKeyArgs的notify方法;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/InputListener.cpp
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
    listener->notifyKey(this);
}

listener就是QueuedInputListener中的mInnerListener对象,也就是InputClassifier对象;
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/InputClassifier.cpp
void InputClassifier::notifyKey(const NotifyKeyArgs* args) {
    // pass through
    mListener->notifyKey(args);
}

4.3.5.3 InputDispatcher传递输入数据流程

根据上面章节的调用,notifyKey调用到了InputDispatcher的方法中;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    mClassifier = new InputClassifier(mDispatcher);
    mReader = createInputReader(readerPolicy, mClassifier);
}
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/InputClassifier.cpp
InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
      : mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {}

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
    ......
    if (!validateKeyEvent(args->action)) {
        return;
    }

    uint32_t policyFlags = ...

    policyFlags |= POLICY_FLAG_TRUSTED;

    int32_t keyCode = args->keyCode;
    accelerateMetaShortcuts(args->deviceId, args->action, keyCode, metaState);

    // 将NotifyKeyArgs数据复制到KeyEvent中;
    KeyEvent event;
    event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
                     args->action, flags, keyCode, args->scanCode, metaState, repeatCount,
                     args->downTime, args->eventTime);

    android::base::Timer t;
    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();

            // InputManagerService过滤并消费掉了此事件,不需要传给应用层;
            policyFlags |= POLICY_FLAG_FILTERED;
            if (!mPolicy->filterInputEvent(&event, policyFlags)) {
                return; // event was consumed by the filter
            }

            mLock.lock();
        }
        // 将NotifyKeyArgs数据复制到KeyEntry中,并加入缓冲队列,等待消费;
        KeyEntry* newEntry =
                new KeyEntry(args->id, args->eventTime, args->deviceId, args->source,
                             args->displayId, policyFlags, args->action, flags, keyCode,
                             args->scanCode, metaState, repeatCount, args->downTime);

        needWake = enqueueInboundEventLocked(newEntry);
        mLock.unlock();
    } // release lock

    // 唤醒消费队列dispatchOnce方法;
    if (needWake) {
        mLooper->wake();
    }
}
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    // 若队列为空,则需要唤醒;
    bool needWake = mInboundQueue.empty();
    // 加入mInboundQueue队列,等待dispatchOnce方法消费此队列中的内容;
    mInboundQueue.push_back(entry);
    traceInboundQueueLengthLocked();

    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) {
                        .......
                        mAppSwitchDueTime = keyEntry.eventTime + APP_SWITCH_TIMEOUT;
                        mAppSwitchSawKeyDown = false;
                        needWake = true;
                    }
                }
            }
            break;
        }

        case EventEntry::Type::MOTION: {
            if (shouldPruneInboundQueueLocked(static_cast<MotionEntry&>(*entry))) {
                mNextUnblockedEvent = entry;
                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: {
            // nothing to do
            break;
        }
    }

    return needWake;
}

至此生产者模式已经生产出了输入事件,添加到了缓冲队列mInboundQueue中,并唤醒了消费队列;
接下来看消费队列如何消费事件并传递给app层的:

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        std::scoped_lock _l(mLock);
        mDispatcherIsAlive.notify_all();

        // 开始消费mInboundQueue中的数据;
        // 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;
        }

        // 检查是否存在事件消费的ANR行为;
        // 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

    // 自动唤醒?
    // Wait for callback or timeout or wake.  (make sure we round up, not down)
    nsecs_t currentTime = now();
    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
    mLooper->pollOnce(timeoutMillis);
}

来分析dispatchOnceInnerLocked方法,是如何消费事件的;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    nsecs_t currentTime = now();

    // Reset the key repeat timer whenever normal dispatch is suspended while the
    // device is in a non-interactive state.  This is to ensure that we abort a key
    // repeat if the device is just coming out of sleep.
    if (!mDispatchEnabled) {
        resetKeyRepeatLocked();
    }

    // If dispatching is frozen, do not process timeouts or try to deliver any new events.
    if (mDispatchFrozen) {
        if (DEBUG_FOCUS) {
            ALOGD("Dispatch frozen.  Waiting some more.");
        }
        return;
    }

    // Optimize latency of app switches.
    // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
    // been pressed.  When it expires, we preempt dispatch and drop all other pending events.
    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
    if (mAppSwitchDueTime < *nextWakeupTime) {
        *nextWakeupTime = mAppSwitchDueTime;
    }

    // Ready to start a new event.
    // If we don't already have a pending event, go grab one.
    if (!mPendingEvent) {
        if (mInboundQueue.empty()) {
            ......
        } else {
            // 拿出队列中的首个事件;
            // Inbound queue has at least one entry.
            mPendingEvent = mInboundQueue.front();
            mInboundQueue.pop_front();
            traceInboundQueueLengthLocked();
        }

        ......
    }

    // 拿到了首个输入事件mPendingEvent,准备传递;
    // Now we have an event to dispatch.
    // All events are eventually dequeued and processed this way, even if we intend to drop them.
    ALOG_ASSERT(mPendingEvent != nullptr);
    bool done = false;
    DropReason dropReason = DropReason::NOT_DROPPED;
    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
        dropReason = DropReason::POLICY;
    } else if (!mDispatchEnabled) {
        dropReason = DropReason::DISABLED;
    }

    if (mNextUnblockedEvent == mPendingEvent) {
        mNextUnblockedEvent = nullptr;
    }

    switch (mPendingEvent->type) {
        case EventEntry::Type::CONFIGURATION_CHANGED: {
            ...
            break;
        }

        case EventEntry::Type::DEVICE_RESET: {
            ...
            break;
        }

        case EventEntry::Type::FOCUS: {
            ...
            break;
        }

        case EventEntry::Type::KEY: {
            KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
            if (isAppSwitchDue) {
                if (isAppSwitchKeyEvent(*typedEntry)) {
                    resetPendingAppSwitchLocked(true);
                    isAppSwitchDue = false;
                } else if (dropReason == DropReason::NOT_DROPPED) {
                    dropReason = DropReason::APP_SWITCH;
                }
            }
            if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *typedEntry)) {
                dropReason = DropReason::STALE;
            }
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
                dropReason = DropReason::BLOCKED;
            }
            // 消费此按键事件;
            done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
            break;
        }

        case EventEntry::Type::MOTION: {
            MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
            if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
                dropReason = DropReason::APP_SWITCH;
            }
            if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *typedEntry)) {
                dropReason = DropReason::STALE;
            }
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
                dropReason = DropReason::BLOCKED;
            }
            done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
            break;
        }
    }

    if (done) {
        if (dropReason != DropReason::NOT_DROPPED) {
            dropInboundEventLocked(*mPendingEvent, dropReason);
        }
        mLastDropReason = dropReason;
        // 释放此事件,其实是添加到mRecentQueue中,可能是用于判断ANR?
        releasePendingEventLocked();
        *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
    }
    // 方法结束,进入下一dispatchOnce循环,再次消费front的输入事件;
}

来分析dispatchKeyLocked方法;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
                                        DropReason* dropReason, nsecs_t* nextWakeupTime) {
    // Preprocessing.
    if (!entry->dispatchInProgress) {
        ......
        entry->dispatchInProgress = true;
        logOutboundKeyDetails("dispatchKey - ", *entry);
    }

    // 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) {
            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) {
        ......
    } 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) {
        setInjectionResult(entry, *dropReason == DropReason::POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
        mReporter->reportDroppedKey(entry->id);
        return true;
    }

    // 查找需要消费输入事件的window对象,存入inputTargets中;
    // Identify targets.
    std::vector<InputTarget> inputTargets;
    int32_t injectionResult =
            findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
        return false;
    }

    setInjectionResult(entry, injectionResult);
    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
        return true;
    }

    // Add monitor channels from event's or focused display.
    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));

    // Dispatch the key.
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

上面有两个关键方法要调查,方法1要查找消费此事件的windowTarget和InputChannel,然后方法2-dispatchEventLocked将事件传递给app的某一个window:
1,findFocusedWindowTargetsLocked 2,dispatchEventLocked

来分析findFocusedWindowTargetsLocked;
在分析findFocusedWindowTargetsLocked之前,来看下InputTarget数据结构,可以看到InputTarget包含了sp inputChannel对象,inputChannel能够把数据发给app端的inputChannel:

struct InputTarget {
    enum {
        /* This flag indicates that the event is being delivered to a foreground application. */
        FLAG_FOREGROUND = 1 << 0,

        /* This flag indicates that the MotionEvent falls within the area of the target
         * obscured by another visible window above it.  The motion event should be
         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
        FLAG_WINDOW_IS_OBSCURED = 1 << 1,

        ...

        /* Mask for all dispatch modes. */
        FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS | FLAG_DISPATCH_AS_OUTSIDE |
                FLAG_DISPATCH_AS_HOVER_ENTER | FLAG_DISPATCH_AS_HOVER_EXIT |
                FLAG_DISPATCH_AS_SLIPPERY_EXIT | FLAG_DISPATCH_AS_SLIPPERY_ENTER,

        /* This flag indicates that the target of a MotionEvent is partly or wholly
         * obscured by another visible window above it.  The motion event should be
         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
        FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,

    };

    // 要传入数据的InputChannel对象;
    // The input channel to be targeted.
    sp<InputChannel> inputChannel;

    // Flags for the input target.
    int32_t flags = 0;

    // Scaling factor to apply to MotionEvent as it is delivered.
    // (ignored for KeyEvents)
    float globalScaleFactor = 1.0f;

    // The subset of pointer ids to include in motion events dispatched to this input target
    // if FLAG_SPLIT is set.
    BitSet32 pointerIds;
    // The data is stored by the pointerId. Use the bit position of pointerIds to look up
    // PointerInfo per pointerId.
    PointerInfo pointerInfos[MAX_POINTERS];

    ...
};

std::string dispatchModeToString(int32_t dispatchMode);

} // namespace android::inputdispatcher
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry& entry, std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
    std::string reason;
    // 获取输入事件对应的displayId,以便找到此display上的focusedWindowHandle。
    int32_t displayId = getTargetDisplayId(entry);
    // 根据displayId查找焦点window和焦点应用程序, mFocusedWindowHandlesByDisplay是一个map类型的数据结构,key为displayId;
    sp<InputWindowHandle> focusedWindowHandle =
            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
    sp<InputApplicationHandle> focusedApplicationHandle =
            getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);

    // If there is no currently focused window and no focused application
    // then drop the event.
    if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr) {
        ALOGI("Dropping %s event because there is no focused window or focused application in "
              "display %" PRId32 ".",
              EventEntry::typeToString(entry.type), displayId);
        return INPUT_EVENT_INJECTION_FAILED;
    }

    // Compatibility behavior: raise ANR if there is a focused application, but no focused window.
    // Only start counting when we have a focused event to dispatch. The ANR is canceled if we
    // start interacting with another application via touch (app switch). This code can be removed
    // if the "no focused window ANR" is moved to the policy. Input doesn't know whether
    // an app is expected to have a focused window.
    if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {
        ......
    }

    // we have a valid, non-null focused window
    resetNoFocusedWindowTimeoutLocked();

    // Check permissions.
    if (!checkInjectionPermission(focusedWindowHandle, entry.injectionState)) {
        return INPUT_EVENT_INJECTION_PERMISSION_DENIED;
    }

    if (focusedWindowHandle->getInfo()->paused) {
        ALOGI("Waiting because %s is paused", focusedWindowHandle->getName().c_str());
        return INPUT_EVENT_INJECTION_PENDING;
    }

    // If the event is a key event, then we must wait for all previous events to
    // complete before delivering it because previous events may have the
    // side-effect of transferring focus to a different window and we want to
    // ensure that the following keys are sent to the new window.
    //
    // Suppose the user touches a button in a window then immediately presses "A".
    // If the button causes a pop-up window to appear then we want to ensure that
    // the "A" key is delivered to the new pop-up window.  This is because users
    // often anticipate pending UI changes when typing on a keyboard.
    // To obtain this behavior, we must serialize key events with respect to all
    // prior input events.
    if (entry.type == EventEntry::Type::KEY) {
        if (shouldWaitToSendKeyLocked(currentTime, focusedWindowHandle->getName().c_str())) {
            *nextWakeupTime = *mKeyIsWaitingForEventsTimeout;
            return INPUT_EVENT_INJECTION_PENDING;
        }
    }

    // 将focusedWindowHandle添加到inputTargets集合中;
    // Success!  Output targets.
    addWindowTargetLocked(focusedWindowHandle,
                          InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
                          BitSet32(0), inputTargets);

    // Done.
    return INPUT_EVENT_INJECTION_SUCCEEDED;
}
/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
/**
 * Get the display id that the given event should go to. If this event specifies a valid display id,
 * then it should be dispatched to that display. Otherwise, the event goes to the focused display.
 * Focused display is the display that the user most recently interacted with.
 */
int32_t InputDispatcher::getTargetDisplayId(const EventEntry& entry) {
    int32_t displayId;
    switch (entry.type) {
        case EventEntry::Type::KEY: {
            const KeyEntry& keyEntry = static_cast<const KeyEntry&>(entry);
            displayId = keyEntry.displayId;
            break;
        }
        case EventEntry::Type::MOTION: {
            const MotionEntry& motionEntry = static_cast<const MotionEntry&>(entry);
            displayId = motionEntry.displayId;
            break;
        }
        case EventEntry::Type::FOCUS:
        case EventEntry::Type::CONFIGURATION_CHANGED:
        case EventEntry::Type::DEVICE_RESET: {
            ALOGE("%s events do not have a target display", EventEntry::typeToString(entry.type));
            return ADISPLAY_ID_NONE;
        }
    }
    // 若输入事件未指定屏幕id,则返回焦点屏幕id,即用户最近操作的屏幕;
    return displayId == ADISPLAY_ID_NONE ? mFocusedDisplayId : displayId;
}

map类型的键值对,保存了焦点window和焦点app;
在应用程序ViewRootImpl.addView时,会将焦点窗口传入此处并保存下来,此处逻辑不再赘述;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.h
    // Focus tracking for keys, trackball, etc. 屏幕id和InputWindowHandle的对应关系;
    std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay
            GUARDED_BY(mLock);

    // Focused applications.
    std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay
            GUARDED_BY(mLock);


/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
                                            int32_t targetFlags, BitSet32 pointerIds,
                                            std::vector<InputTarget>& inputTargets) {
    std::vector<InputTarget>::iterator it =
            std::find_if(inputTargets.begin(), inputTargets.end(),
                         [&windowHandle](const InputTarget& inputTarget) {
                             return inputTarget.inputChannel->getConnectionToken() ==
                                     windowHandle->getToken();
                         });

    const InputWindowInfo* windowInfo = windowHandle->getInfo();

    if (it == inputTargets.end()) {
        InputTarget inputTarget;
        // 根据token获取InputChannel,token和InputChannel的键值对map数据,在mInputChannelsByToken中保存。
        sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
        if (inputChannel == nullptr) {
            ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str());
            return;
        }
        // 将inputChannel等相关信息,保存到inputTarget中;
        inputTarget.inputChannel = inputChannel;
        inputTarget.flags = targetFlags;
        inputTarget.globalScaleFactor = windowInfo->globalScaleFactor;
        inputTargets.push_back(inputTarget);
        it = inputTargets.end() - 1;
    }

    ALOG_ASSERT(it->flags == targetFlags);
    ALOG_ASSERT(it->globalScaleFactor == windowInfo->globalScaleFactor);

    it->addPointers(pointerIds, -windowInfo->frameLeft, -windowInfo->frameTop,
                    windowInfo->windowXScale, windowInfo->windowYScale);
}

至此findFocusedWindowTargetsLocked分析完毕,是查找焦点窗口对应的InputChannel,并保存到inputTargets中;
4.3.5.3 InputChannel传递输入数据

来看下如何将Event输入数据,通过dispatchEventLocked方法,传递给InputChannel。

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry,
                                          const std::vector<InputTarget>& inputTargets) {
    ......

    for (const InputTarget& inputTarget : inputTargets) {
        // 根据inputTarget.inputChannel的token,获取对应的Connection?
        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());
            }
        }
    }
}

疑问:此处为什么要通过inputChannel的token,获取connection对象?inputTarget中已持有inputChannel,已经可以传输数据了啊?

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const {
    if (inputConnectionToken == nullptr) {
        return nullptr;
    }

    for (const auto& pair : mConnectionsByFd) {
        const sp<Connection>& connection = pair.second;
        if (connection->inputChannel->getConnectionToken() == inputConnectionToken) {
            return connection;
        }
    }

    return nullptr;
}

来看下eventEntry开始传输的最后处理流程;

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
                                                 const sp<Connection>& connection,
                                                 EventEntry* eventEntry,
                                                 const InputTarget& inputTarget) {
    ...

    // Skip this event if the connection status is not normal.
    // We don't want to enqueue additional outbound events if the connection is broken.
    if (connection->status != Connection::STATUS_NORMAL) {
        ....
        return;
    }

    // Split a motion event if needed.
    if (inputTarget.flags & InputTarget::FLAG_SPLIT) {
        ...
    }

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

enqueueDispatchEntryLocked将要传输的eventEntry,添加到connection的outboundQueue队列中;
然后通过startDispatchCycleLocked方法,将输入对象传递给app侧;

void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
                                                   const sp<Connection>& connection,
                                                   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()) {
        startDispatchCycleLocked(currentTime, connection);
    }
}

void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
                                                 EventEntry* eventEntry,
                                                 const InputTarget& inputTarget,
                                                 int32_t dispatchMode) {
    ...
    int32_t inputTargetFlags = inputTarget.flags;
    if (!(inputTargetFlags & dispatchMode)) {
        return;
    }
    inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;

    // This is a new event.
    // Enqueue a new dispatch entry onto the outbound queue for this connection.
    std::unique_ptr<DispatchEntry> dispatchEntry =
            createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);

    // Use the eventEntry from dispatchEntry since the entry may have changed and can now be a
    // different EventEntry than what was passed in.
    EventEntry* newEntry = dispatchEntry->eventEntry;
    // Apply target flags and update the connection's input state.
    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;
        }

        case EventEntry::Type::MOTION: {
            ............

            break;
        }
        case EventEntry::Type::FOCUS: {
            break;
        }
        case EventEntry::Type::CONFIGURATION_CHANGED:
        case EventEntry::Type::DEVICE_RESET: {
            LOG_ALWAYS_FATAL("%s events should not go to apps",
                             EventEntry::typeToString(newEntry->type));
            break;
        }
    }

    // Remember that we are waiting for this dispatch to complete.
    if (dispatchEntry->hasForegroundTarget()) {
        incrementPendingForegroundDispatches(newEntry);
    }

    // 将eventEntry添加到connection->outboundQueue中;
    // Enqueue the dispatch entry.
    connection->outboundQueue.push_back(dispatchEntry.release());
    traceOutboundQueueLength(connection);
}

来分析startDispatchCycleLocked方法,应该是将connection->outboundQueue发到app侧;

void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
                                               const sp<Connection>& connection) {
    ......
    // outboundQueue队列不为空,则一直while循环;
    while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.empty()) {
        // 拿到队首的输入事件;
        DispatchEntry* dispatchEntry = connection->outboundQueue.front();
        dispatchEntry->deliveryTime = currentTime;
        const nsecs_t timeout =
                getDispatchingTimeoutLocked(connection->inputChannel->getConnectionToken());
        dispatchEntry->timeoutTime = currentTime + timeout;

        // Publish the event.
        status_t status;
        EventEntry* eventEntry = dispatchEntry->eventEntry;
        switch (eventEntry->type) {
            case EventEntry::Type::KEY: {
                const KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
                std::array<uint8_t, 32> hmac = getSignature(*keyEntry, *dispatchEntry);

                // 通过InputPublisher对象发布此输入事件给上层逻辑;
                // Publish the key event.
                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);
                break;
            }

            case EventEntry::Type::MOTION: {
                ......

                // Publish the motion event.
                status = connection->inputPublisher
                                 .publishMotionEvent(......
                break;
            }
            case EventEntry::Type::FOCUS: {
                ......
        }

        // Check the result.
        if (status) {
            .........
            return;
        }

        // 删除已发布的输入事件,并进入下一循环;
        // Re-enqueue the event on the wait queue.
        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);
    }
}

// 最终会拿到App的对端InputChannel对象,并调用sendMessage方法,将数据通过InputChannel通道下发;
// 然后App端的InputChannel就能够读到输入数据,并响应对应的业务逻辑。

/home/chen/disk2/project/aosp/r_aosp/frameworks/native/libs/input/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) {
    if (ATRACE_ENABLED()) {
        std::string message = StringPrintf("publishKeyEvent(inputChannel=%s, keyCode=%" PRId32 ")", mChannel->getName().c_str(), keyCode);
        ATRACE_NAME(message.c_str());
    }
    if (DEBUG_TRANSPORT_ACTIONS) {
        ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u, deviceId=%d, source=0x%x,  action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d, downTime=%" PRId64 ", eventTime=%" PRId64, mChannel->getName().c_str(), seq, deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount, downTime, eventTime);
    }

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

    InputMessage msg;
    msg.header.type = InputMessage::Type::KEY;
    msg.body.key.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);
}

至此,system_server进程IMS模块,从驱动读取按键类型输入事件,并传递给App模块的流程已完成;
App侧读取并分发按键事件的流程在其他章节会继续介绍;

4.4 App接收和传递Input事件流程

另起一篇;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值