Android7 Input(一)Android Input服务初始化

本系列博客主要描述Android 7.1系统中输入管理服务InputManagerService的源码分析。

概述

本文主要描述了InputManagerService服务的初始化和启动,在Android7系统上InputManagerService服务的框架如下所示:

注:箭头的方向,并不能真实代表数据流向方向。

1、FrameWorks层:inputManagerService对外提供服务的模块;

2、JNI层:因为InputManagerService要去管理底层硬件输入设备,而在Android 7系统的所有与硬件相关的部分,都会涉及到JNI层。用C++代码去管理硬件设备;

3、Inputfliger: 是InputManager事件处理的核心事件,包括事件的获取和分发等;

4、kernel层,主要涉及的input输入驱动,并且将设备产生的事件通过inpu子系统上传给C++ inputflinger层;

5、硬件层,具体的输入设备,因为输入设备的类型很过,这里只是大概罗列出了嵌入式设备上常用的几个;

InputManagerService服务的初始化和启动比较简单,由SystemServer服务创建并拉起。

源码路径

本文描述中涉及的源码有:

frameworks/base/services/java/com/android/server/SystemServer.java

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

framesworks/native/services/inputflinger/inputManager.cpp

InputManagerServie服务的初始化

java层的服务初始化

在系统核心服务SystemServer初始化中,在启动其他服务startOtherService方法中,会创建InputManagerService服务。代码片段如下所示:

frameworks/base/services/java/com/android/server/SystemServer.java

 private void startOtherServices() {......traceBeginAndSlog("StartInputManagerService");/* 创建InputManagerService服务 */inputManager = new InputManagerService(context);Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);traceBeginAndSlog("StartWindowManagerService");wm = WindowManagerService.main(context, inputManager,mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,!mFirstBoot, mOnlyCore);ServiceManager.addService(Context.WINDOW_SERVICE, wm);/* 注册InputManagerServie服务  */ServiceManager.addService(Context.INPUT_SERVICE, inputManager);Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);if (!disableVrManager) {traceBeginAndSlog("StartVrManagerService");mSystemServiceManager.startService(VrManagerService.class);Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}mActivityManagerService.setWindowManager(wm);/* 设置InputManagerService的窗口回调接口 */inputManager.setWindowManagerCallbacks(wm.getInputMonitor());......}

1、在systemServer的服务中创建InputManagerService;

2、设置InputManagerService的窗口回调接口,因此最终的事件要传递给上层App的Windows窗口去处理;

创建InputManagerService并进入它的构造方法继续初始化,代码片段如下所示:

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

 public InputManagerService(Context context) {this.mContext = context;/* 创建Handler, 并使用displayThead现成的Looper */this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());mUseDevInputEventForAudioJack =context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="+ mUseDevInputEventForAudioJack);/* 调用InputManagerService服务的JNI方法nativeInit继续初始化 */mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());String doubleTouchGestureEnablePath = context.getResources().getString(R.string.config_doubleTouchGestureEnableFile);mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :new File(doubleTouchGestureEnablePath);LocalServices.addService(InputManagerInternal.class, new LocalService());}

在构造方法中:

1、创建InputManagerHander,并使用DisplayThread线程的Looper处理Handler消息;

2、调用InputManagerService服务的JNI方法nativeInit()方法继续初始化,并且将mHandler.getLooper().getQueue()队列传递给JNI层,在前面的初始化中InputManagerService自己的Handler使用了DisplayThread的Looper, 也就是说,在这个地方等同于将DisplayThread线程的消息队列传递给了InputManagerService的JNI层;

native层的初始化

根据前面的描述,InputManagerService服务的Java层调用nativeInit方法,继续初始化Native层,初始化代码片段,如下所示:

a、nativeInit()

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,jobject serviceObj, jobject contextObj, jobject messageQueueObj) {/* 将java层的messageQueue对象转化到对应的native层的messageQueue对象 */sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);if (messageQueue == NULL) {jniThrowRuntimeException(env, "MessageQueue is not initialized.");return 0;}/* 创建NativeInputManager输入管理 */NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());im->incStrong(0);/* 将native层的对象指针返回java层 */return reinterpret_cast<jlong>(im);
}

1、将java层的MessageQueue对象转化到它对应native层的C++对象,这个比较管理,涉及到后面的事件处理,暂时先不描述;

2、创建NativeInputManager对象;

3、返回JNI创建的C++对象的指针返回java层;

b、NativeInputManger的初始化

NativeInputManager的初始化,关键代码片段如下所示:

NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp<Looper>& looper) :mLooper(looper), mInteractive(true) {....../* 创建EventHub() 事件获取*/sp<EventHub> eventHub = new EventHub();mInputManager = new InputManager(eventHub, this, this);

1、创建EventHub()对象,该对象,主要就是获取输入事件(各种输入设备产生的事件和软件模拟产生的事件);

2、创建InputManager对象;

c、InputManager对象的初始化

framesworks/native/services/inputflinger/inputManager.cpp

InputManager对象初始化中如下所示:

   const sp<EventHubInterface>& eventHub,const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {/* 创建事件分发对象 */mDispatcher = new InputDispatcher(dispatcherPolicy);/* 创建事件获取对象 */mReader = new InputReader(eventHub, readerPolicy, mDispatcher);initialize();

1、创建事件分发对象;

2、创建事件获取对象;

3、创建事件分发和事件获取线程,如下所示:

void InputManager::initialize() {/* 创建事件获取线程 */mReaderThread = new InputReaderThread(mReader);/* 创建事件分发线程 */mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

至此,InputManagerService服务从java层的初始化过程到JNI层的初始化过程,描述完成.

InputManagerService服务启动

Java层的启动

InputManagerSerivice服务在Java层的启动,也是在SystemServer服务中完成。非常简单。执行代码片段如下所示:

frameworks/base/services/java/com/android/server/SystemServer.java

/* 设置InputManagerService的窗口回调接口 */inputManager.setWindowManagerCallbacks(wm.getInputMonitor());/* 启动InputManagerService服务 */inputManager.start();

然后调用InputManagerService中的start方法,关键执行代码片段如下:

public void start() {Slog.i(TAG, "Starting input manager");/* 调用JNI层nativeStart */nativeStart(mPtr);// Add ourself to the Watchdog monitors.Watchdog.getInstance().addMonitor(this);

1、直接调用jni层的nativeStart的接口;

Native层的启动

jni层的启动,关键代码片段如下所示:

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.");}
}

最终调用InputManager的start方法

framesworks/native/services/inputflinger/inputManager.cpp

status_t InputManager::start() {/* 开启分发线程 */status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);if (result) {ALOGE("Could not start InputDispatcher thread due to error %d.", result);return result;}/* 开启事件获取线程 */result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);if (result) {ALOGE("Could not start InputReader thread due to error %d.", result);mDispatcherThread->requestExit();return result;}return OK;
}

总结

1、InputManagerService服务的注册和启动都在SystemServer服务中完成;

2、InputManagerservice服务初始化过程中会在native层注册事件获取和分发的线程;

3、整个初始化过程中,从Java层到native层都传递了DisplayThread线程的Looper的MessageQueue;

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

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

相关文章

用于 RGB-D 显著目标检测的点感知交互和 CNN 诱导的细化网络(问题)

摘要 问题一&#xff1a;但在对自模态和跨模态的全局长距离依赖关系进行建模方面仍显不足。什么意思&#xff1f; 自模态&#xff08;Intra-modal&#xff09;全局依赖&#xff1a;在同一模态内&#xff0c;长距离像素之间的信息交互对于理解全局背景很重要&#xff0c;但 CN…

html5基于Canvas的经典打砖块游戏开发实践

基于Canvas的经典打砖块游戏开发实践 这里写目录标题 基于Canvas的经典打砖块游戏开发实践项目介绍技术栈核心功能实现1. 游戏初始化2. 游戏对象设计3. 碰撞检测系统4. 动画系统5. 用户界面设计 性能优化1. 渲染优化2. 内存管理 项目亮点技术难点突破项目总结 项目介绍 在这个…

MySQL外键约束下的索引删除难题:从报错到完美解决的实战指南

&#x1f6a8; MySQL外键约束下的索引删除难题&#xff1a;从报错到完美解决的实战指南 &#x1f525; 问题背景&#xff1a;一个看似简单的删除操作引发的连环坑 场景复现&#xff1a;某日接到需求&#xff0c;需删除 invite_codes 表中的冗余索引 FKnqn27fyjlgio5y60eieohi0…

使用 request 的 axios 状态码分析

request.interceptors.response.use(function(response){},function(error){})后端返回结果code400不经过response,直接跳到error。 当后端返回状态码为 400 时直接进入 error 回调而不经过 response 回调&#xff0c;这是因为 axios 默认会将状态码不在 200 - 299 范围内的响…

Rust嵌入式开发环境搭建指南(基于Stm32+Vscode)

Rust嵌入式开发环境搭建指南(基于Stm32+Vscode) 部分目录如下所示: 目录 简介Rust开发环境安装STM32开发工具链安装VSCode环境配置VSCode插件安装调试器配置项目创建与配置常见问题与解决方案简介 本文档旨在指导开发者如何搭建基于Rust语言的STM32嵌入式开发环境。相比传…

动态规划合集——动态规划基本原理

动态规划合集——动态规划基本原理 动态规划原理1258&#xff1a;【例9.2】数字金字塔 动态规划原理深度优先搜索记忆化搜索动态规划&#xff08;顺推&#xff09;动态规划原理题解分析 滚动数组优化动态规划&#xff08;逆推&#xff09; 动态规划原理 从数塔问题出发理解动态…

如何让节卡机器人精准对点?

如何让节卡机器人精准对点&#xff1f; JAKA Zu 软件主界面主要由功能栏、开关栏、菜单栏构成。 菜单栏&#xff1a;控制柜管理&#xff0c;机器人管理与软件管理组成。主要功能为对控制柜关机、APP 设置、机器人本体设 置、控制柜设置、连接机器人和机器人显示等功能。 开关…

自动化测试工具-Playwright介绍和快速实例

Playwright 是什么 Playwright 是由 Microsoft 开发的开源自动化测试工具,专为现代 Web 应用设计。它支持 Chromium、Firefox 和 WebKit 内核的浏览器,能够跨平台(Windows、macOS、Linux)运行,提供强大的浏览器自动化能力,适用于测试、爬虫和监控等场景。 Playwright的…

软考程序员考试知识点汇总

软考程序员考试&#xff08;初级资格&#xff09;主要考察计算机基础理论、编程能力及软件开发相关知识。以下是核心知识点总结及备考建议&#xff1a; 一、计算机基础 数制与编码 二进制、八进制、十进制、十六进制转换原码、反码、补码表示&#xff08;整数与浮点数&#xf…

实时视频分析的破局之道:蓝耘 MaaS 如何与海螺 AI 视频实现高效协同

一、蓝耘 MaaS 平台&#xff1a;AI 模型全生命周期管理的智能引擎 蓝耘 MaaS&#xff08;Model-as-a-Service&#xff09;平台是由蓝耘科技推出的 AI 模型全生命周期管理平台&#xff0c;专注于为企业和开发者提供从模型训练、推理到部署的一站式解决方案。依托云原生架构、高…

设计模式(行为型)-策略模式

目录 定义 类图 角色 角色详解 Strategy&#xff08;抽象策略类&#xff09;​ Context&#xff08;环境类 / 上下文类&#xff09;​ ConcreteStrategy&#xff08;具体策略类&#xff09;​ 优缺点 优点​ 缺点​ 使用场景 类行为差异场景​ 动态算法选…

【算法day14】三数之和

三数之和 https://leetcode.cn/problems/3sum/description/ 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。…

优化器/模型参数/超参数

参数&#xff08;Parameters&#xff09; vs. 超参数&#xff08;Hyperparameters&#xff09; 1.1 参数&#xff08;Parameters&#xff09; 定义&#xff1a;模型中需要学习的变量&#xff0c;例如神经网络中的权重&#xff08;Weight&#xff09;和偏置&#xff08;Bias&a…

10、STL中的unordered_map使用方法

一、了解 1、unordered_map(哈希) unordered_map是借用哈希表实现的关联容器。 访问键值对O&#xff08;1&#xff09;&#xff0c;最坏情况O&#xff08;n&#xff09;&#xff0c;例如哈希冲突严重时。【n是一个哈希桶的元素数量】 unordered_map特性 键值对存储&#xff…

C++ 头文件说明

如果一个程序足够大&#xff0c;代码功能很多&#xff0c;可以想象&#xff0c;不可能把代码写在一个cpp文件里。我们需要模块化&#xff0c;这样的好处很多&#xff0c;方便分工合作&#xff0c;可读性提高&#xff0c;调用也方便。 这个要怎么做呢&#xff1f; 很简单直接当…

Lambda 表达式的语法:

在 Java 中&#xff0c;Lambda 表达式&#xff08;也称为匿名方法&#xff09;是一种简洁的表示方法接口&#xff08;Functional Interface&#xff09;实现的方式。它是 Java 8 引入的特性&#xff0c;目的是提高代码的简洁性和可读性。 Lambda 表达式的语法&#xff1a; La…

C#零基础入门篇(18. 文件操作指南)

## 一、文件操作基础 在C#中&#xff0c;文件操作主要通过System.IO命名空间中的类来实现&#xff0c;例如File、FileStream、FileInfo等。 ## 二、常用文件操作方法 ### &#xff08;一&#xff09;文件读取 1. **使用File.ReadAllText方法读取文件内容为字符串** …

每日一题--内存池

内存池&#xff08;Memory Pool&#xff09;是一种高效的内存管理技术&#xff0c;通过预先分配并自主管理内存块&#xff0c;减少频繁申请/释放内存的系统开销&#xff0c;提升程序性能。它是高性能编程&#xff08;如游戏引擎、数据库、网络服务器&#xff09;中的核心优化手…

【Linux系统】Linux进程终止的N种方式

Linux系列 文章目录 Linux系列前言一、进程终止的概念二、进程终止的场景三、进程终止的实现3.1 程序退出码3.2 运行完毕结果正常3.3 运行完毕结果异常3.4 程序异常退出 总结 前言 进程终止是操作系统中&#xff0c;进程的一个重要阶段&#xff0c;他标志着进程生命周期的结束…

正则表达式引擎深入探讨

正则表达式引擎&#xff08;Regular Expression Engine&#xff09;是正则表达式得以“活起来”的核心。它是一个精密的软件组件&#xff0c;负责接收正则表达式和输入文本&#xff0c;解析模式并执行匹配或替换操作&#xff0c;最终输出结果——可能是简单的“是否匹配”&…