【安卓13 源码】Input子系统(3) - EventHub增加设备的流程
由前面的分析知道,在创建inputreader 线程的时候,会去循环执行 looponce 方法。主要的处理工作是:
- 通过 getEvents() 从 EventHub 获取未处理的事件,这些事件分为两类:一类是原始输入事 件即从设备节点中读取出的原始事件;一类是设备事件即输入设备可用性变化事件
- 通过 processEventsLocked() 对事件进行预处理
/frameworks/native/services/inputflinger/reader/InputReader.cpp
void InputReader::loopOnce() {int32_t oldGeneration;int32_t timeoutMillis;bool inputDevicesChanged = false;std::vector<InputDeviceInfo> inputDevices;{ // acquire lockstd::scoped_lock _l(mLock);oldGeneration = mGeneration;timeoutMillis = -1;uint32_t changes = mConfigurationChangesToRefresh;if (changes) {mConfigurationChangesToRefresh = 0;timeoutMillis = 0;refreshConfigurationLocked(changes);} else if (mNextTimeout != LLONG_MAX) {nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);}} // release lock// 1)首先去eventhub 中获取事件,缓存到 mEventBuffersize_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);{ // acquire lockstd::scoped_lock _l(mLock);mReaderIsAliveCondition.notify_all();if (count) {// 2)对 mEventBuffer 事件进行处理processEventsLocked(mEventBuffer, count);}
1)首先去eventhub 中获取事件,缓存到 mEventBuffer
/frameworks/native/services/inputflinger/reader/EventHub.cpp
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {ALOG_ASSERT(bufferSize >= 1);std::scoped_lock _l(mLock);。。。。
// 初始值 mNeedToScanDevices 是为true 的if (mNeedToScanDevices) {mNeedToScanDevices = false;
// 去扫描设备 scanDevicesLockedscanDevicesLocked();mNeedToSendFinishedDeviceScan = true;}
// 遍历所有的打开的设备mOpeningDeviceswhile (!mOpeningDevices.empty()) {
// 获取设备 Devicestd::unique_ptr<Device> device = std::move(*mOpeningDevices.rbegin());mOpeningDevices.pop_back();ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());event->when = now;event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;// 设置event事件类型是增加的DEVICE_ADDEDevent->type = DEVICE_ADDED;event += 1;// Try to find a matching video device by comparing device namesfor (auto it = mUnattachedVideoDevices.begin(); it != mUnattachedVideoDevices.end();it++) {std::unique_ptr<TouchVideoDevice>& videoDevice = *it;if (tryAddVideoDeviceLocked(*device, videoDevice)) {// videoDevice was transferred to 'device'it = mUnattachedVideoDevices.erase(it);break;}}// 然后将设备的id和设备保存到 mDevices 中auto [dev_it, inserted] = mDevices.insert_or_assign(device->id, std::move(device));
// 扫描设备 scanDevicesLocked
// 扫描设备,path 为:DEVICE_PATH = "/dev/input";
void EventHub::scanDevicesLocked() {status_t result = scanDirLocked(DEVICE_PATH);=======
status_t EventHub::scanDirLocked(const std::string& dirname) {for (const auto& entry : std::filesystem::directory_iterator(dirname)) {// 打开所有的设备openDeviceLocked(entry.path());}=======
void EventHub::openDeviceLocked(const std::string& devicePath) {ALOGV("Opening device: %s", devicePath.c_str());// 打开驱动设备int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);。。。。。// Allocate device. (The device object takes ownership of the fd at this point.)int32_t deviceId = mNextDeviceId++;
// 创建 Device 对象std::unique_ptr<Device> device = std::make_unique<Device>(fd, deviceId, devicePath, identifier);。。。。device->configureFd();// 增肌 device,会打印下列logALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=%s, ""configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",deviceId, fd, devicePath.c_str(), device->identifier.name.c_str(),device->classes.string().c_str(), device->configurationFile.c_str(),device->keyMap.keyLayoutFile.c_str(), device->keyMap.keyCharacterMapFile.c_str(),toString(mBuiltInKeyboardId == deviceId));// 将其增加到map 中addDeviceLocked(std::move(device));
}======
void EventHub::addDeviceLocked(std::unique_ptr<Device> device) {reportDeviceAddedForStatisticsLocked(device->identifier, device->classes);// 将其保存到已经打开的设备map 中mOpeningDevicesmOpeningDevices.push_back(std::move(device));
}
eventhub 将打开的设备保存到了 mOpeningDevices 中,在 InputReader 调用eventhub getevents的时候,去获取 mOpeningDevices先去eventhub 中获取事件,缓存到 mEventBuffer
2)对 mEventBuffer 事件进行处理
设置事件类型是增加的DEVICE_ADDED ,然后在inputreader 线程中处理 processEventsLocked
/frameworks/native/services/inputflinger/reader/InputReader.cpp
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {for (const RawEvent* rawEvent = rawEvents; count;) {int32_t type = rawEvent->type;size_t batchSize = 1;if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {int32_t deviceId = rawEvent->deviceId;while (batchSize < count) {if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT ||rawEvent[batchSize].deviceId != deviceId) {break;}batchSize += 1;}
#if DEBUG_RAW_EVENTSALOGD("BatchSize: %zu Count: %zu", batchSize, count);
#endifprocessEventsForDeviceLocked(deviceId, rawEvent, batchSize);} else {switch (rawEvent->type) {case EventHubInterface::DEVICE_ADDED:// 处理设备增加的消息addDeviceLocked(rawEvent->when, rawEvent->deviceId);break;case EventHubInterface::DEVICE_REMOVED:removeDeviceLocked(rawEvent->when, rawEvent->deviceId);break;case EventHubInterface::FINISHED_DEVICE_SCAN:handleConfigurationChangedLocked(rawEvent->when);break;default:ALOG_ASSERT(false); // can't happenbreak;}}count -= batchSize;rawEvent += batchSize;}
}
void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {if (mDevices.find(eventHubId) != mDevices.end()) {ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);return;}InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);// 依据设备的id 创建了 inputdevice 对象std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);device->configure(when, &mConfig, 0);device->reset(when);if (device->isIgnored()) {ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s' ""(ignored non-input device)",device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str());} else {// 会打印下列log 增加了设备ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s',sources=0x%08x",device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str(),device->getSources());}// 将id 和对应的device 增加到了 mDevices 中mDevices.emplace(eventHubId, device);// Add device to device to EventHub ids map.const auto mapIt = mDeviceToEventHubIdsMap.find(device);if (mapIt == mDeviceToEventHubIdsMap.end()) {std::vector<int32_t> ids = {eventHubId};mDeviceToEventHubIdsMap.emplace(device, ids);} else {mapIt->second.push_back(eventHubId);}bumpGenerationLocked();
// 依据设备的id 创建了 inputdevice 对象
std::shared_ptr<InputDevice> InputReader::createDeviceLocked(int32_t eventHubId, const InputDeviceIdentifier& identifier) {auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {return devicePair.second->getDescriptor().size() && identifier.descriptor.size() &&devicePair.second->getDescriptor() == identifier.descriptor;});std::shared_ptr<InputDevice> device;if (deviceIt != mDevices.end()) {device = deviceIt->second;} else {int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();// 创建了 InputDevice 对象device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),identifier);}// 调用方法 addEventHubDevicedevice->addEventHubDevice(eventHubId);return device;
}
// 调用方法 addEventHubDevice
/frameworks/native/services/inputflinger/reader/InputDevice.cpp
New device: id=2, fd=246, path='/dev/input/event4', name='adaptive_ts', classes=TOUCH | TOUCH_MT
void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {if (mDevices.find(eventHubId) != mDevices.end()) {return;}/ / 创建了 InputDeviceContext 对象,传入this 对象和 eventHubIdstd::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));Flags<InputDeviceClass> classes = contextPtr->getDeviceClasses();std::vector<std::unique_ptr<InputMapper>> mappers;// Check if we should skip populationif (!populateMappers) {mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});return;}// 然后依据不同的设备创建不同的 mapper:SwitchInputMapper
// 将其放到 mappers 中// Switch-like devices.if (classes.test(InputDeviceClass::SWITCH)) {mappers.push_back(std::make_unique<SwitchInputMapper>(*contextPtr));}// 下列是多点触控和单触控的// Touchscreens and touchpad devices.if (classes.test(InputDeviceClass::TOUCH_MT)) {mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));} else if (classes.test(InputDeviceClass::TOUCH)) {mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));}。。。。// insert the context into the devices set
// 最后将其保存到 mDevices 中mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
MultiTouchInputMapper 多点触控是继承了 TouchInputMapper
class MultiTouchInputMapper : public TouchInputMapper
/frameworks/native/services/inputflinger/reader/mapper/InputMapper.h
47 inline InputDeviceContext& getDeviceContext() { return mDeviceContext; }
48 inline const std::string getDeviceName() { return mDeviceContext.getName(); }
49 inline InputReaderContext* getContext() { return mDeviceContext.getContext(); }
50 inline InputReaderPolicyInterface* getPolicy() { return getContext()->getPolicy(); }// getContext 获取的值是 inputreader::contextimpl 对象,在获取getListener,则是
51 inline InputListenerInterface* getListener() { return getContext()->getListener(); }=======
/frameworks/native/services/inputflinger/reader/InputReader.cppInputListenerInterface* InputReader::ContextImpl::getListener() {// 获取的是 mQueuedListenerreturn mReader->mQueuedListener.get();
}
相关文章:
【安卓13 源码】Input子系统(3) - EventHub增加设备的流程
由前面的分析知道,在创建inputreader 线程的时候,会去循环执行 looponce 方法。主要的处理工作是: 通过 getEvents() 从 EventHub 获取未处理的事件,这些事件分为两类:一类是原始输入事 件即从设备节点中读取出的原始…...
基于JAVA+SpringBoot+Vue的网上商城系统的设计与实现
基于JAVASpringBootVue的网上商城系统的设计与实现 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末附源码下载链接…...
Mysql基础练习题 1729.求关注者的数量 (力扣)
编写解决方案,对于每一个用户,返回该用户的关注者数量。 #按 user_id 的顺序返回结果表 题目链接: https://leetcode.cn/problems/find-followers-count/description/ 建表插入语句: Create table If Not Exists Followers(us…...
【鸿蒙HarmonyOS NEXT】页面和自定义组件生命周期
【鸿蒙HarmonyOS NEXT】页面和自定义组件生命周期 一、环境说明二、页面和自定义组件生命周期三、示例代码加以说明四、小结 一、环境说明 DevEco Studio 版本: API版本:以12为主 二、页面和自定义组件生命周期 需要明确几个概念: 页面…...
Node.js Express 框架
Node.js Express 框架 介绍 Express 是一个快速、开放、极简的 Node.js Web 框架。它为构建 Web 应用程序和服务提供了一个强大的工具集,使得开发过程更加高效和便捷。Express 的设计哲学是提供一个最小的 API,让开发者可以轻松地构建自定义的 Web 应用程序。它被广泛用于构…...
生日贺卡录放音芯片,多段音频录音ic生产厂商,NVF04M-32minute
可以录音播放的生日贺卡与传统的纸质贺卡相比,它有着创意以及个性的特点,仅需少量的电子元器件,即可实现录音功能,搭配上文字,让声音存储在生日贺卡里,让贺卡也变得有温度,祝福我想亲口对TA说。…...
电影《西施新传》首映礼,九月金秋全国正式公映
2024年9月1日,古装谋略情感影片《西施新传》在无锡大世界影城中山路IMAX激光店举办首映礼。电影《西施新传》根据作家沈雅琴、笔名一蝶的同名小说改编,以家喻户晓四大美人之首的西施为主人公,讲述了春秋末期吴越战争的故事。越国败于吴国&…...
【H2O2|全栈】关于CSS(1)CSS基础(一)
目录 CSS基础知识 前言 准备工作 啥是CSS? 如何引用CSS? 选择器 通配符选择器 类名(class)选择器 id选择器 CSS解析顺序(优先级) 常见CSS标签(一) 字体属性 font-style…...
动态规划算法之背包问题详细解读(附带Java代码解读)
动态规划中的背包问题(Knapsack Problem)是经典问题之一,通常用来解决选择一组物品放入背包使得背包的价值最大化的问题。根据问题条件的不同,背包问题有很多种变体,如0-1背包问题、完全背包问题、多重背包问题等。这里…...
Vue3+TypeScript二次封装axios
安装如下 npm install axios 第一步:创建config配置文件,用于存放请求后端的ip地址,用于后期打包后便于修改ip地址。 注:typescript要求参数要有类型。(ES6 定义对象 属性 类型 修改的是属性的值) inte…...
华为 HCIP-Datacom H12-821 题库 (16)
有需要题库的可以加下方Q群 V群进行学习交流 1. OSPF 邻居关系建立出现故障,通过 display ospf error 命令来检查,输出结果如图所示,根据图中内容分析,邻居建立失败的原因可能是以下哪一项? A、Process ID 不一致 B、…...
【论文分享精炼版】 sNPU: Trusted Execution Environments on Integrated NPUs
今天在COMPASS分享了之前写的一个博客,做了进一步的提炼总结,大家可以看看原文~ 今天分享的论文《sNPU: Trusted Execution Environments on Integrated NPUs》来自2024年ISCA,共同一作为Erhu Feng以及Dahu Feng。并且, 这两位作…...
MyBatis 入门之动态 SQL
文章目录 一、什么是动态 SQL二、MyBatis 中的动态 SQL 标签三、动态 SQL 的使用示例四、总结 在 Java 开发中,MyBatis 是一个非常流行的持久层框架,它提供了强大的 SQL 映射功能和动态 SQL 支持。动态 SQL 可以根据不同的条件动态地生成 SQL 语句&#…...
软工大二学生待办事项:
该文章会常年更新!坚持! 2024.9.10 学习打包部署 记录睡眠 开始刷一个算法 巩固Git版本控制工具的使用 巩固利用Idea使用版本管理工具,SQl编写 抓紧时间了解公司营业执照 坚持到周末再打瓦!...
MongoDB延迟查询
在 MongoDB 中,查看副本集成员之间的副本延迟可以通过以下步骤进行: 使用 rs.status() 命令: 这个命令提供了副本集的详细状态信息,包括每个成员的延迟情况。在 MongoDB shell 中,你可以执行以下命令: rs.s…...
python如何获取html中的所有链接
在Python中,获取HTML页面中的所有链接通常可以通过使用第三方库如BeautifulSoup或lxml来完成。这里,我将提供一个使用BeautifulSoup库的示例,因为它简单易用且功能强大。 首先,你需要安装BeautifulSoup和requests库(如…...
79-java static修饰的类能不能被继承
Java中的类可以被final关键字修饰,表示这个类不能被继承。如果一个类被final修饰,那么这个类不能被继承,也就是说,final类不能被继承。 另一方面,static关键字可以用来修饰内部类,这样的内部类是静态内部类…...
MacOS wine中文乱码问题
安装wine 1、brew update 执行失败,提示安装如下 2、git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow 3、git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow 3、brew update 4、brew in…...
基于Springboot的鲜花销售网站的设计与实现
项目描述 这是一款基于Springboot的鲜花销售网站的系统 模块描述 鲜花销售系统 1、用户 登录 在线注册 浏览商品 鲜花搜索 订购商品 查询商品详情 水果分类查看 水果加购物车 下单结算 填写收货地址 2、管理员 登录 用户管理 商品管理 订单管理 账户管理 截图...
安卓玩机工具-----适合安卓机型的“搞机工具箱” 功能齐全 玩机推荐
搞机工具箱最新版是一款相当出色的电脑端手机工具箱软件,搞机工具箱正式版功能强劲,可以帮助用户不需要root就能够直接对手机进行调节,方便对手机进行更加全面的掌控,搞机工具箱便捷好用,只需要根据文字提示及自己的需…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
Java并发编程实战 Day 11:并发设计模式
【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...
