Android源码笔记-输入事件(一)

          这一节主要了解一下Android输入事件源码,Android输入系统的工作原理概括来说,就是监控/dev/input/下的所有设备节点,当某个节点有数据可读时,将数据读出并进行一系列的加工,然后在所有的窗口中寻找合适的事件接收者,并派发给它。 整体含有几个关键因素:

Linux内核:接受输入设备的中断,并将原始事件的数据写入设备节点中。

设备节点:作为内核与IMS的桥梁,它将原始事件的数据暴露给用户空间,以便IMS可以从中读取事件。

EventHub:直接访问所有的设备节点。并且正如其名字所描述的,它通过一个名为getEvents()的函数将所有输入系统相关的待处理的底层事件返回给使用者。这些事件包括原始输入事件、设备节点的增删等。

InputReader,是IMS中的关键组件之一。它运行于一个独立的线程中,负责管理输入设备的列表与配置,以及进行输入事件的加工处理。它通过其线程循环不断地通过getEventsO)函数从EventHub 中将事件取出并进行处理。对于设备节点的增删事件,它会更新输入设备列表与配置。对于原始输入事件,InputReader对其进行翻译、组装、封装为包含更多信息、更具可读性的输人事件,然后交给 InputDispatcher 进行派发。

InputReaderPolicy:它为InputReader的事件加工处理提供一些策略配置,例如键盘布局信息等。

InputDispatcher:是IMS中的另一个关键组件。它也运行于一个独立的线程中。InputDispatcher中保管了来自WMS的所有窗口的信息,其收到来自InputReader的输入事件后,会在其保管的窗口中寻找合适的窗口,并将事件派发给此窗口。

InputDispatcherPolicy:它为InputDispatcher的派发过程提供策略控制。例如截取某些特定的输入事件用作特殊用途,或者阻止将某些事件派发给目标窗口。一个典型的例子就是HOME键被InputDispatcherPolicy截取到PhoneWindowManager中进行处理,并阻止窗口收到HOME键按下的事件。

WMS:虽说不是输入系统中的一员,但是它却对InputDispatcher的正常工作起到了至关重要的作用。当新建窗口时,WMS为新窗口和IMS创建了事件传递所用的通道。另外,WMS还将所有窗口的信息,包括窗口的可点击区域、焦点窗口等信息,实时地更新到IMS的InputDispatcher 中,使得InputDispatcher 可以正确地将事件派发到指定的窗口。

ViewRootImpl:对某些窗口,如壁纸窗口、SurfaceView的窗口来说,窗口就是输入事件派发的终点。而对其他的如Activity、对话框等使用了Android 控件系统的窗口来说,输入事件的终点是控件(View)。ViewRootImpl将窗口所接收的输人事件沿着控件树将事件派发给感兴趣的控件。

frameworks/base/services/java/com/android/server/SystemServer.javapublic static void main(String[] args) {new SystemServer().run();}private void run() {TimingsTraceAndSlog t = new TimingsTraceAndSlog();try {t.traceBegin("InitBeforeStartServices");// Record the process start information in sys props.SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime));SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START,mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);      // The system server should never make non-oneway callsBinder.setWarnOnBlocking(true);// The system server should always load safe labelsPackageItemInfo.forceSafeLabels();// Default to FULL within the system server.SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;// Deactivate SQLiteCompatibilityWalFlags until settings provider is initializedSQLiteCompatibilityWalFlags.init(null);// Here we go!Slog.i(TAG, "Entered the Android system server!");final long uptimeMillis = SystemClock.elapsedRealtime();EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);if (!mRuntimeRestart) {FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_INIT_START,uptimeMillis);}SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());// Mmmmmm... more memory!VMRuntime.getRuntime().clearGrowthLimit();// Some devices rely on runtime fingerprint generation, so make sure// we've defined it before booting further.Build.ensureFingerprintProperty();// Create the system service manager.mSystemServiceManager = new SystemServiceManager(mSystemContext);mSystemServiceManager.setStartInfo(mRuntimeRestart,mRuntimeStartElapsedTime, mRuntimeStartUptime);LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);// Prepare the thread pool for init tasks that can be parallelizedSystemServerInitThreadPool.start();// Attach JVMTI agent if this is a debuggable build and the system property is set....} finally {t.traceEnd();  // InitBeforeStartServices}// Setup the default WTF handlerRuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf);// Start services.try {t.traceBegin("StartServices");// 启动引导服务startBootstrapServices(t);// 启动核心服务startCoreServices(t);// 启动其他服务 startOtherServices(t);} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {t.traceEnd(); // StartServices}StrictMode.initVmDefaults(null);...// Diagnostic to ensure that the system is in a base healthy state. Done here as a common// non-zygote process.if (!VMRuntime.hasBootImageSpaces()) {Slog.wtf(TAG, "Runtime is not running with a boot image!");}// Loop forever.Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}private void startOtherServices(@NonNull TimingsTraceAndSlog t) {final Context context = mSystemContext;VibratorService vibrator = null;DynamicSystemService dynamicSystem = null;IStorageManager storageManager = null;NetworkManagementService networkManagement = null;IpSecService ipSecService = null;NetworkStatsService networkStats = null;NetworkPolicyManagerService networkPolicy = null;ConnectivityService connectivity = null;NsdService serviceDiscovery = null;WindowManagerService wm = null;SerialService serial = null;NetworkTimeUpdateService networkTimeUpdater = null;InputManagerService inputManager = null;TelephonyRegistry telephonyRegistry = null;ConsumerIrService consumerIr = null;MmsServiceBroker mmsService = null;HardwarePropertiesManagerService hardwarePropertiesService = null;try {t.traceBegin("StartInputManagerService");inputManager = new InputManagerService(context);wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());inputManager.start();		} catch (Throwable e) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting core service");throw e;}		} 
/frameworks/base/services/core/java/com/android/server/input/InputManagerService.javapublic void start() {Slog.i(TAG, "Starting input manager");nativeStart(mPtr);// Add ourself to the Watchdog monitors.Watchdog.getInstance().addMonitor(this);registerPointerSpeedSettingObserver();registerShowTouchesSettingObserver();registerAccessibilityLargePointerSettingObserver();registerLongPressTimeoutObserver();mContext.registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {updatePointerSpeedFromSettings();updateShowTouchesFromSettings();updateAccessibilityLargePointerFromSettings();updateDeepPressStatusFromSettings("user switched");}}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);updatePointerSpeedFromSettings();updateShowTouchesFromSettings();updateAccessibilityLargePointerFromSettings();updateDeepPressStatusFromSettings("just booted");}
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cppstatic 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.");}}inline sp<InputManager> getInputManager() const { return mInputManager; }

用reinterpret_cast操作符将jlong类型的ptr强制转换为原类型(NativeInputManager指针类型)。

 /frameworks/native/services/inputflinger/InputManager.cppstatus_t InputManager::start() {status_t result = mDispatcher->start();if (result) {ALOGE("Could not start InputDispatcher thread due to error %d.", result);return result;}result = mReader->start();if (result) {ALOGE("Could not start InputReader due to error %d.", result);mDispatcher->stop();return result;}return OK;
}
/frameworks/native/services/inputflinger/reader/InputReaderFactory.cppnamespace android {sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,const sp<InputListenerInterface>& listener) {return new InputReader(std::make_unique<EventHub>(), policy, listener);
}} // namespace android/frameworks/native/services/inputflinger/reader/InputReader.cppstatus_t InputReader::start() {if (mThread) {return ALREADY_EXISTS;}mThread = std::make_unique<InputThread>("InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });return OK;
}
/frameworks/native/services/inputflinger/InputThread.cppclass InputThreadImpl : public Thread {
public:explicit InputThreadImpl(std::function<void()> loop): Thread(/* canCallJava */ true), mThreadLoop(loop) {}~InputThreadImpl() {}private:std::function<void()> mThreadLoop;bool threadLoop() override {mThreadLoop();return true;}
};

InputManager的start函数运行了InputDispatcherThread和InputReaderThread线程;

InputDispatcher和InputReader是在哪创建的

/frameworks/native/services/inputflinger/InputManager.cppInputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {mDispatcher = createInputDispatcher(dispatcherPolicy);mClassifier = new InputClassifier(mDispatcher);mReader = createInputReader(readerPolicy, mClassifier);
}

可以看出InputDispatcher和InputReader是有关联的,InputDispatcher会作为一个参数传入到InputReader中;

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

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

相关文章

05 | Swoole 源码分析之 WebSocket 模块

首发原文链接&#xff1a;Swoole 源码分析之 WebSocket 模块 大家好&#xff0c;我是码农先森。 引言 WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它允许客户端和服务器之间进行实时数据传输。 与传统的 HTTP 请求-响应模型不同&#xff0c;WebSocket 可以保持…

Bash相关

Bash shell是Linux内核与用户之间的解释器程序 变量 自定义变量&#xff0c;名称可以用数字、字母、下划线、不能以数字开头&#xff0c;不能使用特殊符号&#xff0c;等号两边不能有空格 格式&#xff1a;变量名称值 环境变量&#xff0c;由系统提前定义好&#xff0c;使用…

node res.end返回json格式数据

使用 Node.js 内置 http 模块的createServer()方法创建一个新的HTTP服务器并返回json数据&#xff0c;代码如下&#xff1a; const http require(http);const hostname 127.0.0.1; const port 3000;const data [{ name: 测试1号, index: 0 },{ name: 测试2号, index: 1 },…

PhpWord导入试卷

规定word导入格式 1、[单选题][2024][一般]题目1 A.选项1 B.选项2 C.选项3 D.选项4 答案&#xff1a;D 试题图片&#xff08;上传多媒体图片&#xff09;&#xff1a; 分数&#xff1a;2 答案解析&#xff1a; 2、[多选题][2024][困难]题目2 A.选项1 B.选项2 C.选项3 D.选项4 E…

[计算机效率] 格式转换工具:格式工厂

3.14 格式转换工具&#xff1a;格式工厂 格式工厂是一款功能强大的多媒体格式转换软件&#xff0c;可以实现音频、视频、图片等多种格式的转换。它支持几乎所有类型的多媒体格式&#xff0c;包括视频、音频、图片、字幕等&#xff0c;可以轻松实现格式之间的转换&#xff0c;并…

分发饼干(C++ 贪心)

目录 题目需求 贪心算法思想 什么是贪心 贪心算法的使用 贪心算法的优缺点 代码实现 后言 题目需求 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&…

基本环境搭建指南

前端相关 Nodejs 官网下载&#xff1a;https://nodejs.cn/ 网盘下载&#xff1a;https://yun.mllt.cc/s/Rvtm 数据库相关 MySQL https://dev.mysql.com/downloads/mysql/5.7.html navcat https://navicat.com.cn/products redis 官网下载&#xff1a;https://redis.io/docs/ins…

python-文件操作常用功能-2

目录 列出子目录 获取文件属性 列出子目录 如果要列出子目录而不是文件&#xff0c;请使用下面的方法。现在展示如何使用 os.listdir() 和 os.path() : import osbasepath my_directoryfor entry in os.listdir(basepath):if os.path.isdir(os.path.join(basepath,entry)):…

手写红黑树【数据结构】

手写红黑树【数据结构】 前言版权推荐手写红黑树一、理论知识红黑树的特征增加删除 二、手写代码初始-树结点初始-红黑树初始-遍历初始-判断红黑树是否有效查找增加-1.父为黑&#xff0c;直接插入增加-2. 父叔为红&#xff0c;颜色调换增加-3. 父红叔黑&#xff0c;颜色调换&am…

C++ Primer 总结索引 | 第十二章:动态内存

1、到目前为止&#xff0c;我们编写的程序中 所使用的对象 都有着严格定义的生存期。全局对象 在程序启动时分配&#xff0c;在程序结束时 销毁。对于 局部自动对象&#xff0c;当我们进入 其定义所在的程序块时被创建&#xff0c;在 离开块时销毁。局部static对象 在第一次使用…

Qt_Note20_QML_自定义Grid控件与OpacityMask的使用

import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.12 import QtGraphicalEffects 1.14Window {visible: truewidth: 640height: 480title: qsTr("Hello World")// 自定义Grid控件与OpacityMask的使用Grid {id: gridwidth: 15height: 200co…

在线教育平台项目总结

一、业务流程 1.企业&#xff08;B&#xff09; 内容管理、媒资、缓存、消息、任务调度、搜索 2.个人&#xff08;C&#xff09; 搜索、缓存、订单、支付、学习 二、关键技术 1.缓存三兄弟&#xff1a; 缓存穿透&#xff0c;高并发请求过来之后&#xff0c;查询数据库中存…

升降梯人数识别摄像机

升降梯人数识别摄像机是一种智能监测设备&#xff0c;主要用于实时识别和计算升降梯内乘客的数量。通过搭载先进的图像识别技术和人工智能算法&#xff0c;该设备可以准确监测乘客进出数量&#xff0c;提供重要数据支持和信息反馈&#xff0c;帮助管理人员有效管理升降梯运行&a…

STM32学习和实践笔记(4): 分析和理解GPIO_InitTypeDef GPIO_InitStructure (a)

深入分析及学习一下上面这一段代码的构成与含义。 首先&#xff0c;这个GPIO_InitTypeDef GPIO_InitStructure;其实与int a 是完全类似的语法格式以及含义。 GPIO_InitStructure就相当于a这样一个变量。不过从这个变量的名字可以知道&#xff0c;这是一个用于GPIO初始化的结构…

界面控件DevExtreme JS ASP.NET Core 2024年度产品规划预览(一)

在本文中我们将介绍今年即将发布的v24.1附带的主要特性&#xff0c;这些特性既适用于DevExtreme JavaScript (Angular、React、Vue、jQuery)&#xff0c;也适用于基于DevExtreme的ASP.NET MVC/Core控件。 注意&#xff1a;本文中列出的功能和特性说明官方当前/预计的发展计划&a…

hcip实验4:gre mgre ppp综合实验

实验拓扑: 实验目的&#xff1a; 1.R5为ISP&#xff0c;只能进行IP地址配置&#xff0c;其所有地址均配为公有IP地址 2.R1和R5间使用PPP的PAP认证&#xff0c;R5为主认证方&#xff1b;R2与R5之间使用ppp的CHAP认证&#xff0c;R5为主认证方;R3与R5之间使用HDLC封装; 3.R1、R…

MQ消息队列详解以及MQ重复消费问题

MQ消息队列详解以及MQ重复消费问题 1、解耦2、异步调用3、流量削峰4、MQ重复消费问题&#xff0c;以及怎么解决&#xff1f;4.1、重复消费产生4.2、解决方法&#xff1a; https://blog.csdn.net/qq_44240587/article/details/104630567 核心的就是&#xff1a;解耦、异步、削锋…

当面试官问你插入排序算法,你敢说自己会吗?

算法学习的重要性 在程序员的世界里&#xff0c;算法就如同一座桥梁&#xff0c;连接着问题与解决方案&#xff0c;是实现优秀程序的关键。 掌握算法&#xff0c;就能够在面对各种问题时&#xff0c;找到最合适的解决方法&#xff0c;以最少的时间和空间&#xff0c;实现最优的…

解析基础设施即代码:重新定义云管理

由于现代架构、应用程序接口和相互关联的服务之间的互联性越来越强&#xff0c;云基础设施的复杂性也与日俱增。随着需要管理的云资源数量不断增加&#xff0c;企业开始采用基础设施即代码&#xff08;IaC&#xff09;来解决云应用的复杂性和相互依赖性问题。 IaC 提供各种工具…