Event事件的实现(Android 2.3)

相关文件

// Java相关
framework/base/core/java/android/view/IWindowManager.aidl
framework/base/core/java/android/view/KeyCharacterMap.java
framework/base/services/java/com/android/server/WindowManagerService.java
framework/base/services/java/com/android/server/KeyInputQueue.java
framework/base/services/java/com/android/server/InputDevice.java
frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

// JNI接口
framework/base/services/jni/com_android_server_InputManager.cpp
framework/base/core/jni/android_view_InputQueue.cpp
framework/base/core/jni/android_view_InputChannel.cpp

// C++相关
framework/base/libs/ui/Input.cpp
framework/base/libs/ui/InputDispatcher.cpp
framework/base/libs/ui/InputManager.cpp
framework/base/libs/ui/InputReader.cpp
framework/base/libs/ui/InputTransport.cpp
framework/base/libs/ui/EventHub.cpp
framework/base/libs/ui/KeyLayoutMap.cpp
framework/base/libs/ui/KeyCharacterMap.cpp
framework/base/libs/utils/Looper.cpp
framework/base/libs/utils/Threads.cpp

Event事件处理概述

    首先我们要明确一个概念,keyboard或者touch事件最先由底层硬件接收,再通过驱动一层一层向上传递。
中间经过了JNI调用,进程间通信等过程。而Java层主要是根据不同的事件类型,调用用户自定义的回调方法,
从而做出不同事件的响应处理。无论是哪种类型的事件,都是经过统一的处理流程来实现。
    其次,我们还需要知道Event事件是通过Service获取,目前Android是通过创建Java层的
WindowManagerService,该服务通过JNI调用C/C++代码来实现Event事件的接收,最后传递给当前焦点的Activity。
    第三,输入事件由Service捕获,再通过ashem的机制传递给其他需要处理的应用程序。
    第四,所有事件都会经过主窗口进行预处理再分发给用户窗口。
    我们的分析从Service开始。

Java层的service实现

    Java层会在SystemServer启动时加载WindownManagerService的服务,该类继承自IWindowManager.Stub。
与Andriod 2.1不同的是,输入事件由一个InputManager管理类来处理,它主要通过native的方法来初始化C++
层的InputManager管理类,并开启输入事件的监听线程,此外还提供了调用其他native方法的接口。那么我们
关心的事件接收和事件分发的处理在哪里呢?答案是native层,下面我们将详细分析C++层的InputManager类。

JNI层的接口实现

    Java层InputManager对应的native代码在文件com_android_server_InputManager.cpp中,它包含
NativeInputManager用来作C++层InputManager的初始化。该类主要有三个作用:
    1. 对C++层方法作封装,让native代码更清晰。
    2. 实现InputReaderPolicyInterface和InputDispatcherPolicyInterface的接口。
    3. 初始化时接收来自Java层InputManager.Callbacks作为回调。
    
    Java层InputChannel对应的native代码在android_view_InputChannel.cpp中,它用来初始化Server端和Client
端的InputChannel对象(C++层)。具体的实现是通过InputChannel(C++层)完成。

    Java层的InputQueue对应的native代码在android_view_InputQueue.cpp中,它用来注册Client端的
InputChannel,实现处理事件消息的callback方法。

C++层的事件处理模块

各模块的简要描述

数据结构类

功能实现类

管理类

Event处理流程

启动事件监听服务

如何实现事件的读取

如何实现事件的分发一

Looper类

Thread类

CommandEntry(预处理队列)

DispatchEntry(分发队列)

加入队列之前做预处理

分发给用户之前做预处理

如何实现事件的分发二

请求加入Looper的监听循环

两个回调函数

发布者和消费者的抽象

Event处理总结

/*
 * NDK input queue API.
 *
 * Here is the event flow:
 * 1. Event arrives in input consumer, and is returned by getEvent().
 * 2. Application calls preDispatchEvent():
 *    a. Event is assigned a sequence ID and enqueued in mPreDispatchingKeys.
 *    b. Main thread picks up event, hands to input method.
 *    c. Input method eventually returns sequence # and whether it was handled.
 *    d. finishPreDispatch() is called to enqueue the information.
 *    e. next getEvent() call will:
 *       - finish any pre-dispatch events that the input method handled
 *       - return the next pre-dispatched event that the input method didn't handle.
 *    f. (A preDispatchEvent() call on this event will now return false).
 * 3. Application calls finishEvent() with whether it was handled.
 *    - If handled is true, the event is finished.
 *    - If handled is false, the event is put on mUnhandledKeys, and:
 *      a. Main thread receives event from consumeUnhandledEvent().
 *      b. Java sends event through default key handler.
 *      c. event is finished.
 */

Event处理类图

参考代码