Android Input——输入系统介绍(一)

news2025/4/17 12:26:52

        Input 是 Android 系统中的一个重要模块,它是负责处理用户输入操作的核心组件。该系统从各种输入设备(如触摸屏、键盘、鼠标等)获取原始输入事件,并将其转换为 Android 应用可以理解和消费的 KeyEvent 或 MotionEvent 对象。

一、Input简介

        Input 系统对于提供流畅、灵敏和一致的用户交互体验至关重要,它需要在不同的设备、场景和应用中保证输入事件的正确性、及时性和安全性。

1、输入设备节点

        在 Android 系统中,输入设备通过 /dev/input/ 目录下的节点进行通信。每个输入设备都会被分配一个 event 节点,例如 event0, event1、event2 等。这些节点允许用户空间的应用程序与硬件交互,接收来自键盘、鼠标、触摸屏等设备的输入事件。

        可以通过 getevent -p 命令来查看所有连接的输入设备及其详细信息,包括支持的事件类型和值范围。也可以通过 /proc/bus/input/devices 文件查看类似信息。虽然具体的映射关系可能会根据设备制造商和配置有所不同,但常见的输入设备及其对应的event节点如下:

  • 触摸屏:通常对应于某个 eventX 节点,具体取决于设备上安装的其他输入设备数量。可以通过检查设备名称来识别,如 "Synaptics Touch" 或类似的标识符。
  • 键盘:同样会有一个 eventX 节点,对于外部键盘,它可能具有特定的供应商 ID 和产品 ID。
  • 鼠标/触控板:这些也会有自己的 eventX 节点,并且可能同时支持按键和绝对坐标事件。
  • 加速度计、陀螺仪等传感器:虽然严格来说不是 “输入” 设备,但在 Android 中它们也通过 input 子系统报告数据,因此会有相应的 eventX 节点。

二、关键类 

1、InputManagerService

        InputManagerService 是 Android 系统中负责管理输入设备和处理输入事件的核心服务之一。它主要工作在于初始化输入系统的各个组件、管理和监控输入设备,并为其他系统组件提供接口来查询和交互与输入相关的信息。

  • 初始化输入系统:InputManagerService 负责启动并初始化 InputReader 和 InputDispatcher 这两个关键组件。InputReader 从输入设备读取原始数据并解析成高层次的输入事件,而 InputDispatcher 则将这些事件分发给当前激活的应用程序或系统服务。
  • 设备管理:它能够检测新连接的输入设备(如触摸屏、键盘等),并通过 InputReader 加载相应的驱动程序和配置。同时,它也能识别设备断开的情况,提供 API 让其他系统组件可以查询已连接的输入设备列表及其属性(例如支持的按键类型、触控特性等)。
  • 策略制定:InputManagerService 还负责实现一些高级的输入策略,比如屏幕旋转时如何调整输入坐标,或者在多窗口模式下如何正确地将输入事件分发到正确的应用界面。
  • 与其他系统服务协作:与 WindowManager 紧密合作,确保输入事件被准确地发送到当前聚焦的窗口或视图。支持无障碍服务(Accessibility Services),允许这些服务监听或修改输入事件以辅助有特殊需求的用户。
  • 安全性和权限控制:管理对输入设备访问的安全性,确保只有授权的应用程序才能接收特定类型的输入事件。

2、EventHub

        在 Android 输入系统中,EventHub 是一个非常关键的组件,它位于输入系统的底层,负责直接与 Linux 内核提供的输入设备节点(如 /dev/input/eventX)进行交互。EventHub 从这些设备节点读取原始输入事件,并将它们传递给更高层的组件,例如 InputReader,以便进一步处理和分发。

主要职责

  • 设备管理:EventHub 负责扫描 /dev/input 目录下的所有输入设备,并为每个设备打开相应的 event 节点。它可以检测到新设备的添加或现有设备的移除,并通知上层组件(如 InputManagerService)有关这些变化的信息。
  • 事件读取:一旦打开了设备节点,EventHub 会持续监听来自这些设备的输入事件。使用非阻塞 I/O 操作高效地读取事件数据,确保即使在高负载情况下也能保持良好的响应性。
  • 事件封装与转发:将从设备节点读取到的原始输入事件封装成 RawEvent 对象。这些 RawEvent 对象随后被传递给 InputReader,后者负责解析这些事件并生成高层次的输入事件(如 MotionEvent 或 KeyEvent),然后由 InputDispatcher 进行分发。
  • 设备信息查询:提供接口让其他组件能够查询特定输入设备的详细信息,包括支持的事件类型、设备名称等。

工作流程

  • 初始化阶段:当 InputManagerService 启动时,它会创建一个 EventHub 实例。EventHub 初始化过程中会打开所有的输入设备节点,并准备接收事件。
  • 事件循环:EventHub 进入一个持续运行的循环,在这个循环中不断地检查是否有新的输入事件可用。如果有事件到达,则读取并将它们封装成 RawEvent 对象,然后通知 InputReader 有新的事件需要处理。
  • 设备变更处理:如果检测到有新的输入设备连接或现有的设备断开,EventHub 会通知 InputManagerService,从而允许系统动态调整对新设备的支持或移除旧设备的引用。 

        因此,EventHub 提供了与底层硬件交互的基础,确保了各种输入设备产生的事件能够被正确地捕获、解析并最终传递给应用程序。 

3、InputReader

        在 Android 输入系统中,InputReader 是一个核心组件,负责从底层硬件读取原始输入事件,如通过调用 EventHub 的接口,管理设备的添加与删除,并进行事件的加工处理。其内部会不断的通过 EventHub 的 getEvents 轮询驱动的事件,并最终将事件发送给 InputDispatcher 进行派发。并将这些事件解析为更高层次的事件类型(如触摸事件 MotionEvent 和按键事件 KeyEvent),以便上层的应用程序或服务能够理解和处理这些输入。

主要职责

  • 事件解析:从 EventHub 接收原始输入事件(通过读取 /dev/input/eventX 节点获取)。解析这些原始事件为高层次的输入事件类型,例如:触摸屏输入 -> MotionEvent、键盘输入 -> KeyEvent、鼠标或其他指针设备输入 -> MotionEvent 等。
  • 设备支持:支持多种类型的输入设备,包括但不限于触摸屏、键盘、鼠标等。根据设备的不同特性,正确地解释和转换输入数据。例如,触摸屏可能需要特别处理多点触控或多手势操作。
  • 状态管理:维护当前的输入状态,比如跟踪触摸点的位置、按键的状态等。处理输入事件的时间戳,确保事件按正确的顺序被分发。
  • 与 InputDispatcher 协作:将解析后的事件传递给InputDispatcher,由它决定如何将这些事件分发给前台应用程序或系统服务进行处理。

工作流程

  • 初始化阶段:当 InputManagerService 启动时,它会创建一个 InputReader 实例。InputReader 初始化过程中会准备读取来自所有连接的输入设备的数据。
  • 事件循环:InputReader 进入一个持续运行的循环,在这个循环中不断地从 EventHub 获取新的原始输入事件。对于每个获取到的事件,InputReader 都会根据事件类型和来源设备对其进行解析。
  • 事件分发:解析完成后,InputReader 生成相应的高层次事件对象(如 MotionEvent 或 KeyEvent)。这些事件随后被传递给 InputDispatcher,后者根据当前的焦点窗口和其他因素决定哪个应用或服务应该接收这些事件。 

        总之,InputReader 主要负责将来自各种输入设备的原始事件转换为应用程序可以直接使用的高层次事件。 

4、InputDispatcher

        InputDispatcher 是 Android 输入系统中的一个关键组件,它负责接收由 InputReader 解析出来的高层次输入事件(如触摸事件 MotionEvent 和按键事件 KeyEvent),并将这些事件分发到当前活动的应用程序或系统服务中进行处理。InputDispatcher 确保了用户交互能够被正确且高效地传递给前台应用或适当的后台服务。

主要职责

  • 事件分发:接收来自 InputReader 的输入事件,并根据当前的焦点窗口和视图层次结构将事件分发给正确的应用程序或系统服务。处理多任务环境下的事件分发,确保即使在多窗口或多应用切换的情况下也能准确地将事件发送到正确的接收者。
  • 策略实施:实施一系列策略来决定如何处理特定类型的输入事件。例如,处理屏幕旋转时的坐标转换、管理输入法(IME)与应用之间的交互等。支持无障碍服务(Accessibility Services),允许这些服务监听或修改输入事件以辅助有特殊需求的用户。
  • 同步与异步处理:通过使用同步屏障(Synchronous Barrier)机制来确保某些关键输入事件(如触摸事件)在适当的时间点被处理,避免因其他高优先级任务导致的延迟。提供异步事件处理能力,使得一些非关键的输入事件可以在不影响用户体验的情况下稍后处理。
  • 状态跟踪:维护输入通道的状态信息,包括当前激活的窗口、视图层级关系以及各个输入设备的状态等。监控输入设备的变化(如设备添加或移除),并相应地调整事件分发策略。

工作流程

  • 初始化阶段:当 InputManagerService 启动时,会创建一个 InputDispatcher 实例。初始化过程中,InputDispatcher 会准备接收来自 InputReader 的输入事件,并设置必要的回调接口用于事件分发。
  • 事件循环:InputDispatcher 进入一个持续运行的循环,在这个循环中等待新的输入事件到来。每当接收到一个新的输入事件时,InputDispatcher 会基于当前的窗口焦点和视图层次结构确定哪个应用或服务应该接收该事件。
  • 事件分发:根据确定的目标应用或服务,InputDispatcher 将事件通过 InputChannel 发送到相应的接收者。如果目标应用正在处理其他高优先级任务,InputDispatcher 可能会选择暂时缓存事件,直到应用准备好接收为止。 

        InputDispatcher 主要是确保了用户的输入能够被正确且及时地传递给前台应用或适当的后台服务。 

5、WindowManagerService

        WindowManagerService(简称 WMS)是 Android 系统中的核心服务之一,负责管理系统中所有的窗口。它管理着窗口的创建、销毁、布局、显示顺序以及输入事件的分发等任务。WMS 与 InputDispatcher 和 InputReader 密切合作,确保用户交互能够被正确地传递给相应的应用程序或系统服务。

主要职责

  • 窗口管理:负责管理所有窗口的生命周期,包括窗口的添加、删除和更新。维护窗口的层级结构,决定哪些窗口应该在前面显示,哪些应该在后面。
  • 布局与绘制:计算每个窗口的大小和位置,并告知 SurfaceFlinger 如何合成这些窗口以生成最终的屏幕图像。处理多窗口模式(如分屏模式),调整各应用窗口的布局以适应不同的显示需求。
  • 输入事件分发:与 InputDispatcher 协同工作,确定哪个窗口应该接收特定的输入事件(如触摸或按键事件)。根据当前窗口的焦点状态和视图层次结构,将输入事件准确地分发到正确的应用或服务。
  • 屏幕方向与动画:管理屏幕的方向变化,并协调相关窗口的重新布局和重绘。支持窗口转换动画,提升用户体验。
  • 多显示器支持:在支持多显示器的设备上,WMS 可以将不同窗口分配到不同的显示器上显示。

工作流程

    • 初始化阶段:当 Android 系统启动时,SystemServer 进程会启动 WMS。初始化过程中,WMS 会准备接收来自客户端(如 AMS)的窗口请求,并设置必要的回调接口用于处理这些请求。
    • 窗口操作:应用程序通过调用 WindowManager 的 API 来请求创建、更新或删除窗口。
    • WMS 接收到这些请求后,根据当前的窗口状态和布局规则进行相应的处理,并通知 SurfaceFlinger 更新显示内容。
    • 输入事件处理:输入事件首先由 InputReader 解析为高层次的事件类型,然后传递给 InputDispatcher。InputDispatcher 使用 WMS 提供的信息来决定哪个窗口应接收该事件,并通过窗口关联的 InputChannel 将事件发送给目标应用。
    • 屏幕方向与动画:当检测到设备旋转或其他需要改变屏幕方向的情况时,WMS 会协调所有受影响的窗口进行重新布局,并触发相应的动画效果。

            WMS 仅管理着系统中所有窗口的生命周期和布局,还负责确保用户交互能够被正确地传递给前台应用或适当的后台服务。WMS 在每次新建窗口时,都会将窗口信息更新到 InputDispatcher 中,这样 InputDispatcher 才能找到对应的窗口。

    6、ViewRootImpl

            ViewRootImpl 是 Android 系统中连接 WindowManager 和 View 层次结构的关键组件。它负责管理视图树的测量、布局、绘制过程,并处理输入事件的接收和分发。作为每个窗口与系统服务交互的桥梁,ViewRootImpl 在 Android 应用的 UI 渲染和用户交互方面扮演着至关重要的角色。

    主要职责

    • UI 渲染:负责视图树的测量(measure)、布局(layout)和绘制(draw)流程。通过调用 performTraversals() 方法来触发这些过程,确保视图能够正确地显示在屏幕上。
    • 输入事件处理:接收来自 InputDispatcher 的输入事件(如触摸或按键事件),并通过 dispatchInputEvent() 方法将这些事件分发给适当的视图进行处理。支持事件预处理(如手势识别)和后处理(如滚动、缩放等)。
    • 与 WMS 交互:作为应用端与 WMS 通信的接口,负责向 WMS 注册窗口,并接收有关窗口状态变化的通知(如屏幕旋转、尺寸变化等)。处理窗口属性的更新请求,如调整大小、位置或透明度等。
    • 动画支持:支持视图层次结构中的动画效果,包括属性动画、过渡动画等。协调视图的重绘以确保动画流畅运行。
    • 硬件加速:如果启用了硬件加速,ViewRootImpl 将使用 OpenGL ES 来渲染视图,从而提高性能和视觉效果。

    工作流程 

    • 初始化阶段:当一个新的窗口被创建时,系统会为该窗口创建一个 ViewRootImpl 实例。初始化过程中,ViewRootImpl 会设置与之关联的 DecorView(顶级视图容器),并准备开始处理视图的生命周期事件。
    • 视图绘制:ViewRootImpl 调用 performTraversals() 方法来启动视图的测量、布局和绘制流程。这个方法会在需要时递归遍历整个视图树,确保每个视图都被正确地测量和布置。
    • 输入事件处理:输入事件首先由 InputReader 解析,然后通过 InputDispatcher 分发到正确的 ViewRootImpl 实例。ViewRootImpl 使用 WindowInputEventReceiver 来接收这些事件,并通过 dispatchInputEvent() 方法将其传递给相应的视图进行处理。
    • 与 WMS 交互:当应用程序请求更改窗口属性时,ViewRootImpl 会与 WMS 通信,请求相应的变更。同样,当 WMS 发送有关窗口状态变化的通知时,ViewRootImpl 会相应地更新其内部状态,并通知相关视图进行必要的调整。

            ViewRootImpl 是 Android 应用程序中连接视图层次结构与系统服务的核心组件,负责管理视图的渲染和输入事件的处理。

    总结

            Android 输入系统是一个复杂但高效的设计,旨在处理来自各种输入设备(如触摸屏、键盘等)的用户交互,并将这些交互转换为应用程序可以理解和响应的形式。

    • EventHub:输入系统的最底层,直接与硬件通信,监听和读取输入设备的原始事件。
    • InputReader:从 EventHub 获取原始输入事件,对其进行解析,转化为更高层次的事件,以便上层应用或服务能够理解。
    • InputDispatcher:接收由 InputReader 转换后的高层次输入事件,并基于当前窗口焦点状态,通过 InputChannel 将事件分发到正确的应用程序或服务中。
    • IMS:管理着 EventHub、InputReader 和 InputDispatcher 的生命周期,同时也提供了对外的接口,使得其他系统组件可以查询输入设备的信息。
    • WMS:负责管理窗口的层级结构和布局,确定哪个窗口应该接收到输入事件,并将这些信息传递给 InputDispatcher,以便准确地分发事件。
    • ViewRootImpl:是每个窗口的根视图实现类,它不仅负责视图的测量、布局和绘制,还通过 InputChannel:接收来自 InputDispatcher 的输入事件,并将这些事件进一步分发给具体的视图组件进行处理。

            因此,在 Android 输入系统中,EventHub 担任了与硬件交互的角色,而 InputReader 则负责将这些原始数据解析成可理解的事件类型。InputDispatcher 根据 WMS 提供的信息,将这些事件分发给合适的窗口。IMS 作为一个管理者,确保整个输入流程的顺利进行。最后,ViewRootImpl 在每个窗口内扮演着重要角色,负责视图的具体渲染和事件处理,确保用户交互能够被正确地解释和响应。这些组件紧密合作,共同构成了一个强大且灵活的输入系统,支持多种类型的输入设备和复杂的用户界面需求。 

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2331105.html

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

    相关文章

    20250408-报错:pre_state = state同更新现象

    项目场景: 基于强化学习解决组合优化问题 问题描述 # POMO Rolloutstate, reward, done self.env.pre_step()# next_state statewith autocast():while not done:# 执行动作并获取新状态和奖励selected, prob self.model(state)# 更新状态:因为self.env.step(s…

    如何在服务器里部署辅助域

    辅助域(Additional Domain Controller,ADC)是指在现有的Active Directory(活动目录)架构中,新增一个或多个域控制器以提高目录服务的可用性和可靠性。以下是辅助域的定义、功能和应用场景的详细说明&#x…

    GNSS有源天线和无源天线

    区别 需要外部供电的就是有源天线,不需要外部供电的是无源天线。 无源天线 一般就是一个陶瓷片、金属片等,结构简单,成本低廉,占用空间及体积小,适合于强调紧凑型空间的导航类产品。 不需要供电,跟设备直…

    欧税通香港分公司办公室正式乔迁至海港城!

    3月20日,欧税通香港分公司办公室正式乔迁至香港油尖旺区的核心商业区海港城!左手挽着内地市场,右手牵起国际航道——这波乔迁选址操作堪称“地理课代表”! 乔迁仪式秒变行业大联欢!感谢亚马逊合规团队、亚马逊云、阿里国际站、Wayfair、coupang、美客多…

    ETPNav:基于演进拓扑规划的连续环境视觉语言导航模型

    1、现有工作的缺陷: 最近,出现了一种基于模块化航路点的方法的新兴趋势,该方法将复杂任务分为航路点生成、子目标规划和导航控制: (1)在每个决策循环中,代理使用预训练的网络来预测附近的几个…

    Spring Cloud LoadBalancer负载均衡+算法切换

    目录 介绍核心功能负载均衡启动两个支付服务订单模块引入依赖LoadBalanced 注解启动订单服务测试结果 负载均衡算法切换总结 介绍 Spring Cloud LoadBalancer 是 Spring Cloud 提供的客户端负载均衡解决方案,提供更现代化的 API 和更好的 Spring 生态系统集成。它支…

    游戏引擎学习第210天

    回顾并为今天的工作做准备 今天我们,进行一些编码工作。这部分的编码内容对那些对代码架构感兴趣的人非常有帮助,我认为今天的编码内容会很有教育意义,尤其是在展示一些代码转化的过程中,希望大家能够从中获得一些启发。 接下来…

    UML类图综合实验三补档

    1.使用简单工厂模式模拟女娲(Nvwa)造人(Person),如果传入参数“M”,则返回一个Man对象,如果传入参数“W”,则返回一个Woman对象,用Java语言实现该场景。现需要增加一个新的Robot类,如果传入参数“R”&#…

    WinForm真入门(11)——ComboBox控件详解

    WinForm中 ComboBox 控件详解‌ ComboBox 是 WinForms 中一个集文本框与下拉列表于一体的控件,支持用户从预定义选项中选择或直接输入内容。以下从核心属性、事件、使用场景到高级技巧的全面解析: 一、ComboBox 核心属性‌ 属性说明示例‌Items‌下拉…

    DeepSeek底层揭秘——《推理时Scaling方法》技术对比浅析

    4月初,DeepSeek 提交到 arXiv 上的最新论文正在 AI 社区逐渐升温。 笔者尝试对比了“关于推理时Scaling”与现有技术,粗浅分析如下: 与LoRA的对比 区别: 应用场景:LoRA是一种参数高效微调方法,主要用于在…

    Android Coli 3 ImageView load two suit Bitmap thumb and formal,Kotlin(四)

    Android Coli 3 ImageView load two suit Bitmap thumb and formal,Kotlin(四) 对 Android Coli 3 ImageView load two suit Bitmap thumb and formal,Kotlin(三)-CSDN博客 进行完善,注意完善 …

    Adam优化器研究综述

    摘要 Adam优化器(Adaptive Moment Estimation)是一种广泛应用于深度学习的优化算法,通过自适应学习率加速梯度下降过程。本文从Adam的定义、算法原理、优势与局限性、应用场景及变体等方面进行调研,结合学术文献和实践经验&#x…

    在 macOS 上连接 PostgreSQL 数据库(pgAdmin、DBeaver)

    在 macOS 上连接 PostgreSQL 数据库 pgAdmin 官方提供的图形化管理工具,支持 macOS。 下载地址:https://www.pgadmin.org/ pgAdmin 4 是对 pgAdmin 的完全重写,使用 Python、ReactJs 和 Javascript 构建。一个用 Electron 编写的桌面运行时…

    2018年真题

    数学基础 一、 (共4分)用逻辑符号表达下列语句(论域为包含一切事物的集合) 1、(2分)集合A的任一元素的元素都是A的元素 经过对图片文字的识别与逻辑分析,结果如下: 符号定义&…

    Efficient Burst Raw Denoising:稳定噪声方差和分频率降噪

    Efficient Burst Raw Denoising with Stabilization and Multi-Frequency Denoising Network Burst Raw Denoising必要性Burst Raw Image Denoising流程Main Contributions具体方法介绍集成noise priorCMOS sensor 噪声建模噪声变换(Variance stabilization&#xf…

    mapbox进阶,使用本地dem数据,加载hillshade山体阴影图层

    👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️hillshade 山体阴影图层 api1.3.1 ☘️…

    【C++】Stack Queue 仿函数

    📝前言: 这篇文章我们来讲讲STL中的stack和queue。因为前面我们已经有了string、vector和list的学习基础,所以这篇文章主要关注一些stack和queue的细节问题,以及了解一下deque(缝合怪)和priority_queue &am…

    代码随想录_单调栈

    代码随想录_单调栈 739.每日温度 739. 每日温度 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,…

    BoostSearch搜索引擎项目 —— 测试用例设计 + web自动化测试代码

    web自动化代码: https://gitee.com/chicken-c/boost-search/tree/master/AutoTest

    【Ansible自动化运维】一、初步了解,开启自动化运维之旅

    在当今数字化时代,随着企业 IT 基础设施规模的不断扩大,传统的手工运维方式逐渐显得力不从心。自动化运维技术应运而生,其中 Ansible 凭借其简洁易用、功能强大的特点,成为众多运维工程师和开发人员的首选工具。本篇文章将从基础概…