首页 > 其他分享 >Android 输入系统介绍

Android 输入系统介绍

时间:2023-11-24 17:37:57浏览次数:46  
标签:... args 介绍 frameworks 事件 services input Android 输入

目录

一、目的

        最近接触到了一个问题:耳机插入事件的由来,走读了下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把音频数据扔给适当的接收者。它们只是“可爱”的词…

标签:...,args,介绍,frameworks,事件,services,input,Android,输入
From: https://www.cnblogs.com/zhiqinlin/p/17854238.html

相关文章

  • 操作流程分享:HDMI输入SIL9293C配套NR-9 2AR-18的国产GOWIN开发板
     1.产品概述HDMI输入配套板是用于GOWINNR-9和2AR-18的开发板配套的HDMI输出板子。最大分辨率支持1920*1080P,60Hz刷新率,24位RGB色彩深度。主芯片是SIL9293C.2.操作流程1)断电,对接好开发板。保持引脚一致性。如下图所示,连接好显示器。NR-9在VIO2区,2AR......
  • Android ADB commands...
     //backbuttonadbshellinputkeyevent4//homebuttonadbshellinputkeyevent3//Searchbuttonadbshellinputkeyevent187//Stopcurrentrunningappadbshellamforce-stopcom.cas.myapp//com.cas.myappisappname//Startactivity, adbshellamstart......
  • el-input的form表单动态输入校验
    <el-form:inline="true"class="form_inline"label-width="120px":label-position="labelPosition"><divclass="el-form-itemasterisk-left"v-for="(field,index)inperson.kpiList&qu......
  • Android新手必学:Android的生命周期
    引言在Android开发中,了解和理解Android应用程序的生命周期是非常重要的。Android的生命周期指的是应用程序从创建到销毁的整个过程中,系统调用和管理组件的方法和回调。了解生命周期可以帮助我们更好地管理应用程序的状态和资源,提高应用程序的性能和用户体验。本文将介绍Android应用......
  • Android新手必学:Android中的动画介绍
    引言在现代移动应用开发中,动画是提升用户体验和吸引用户注意力的重要因素之一。Android平台提供了丰富的动画功能,使开发者能够创建出各种各样的动画效果。对于Android新手来说,了解和掌握Android中的动画是非常重要的一步。本文将介绍Android中的动画概念、类型和使用方法,帮助你快速......
  • Android新手必学:Fragment的用法
    引言Fragment是Android开发中一个重要的组件,它可以被认为是一个模块化的UI组件,用于构建灵活和可重用的界面。在Android应用程序中使用Fragment可以实现更好的UI组织、模块化开发和适配多屏幕等需求。本文将介绍Fragment的基本概念和用法,帮助Android新手开发者快速上手使用Fragment......
  • Android新手必学-ListView控件的使用
    简介在Android应用开发中,ListView是一种常用的UI控件,用于展示可滚动的列表视图。它可以用来展示大量数据,并且提供了灵活的布局和交互方式。本文将详细介绍ListView控件的使用方法,包括创建和配置ListView、自定义适配器以及处理列表项点击事件等。目录ListView介绍创建和配置ListVie......
  • Android数据流的狂欢:Channel与Flow
    在Android应用程序的开发中,处理异步数据流是一个常见的需求。为了更好地应对这些需求,Kotlin协程引入了Channel和Flow,它们提供了强大的工具来处理数据流,实现生产者-消费者模式,以及构建响应式应用程序。本文将深入探讨Channel和Flow的内部实现原理、高级使用技巧以及如何在......
  • Android新手必学-关于权限的申请
    引言在Android应用开发中,权限管理是一个至关重要的方面。Android系统为了保护用户的隐私和安全,对应用程序的访问权限进行了严格的控制。作为一名Android新手开发者,了解和正确处理权限是至关重要的。本文将介绍Android权限的概念、权限的分类以及如何在应用程序中正确申请和处理权限......
  • Android新手必学:关于多线程的知识
    引言在Android开发中,多线程编程是一项非常重要的技能。Android应用程序通常需要同时执行多个任务,如网络请求、文件读写、耗时计算等。如果在主线程中执行这些任务,会导致应用程序的界面卡顿,用户体验变差。因此,我们需要使用多线程来实现并发执行任务,提高应用程序的响应性能和用户体验......