• android的frameworks层键盘事件处理流程分析


    事件处理流程
    1)InputManager负责读取事件并把事件送到frameworks的java层
    2)WindowManagerService里会有一个InputMonitor类来监听事件变化并做相应的分发处理。
    3)在WindowManagerService会有一个WindowManagerPolicy来做消息拦截处理。
    4)WindowManagerService会把消息发给最上面运行的窗口接收

    源码分析
    WindowManagerService.java主要向Android为窗口系统提供服务,把KeyEvent分发给最上层的窗口;
    WindowManagerService通过InputManager提供的native接口开启了两个线程驱动做KeyEvent读取和分发给WindowManagerService管理的客户端。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    mInputManager = new InputManager(context, this);
    mInputManager.start();
     
    InputManager是WindowManagerService的成员变量,主要实现了读取RawEvent,分发事件给WindowManagerService;
    InputManager.java的native代码InputManager.cpp实现了读取和事件分发,他初始化两个线程
    void InputManager::initialize() {
        mReaderThread = new InputReaderThread(mReader);//不断地从/dev/input/目录下面的设备文件读取事件
        mDispatcherThread = new InputDispatcherThread(mDispatcher);//事件分发
    }
    InputManager通过InputManager.Callbacks类响应回调,在回调里再调用 WindowManagerService.InputMonitor来接收事件。并在 WindowManagerService.InputMonitor.interceptKeyBeforeQueueing()和 interceptKeyBeforeDispatching()进行消息拦截处理。处理的代码如下:
    WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
            /* Provides an opportunity for the window manager policy to intercept early key
             * processing as soon as the key has been read from the device. */
            public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
                    int policyFlags, boolean isScreenOn) {
                return mPolicy.interceptKeyBeforeQueueing(whenNanos,
                        keyCode, down, policyFlags, isScreenOn);
            }
    拦截处理的执行代码就在PhoneWindowManager.interceptKeyBeforeQueueing()方法中。详细的请参看源码

    EventHub.cpp主要用来读取设备文件中的RawEvent,而InputReader.cpp和InputDispatcher.cpp算是它们之间的对接层。InputReader从设备文件中读取的是RawEvent,在交给InputDispatcher进行分发之前,它需要先把 RawEvent进行转化分类,拆分成KeyEvent、MotionEvent、TrackEvent各种类型等。

    相关源代码位置
    /frameworks/base/services/java/com/android/server/WindowManagerService.java(事件分发给最前面的窗口)
    /frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java(拦截消息的处理类)
    /frameworks/base/core/java/android/view/KeyEvent.java(按键事件定义)
    /frameworks/base/services/java/com/android/server/InputManager.Java(Java层输入管理)
    /frameworks/base/libs/ui/InputManager.cpp(native层输入管理)
    /frameworks/base/libs/ui/InputReader.cpp(事件读取线程)
    /frameworks/base/libs/ui/InputDispatcher.cpp(事件分发线程)

    /frameworks/base/libs/ui/EventHub.cpp(键码与键值转换)


    参考文档:

    Android按键事件处理流程 -- KeyEvent

  • 相关阅读:
    Android studio 快捷键记录
    Android开发 判断目标Fragment是否在前台
    Android开发 build.gradle的使用记录
    Android开发 在Application用于初始化的工具类
    Android开发 因为模块化导致findViewById返回为空null
    Android开发 本地广播
    Android开发 报错: xxx does not have a NavController set on xxx
    Android开发 GridLayout网格布局
    Android开发 Fragment启动Activity在使用onActivityResult的一些问题
    Html 创建自定义标签并且被jQuery获取到
  • 原文地址:https://www.cnblogs.com/chengliu/p/4130608.html
Copyright © 2020-2023  润新知