欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新

Android 输入系统介绍,同时,IMS输入系统

来源: 开发者 投稿于  被查看 49883 次 评论:99

Android 输入系统介绍,同时,IMS输入系统


目录
  • 一、目的
  • 二、环境
  • 三、相关概念
    • 3.1 输入设备
    • 3.2 UEVENT机制
    • 3.3 JNI
    • 3.4 EPOLL机制
    • 3.5 INotify
  • 四、详细设计
    • 4.1 结构图
    • 4.2 代码结构
    • 4.3 InputManagerService模块
      • 4.3.1 IMS服务入口
      • 4.3.2 IMS初始化
      • 4.3.3 IMS启动
      • 4.3.4 IMS消息监听
    • 4.4 NativeInputManager模块
      • 4.4.1 nativeInit初始化
      • 4.4.2 nativeStart启动
    • 4.5 Inputflinger模块
      • 4.5.1 启动事件管理服务
    • 4.6 Inputreader模块
      • 4.6.1 启动InputReader线程
      • 4.6.2 EventHub获取事件队列
      • 4.6.3 Input事件加工
      • 4.6.4 事件发布
    • 4.7 Inputdispatcher模块
      • 4.7.1 Input事件上报
      • 4.7.2 启动InputDispatcher线程
    • 4.8 WindowManagerService模块
      • 4.8.1 ViewRootImpl阶段
      • 4.8.2 WindowManagerService.addWindow()
      • 4.8.3 WindowInputEventReceiver
  • 五、Input设备节点介绍
    • 5.1 常见触摸事件类型
    • 5.2 getevent
    • 5.3 sendevent
  • 六、参考资料

一、目的

        最近接触到了一个问题:耳机插入事件的由来,走读了下IMS输入系统服务的源码。同时,IMS输入系统服务在Android的开发过程中,也经常出现,有必要了解下相关原理。

  1. 学习下IMS输入系统的源码设计,了解该模块承担的业务职责,熟悉Android结构
  2. 了解Android屏幕点击事件、物理按键事件的分发规则

二、环境

  1. 版本:Android 11
  2. 平台:高通 QCM2290

三、相关概念

3.1 输入设备

        常见的输入设备有鼠标、键盘、触摸屏等,用户通过输入设备与系统进行交互。

3.2 UEVENT机制

        "uevent" 是 Linux 系统中的一种事件通知机制,用于向用户空间发送有关内核和设备状态变化的通知。这种机制通常用于设备驱动程序、热插拔事件以及设备状态变化等场景,以便用户空间应用程序能够在这些事件发生时做出相应的响应。

3.3 JNI

        JNI,全称Java Native Interface,是Java编程语言的一种编程框架,用于实现Java代码与其他编程语言(如C、C++)进行交互的接口。JNI允许Java程序调用原生代码(native code),即由其他编程语言编写的代码,并且允许原生代码调用Java代码。通过JNI,Java程序可以访问底层系统功能、使用硬件设备、调用第三方库等。

3.4 EPOLL机制

        监听多个描述符的可读/可写状态。等待返回时携带了可读的描述符

3.5 INotify

        Linux 内核所提供的一种文件系统变化通知机制。可以监控文件系统的变化,如文件新建、删除、读写等

四、详细设计

通过屏幕的触摸事件,来分析IMS系统,相关如下

4.1 结构图

4.2 代码结构

层级 模块 描述 源码 编译产物
Framework InputManagerService xxx frameworks/base/services/core/java/ out/target/product/qssi/system/framework/services.jar
Native NativeInputManager xxx frameworks/base/services/core/jni/ out/target/product/qssi/system/lib64/libandroid_servers.so
Native Inputflinger xxx frameworks/native/services/inputflinger/ out/target/product/qssi/system/lib64/libinputflinger.so
Native Inputreader xxx frameworks/native/services/inputflinger/reader out/target/product/qssi/system/lib64/libinputreader.so
Native Inputdispatcher xxx frameworks/native/services/inputflinger/dispatcher/ (静态库)out/soong/.intermediates/frameworks/native/services/inputflinger/dispatcher/libinputdispatcher/android_arm64_armv8-a_static/libinputdispatcher.a
Native NativeInputEventReceiver xxx frameworks/base/core/jni/ out/target/product/qssi/system/lib64/libandroid_runtime
Native InputChannel xxx frameworks/native/libs/input/ out/target/product/qssi/system/lib64/libinput.so

4.3 InputManagerService模块

        InputManagerService是Android框架层一个非核心服务,主要是提供一个IMS输入系统启动的入口,同时对应用层提供业务相关接口。

4.3.1 IMS服务入口

        Android设备开机后,会启动system_server进程,InputManagerService服务(以下简称IMS)在该进程被唤起。

@frameworks\base\services\java\com\android\server\SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    ...
    t.traceBegin("StartInputManagerService");
    inputManager = new InputManagerService(context);//新建IMS实例
    t.traceEnd();
    ...
    t.traceBegin("StartInputManager");
    inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());//设置窗体事件监听
    inputManager.start();//启动IMS服务
    t.traceEnd();
    ...
}

4.3.2 IMS初始化

        此处做一些IMS相关的初始化操作,会调用nativeInit方法,获取一个NativeInputManager对象,类似于一个句柄。

@frameworks\base\services\core\java\com\android\server\input\InputManagerService.java
private static native long nativeInit(InputManagerService service,
        Context context, MessageQueue messageQueue);
public InputManagerService(Context context) {
    ...
    mStaticAssociations = loadStaticInputPortAssociations();
    mUseDevInputEventForAudioJack =
            context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
    Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
            + mUseDevInputEventForAudioJack);
    mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
    ...
}

4.3.3 IMS启动

        InputManagerService通过start方法启动,会调用nativeStart方法,该方法为Native方法

@frameworks\base\services\core\java\com\android\server\input\InputManagerService.java
private static native void nativeStart(long ptr);
public void start() {
    Slog.i(TAG, "Starting input manager");
    nativeStart(mPtr);

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

4.3.4 IMS消息监听

        该方法为Native的回调方法,用于上报IMS事件,如耳机插入事件等。

@frameworks\base\services\core\java\com\android\server\input\InputManagerService.java
// Native callback.
private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
    ...
    if ((switchMask & SW_LID_BIT) != 0) {
        final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
        mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
    }

    if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
        final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0);
        mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
    }

    if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
        mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
                    switchMask);
    }
    ...
}

4.4 NativeInputManager模块

        该模块为JNI模块,主要处理Java方法与c++方法映射关系,即IMS服务与InputFlinger模块的通信桥梁。

4.4.1 nativeInit初始化

(1)新建一个NativeInputManager对象,并将该对象返回给java层

@\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);
    ...
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

(2)创建InputManager管理类,主要用于管理Input事件分发、事件读取行为

@\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();
    ...
    mInputManager = new InputManager(this, this);
    defaultServiceManager()->addService(String16("inputflinger"),
            mInputManager, false);
}

4.4.2 nativeStart启动

获取上一个阶段创建NativeInputManager对象,并引用start启动该模块

@\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);
    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}

4.5 Inputflinger模块

input事件的管理类,数据传递类,也是输入系统native层核心的模块。
ps: 根据字典里的定义,flinger是指出轨的人。在SurfaceFlinger的例子中,它把可视数据扔给surface AudioFlinger把音频数据扔给适当的接收者。它们只是“可爱”的词…

用户评论