input系统之启动介绍
迪丽瓦拉
2025-05-28 14:53:06
0
IMS的整体架构diagram

请添加图片描述
输入事件的源头位于、dev/input下的设备节点,输入系统的终点是由WMS管理的某个窗口。Android输入系统的功能是读取设备节点中原始事件,加工封装后派发一个特定的窗口以及窗口控件,及扫描输入设备将设备封装到mDevices数组。

模块模块说明
linux 内核接受输入设备中断,将原始事件数据写入到设备节点
设备节点IMS可以从中读取事件
InputManagerService分为Java层和native层两部分,Java层负责与WMS的通信;Native层是InputReader和InputDispatcher两个输入系统关键组件的运行容器
EventHub直接访问所有的设备节点,通过一个名为getEvent()的函数将所有输入系统相关的处理底层事件返回给使用者
InputReader运行于独立线程,负责管理输入设备的列表和配置,以及进行输入事件的加工处理。通过线程循环不断地通过getEvent()函数从EventHub中将事件取出并进行处理。对于设备节点的增删事件,他会更新输入设备列表于配置。对于原始输入事件,InputReader对其进行翻译,组装封装包含更多的信息,然后交给InputDispatcher进行派发。
InputReaderPolicy为InputReader事件加工处理提供策略配置
InputDispatcherIMS的另一个组件。它也运行在一个独立线程中,InputDispatcher中保管了来自WMS所有窗口的信息,收到来自InputReader的输入事件后,会寻找合适的窗口,将事件派发给它。
InputDispatcherPolicy它为InputDispatcher的派发过程提供策略控制
WMS对InputDispatcher的正常工作起到了重要作用。新建窗口时,WMS为新窗口和IMS创建了事件传递所用的通道。另外,还将所有窗口的信息,包括窗口的可点击区域,焦点窗口等信息,实时更新到IMS的InputDispatcher中,使得InputDispatcher可以正确地将事件派发到指定窗口。
ViewRoot对于某些窗口,如壁纸窗口,SurfaceView的窗口来说,窗口即是输入事件派发的终点。而对于其他的Activity,对话框等使用了Android控件系统的窗口来说,输入事件的终点是控件(view)。ViewRootImpl将窗口所接受到的输入事件沿着控制树派发给View

内核将原始事件写入到设备节点中,InputReader不断地通过EventHub将原始事件取出来并加工成Android输入事件,交给InputDispatcher。InputDispatcher根据WMS提供的窗口信息将事件交给合适的窗口。窗口的ViewRootImpl对象再沿着控件树将事件派发给具体的控件。控件对其收到的事件作出响应,更新自己的画面、执行特定的动作。

IMS启动流程分析

Android的输入子系统是在InputManagerService启动的,而InputManagerService是在system_server中启动的。接下来从SystemServer的启动开始逐步分析:

//systemserver->startOtherServices
private void startOtherServices() {//...inputManager = new InputManagerService(context);//关键点1wm = WindowManagerService.main(context, inputManager,mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,!mFirstBoot, mOnlyCore);ServiceManager.addService(Context.WINDOW_SERVICE, wm);ServiceManager.addService(Context.INPUT_SERVICE, inputManager);inputManager.setWindowManagerCallbacks(wm.getInputMonitor());inputManager.start();//关键点2
}
InputManagerService
    public InputManagerService(Context context) {this.mContext = context;this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());mUseDevInputEventForAudioJack =context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="+ mUseDevInputEventForAudioJack);//调用nativeInit来执行C++层的初始化操作mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());LocalServices.addService(InputManagerInternal.class, new LocalService());}
com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz,jobject serviceObj, jobject contextObj, jobject messageQueueObj) {sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);if (messageQueue == NULL) {jniThrowRuntimeException(env, "MessageQueue is not initialized.");return 0;}//构造一个NativeInputManagera对象NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());im->incStrong(0);return reinterpret_cast(im);
}

这里创建一个NativeInputManager的实例,并将其作为返回值保存在InputMangerService的mPtr字段里,继续分析NativeInputManager的构造器。

NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp& looper) :mLooper(looper), mInteractive(true) {JNIEnv* env = jniEnv();mContextObj = env->NewGlobalRef(contextObj);mServiceObj = env->NewGlobalRef(serviceObj);{AutoMutex _l(mLock);mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;mLocked.pointerSpeed = 0;mLocked.pointerGesturesEnabled = true;mLocked.showTouches = false;}//构造一个EventHub对象,InputReaderPolicy,InputDispatcherPolicy,传递给InputManagersp eventHub = new EventHub();mInputManager = new InputManager(eventHub, this, this);
}

这里继续分析关键对象InputManager,代码如下:

InputManager::InputManager(const sp& eventHub,const sp& readerPolicy,const sp& dispatcherPolicy) {mDispatcher = new InputDispatcher(dispatcherPolicy);mReader = new InputReader(eventHub, readerPolicy, mDispatcher);initialize();
}

这里创建了一个InputReaderThread和InputDispatcherThread对象,前面构造器中创建InputReader是通过InputReaderThread来读取输入事件,而InputDispatcher实际通过InputDispatcherThread来发输入事件。
在这里插入图片描述
InputManager的创建过程分别为InputReader与InputDispatcher创建了线程,IMS的成员准备就绪。

InputManagerService线程启动分析

线程启动

inputManager.start();
---------------------------------------
public void start() {Slog.i(TAG, "Starting input manager");nativeStart(mPtr);//...
}
----------------------------------------
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {NativeInputManager* im = reinterpret_cast(ptr);status_t result = im->getInputManager()->start();
}
---------------------------------------
status_t InputManager::start() {status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);//...result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);//...return OK;
}

InputManager启动了一个InputReaderThread和InputDispatcherThread来读取和分发消息,调用run之后,会进入threadLoop函数。这里start()函数的功能就是启动这两个线程,使得InputReader于InputDispatcher开始工作。当两个线程启动后,InputReader在其线程循环中不断地从EventHub中读取输入事件,加工处理后将事件放入InputDispatcher的派发发队列中,InputDispatcher在线程循环中将派发队列中的事件取出,查找合适窗口,将事件写入。窗口事件接收线程的Looper从管道中将事件取出,交由事件处理函数进行事件响应。
请添加图片描述

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...