android Input专题- Q/R/S 10/11/12 InputReader源码分析1

Android Input系统3 InputReader线程 一 InputReader起点 上一篇文章Android Input系统2 输入系统启动,介绍IMS服务的启动过程会创建两个native线程,分别是InputReader,InputDispatcher. 接下来从InputReader线程的执行过程从threadLoop为起点开始分析。 1.1 threadLoop InputReader.cpp bool InputReaderThread::threadLoop() { mReader->loopOnce(); return tr 阅读详情
AI摘要

这篇博客深入解析了Android系统中InputReaderThread如何获取设备事件,以及InputReader如何处理这些事件。主要关注EventHub的getEvents方法,该方法通过epoll_wait监听设备事件,并将输入事件转化为RawEvent。接着,InputReader的processEventsLocked方法处理这些事件,包括处理设备的添加、移除以及一系列的输入事件。通过对这两个关键方法的分析,理解Android输入系统的数据流转和处理流程。

新课程优惠获取请加入千里马老师qq群:422901085
上节课已经讲到了InputReaderThread和InputDispatchThread已经启动了,调用了对应的run方法,这里会导致对应的threadLoop方法执行:

native/services/inputflinger/InputReaderBase.cpp

bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}

这里会调用到mReader的loopOnce方法,这个方法将是非常关键的方法:

void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    std::vector<InputDeviceInfo> inputDevices;
 //省略部分
    //mEventHub获取数据
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

    { // acquire lock
        AutoMutex _l(mLock);
        mReaderIsAliveCondition.broadcast();

        if (count) {
            processEventsLocked(mEventBuffer, count);
        }

       //省略部分

        if (oldGeneration != mGeneration) {
            inputDevicesChanged = true;
            getInputDevicesLocked(inputDevices);
        }
    } // release lock

    // Send out a message that the describes the changed input devices.
    if (inputDevicesChanged) {
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }

//省略部分注释
    mQueuedListener->flush();
}

1. mEventHub中获取getEvents数据:

这里第一步就是调用了EventHub的getEvents方法:

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    ALOG_ASSERT(bufferSize >= 1);

    AutoMutex _l(mLock);

    struct input_event readBuffer[bufferSize];

    RawEvent* event = buffer;
    size_t capacity = bufferSize;
    bool awoken = false;
    for (;;) {
       //省略部分

        if (mNeedToScanDevices) {
            mNeedToScanDevices = false;
            scanDevicesLocked();
            mNeedToSendFinishedDeviceScan = true;
        }
//第一次一般遍历mOpeningDevices这个列表进行各个device获取变成DEVICE_ADDED
        while (mOpeningDevices != nullptr) {
            Device* device = mOpeningDevices;
            ALOGV("Reporting device opened: id=%d, name=%s\n",
                 device->id, device->path.c_str());
            mOpeningDevices = device->next;
            event->when = now;
            event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
            event->type = DEVICE_ADDED;
            event += 1;
            mNeedToSendFinishedDeviceScan = true;
            if (--capacity == 0) {
                break;
            }
        }
//第一次扫描完毕消息
        if (mNeedToSendFinishedDeviceScan) {
            mNeedToSendFinishedDeviceScan = false;
            event->when = now;
            event->type = FINISHED_DEVICE_SCAN;
            event += 1;
            if (--capacity == 0) {
                break;
            }
        }

        // Grab the next input event.
        bool deviceChanged = false;
        //第一次扫描时候没有消息,指导后面有触摸消息才会进入这里,这里是会由下面epoll监听消息触发
        while (mPendingEventIndex < mPendingEventCount) {
            const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
            if (eventItem.data.fd == mINotifyFd) {
                if (eventItem.events & EPOLLIN) {
                    mPendingINotify = true;
                } else {
                    ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
                }
                continue;
            }
//省略部分

            Device* device = getDeviceByFdLocked(eventItem.data.fd);

    //省略部分
            // This must be an input event
            if (eventItem.events & EPOLLIN) {
             //读取对应数据
                int32_t readSize = read(device->fd, readBuffer,
                        sizeof(struct input_event) * capacity);
                //省略部分
                } else {
                    int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
					//获取真实读取到的inputevent数据真实个数
                    size_t count = size_t(readSize) / sizeof(struct input_event);
                    //构造出对应的event
                    for (size_t i = 0; i < count; i++) {
                        struct input_event& iev = readBuffer[i];
                        event->when = processEventTimestamp(iev);
                        event->deviceId = deviceId;
                        event->type = iev.type;
                        event->code = iev.code;
                        event->value = iev.value;
                        event += 1;
                        capacity -= 1;
                    }
                 //省略部分
                }
            }
            //省略部分
        }
//省略部分
        if (event != buffer || awoken) {//第一次扫描就会进入这里进行返回
            break;
        }
//省略部分
//这里epoll在等待消息产生,产生消息EventItem都会放到mPendingEventItems中
        int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);

        if (pollResult < 0) {
          //省略部分
        } else {
        //这里对mPendingEventCount进行赋值真正有多少个事件产生
            // Some events occurred.
            mPendingEventCount = size_t(pollResult);
        }
    }

    // All done, return the number of events we read.
    return event - buffer;
}

这个方法相对还是比较复杂的,主要关心做了两部分的业务:
1、获取设备device各个信息,及监听设备变化
2、监听各个设备产生数据,并转换变成元数据RawEvent
最后会把一个个的RawEvent放入到传递进来的event这个链表里面即InputReader的

 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

中的mEventBuffer,所以后面就是用这个mEventBuffer进行对应数据读取等,当mEventBuffer数据有了之后那应该到了InputReader loopOnce的下一步了。

2. 处理数据processEventsLocked

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
        //首先判断type类型,如果已经开始触摸,那么这里type值肯定会小于FIRST_SYNTHETIC_EVENT
        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;
                }
                //一个触摸事件是由若干个RawEvent组成,比如触摸滑动,他有abs,syn等类型
                batchSize += 1;
            }
            //把一个系列事件完成后进行processEvents进行处理
            processEventsForDeviceLocked(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 happen
                break;
            }
        }
        count -= batchSize;
        rawEvent += batchSize;
    }
}

这里注释中对大部分已经进行讲解,最重要其实是processEventsForDeviceLocked

Android13 adb input 调试命令使用和源码解析 本章重点Android13 adb input 调试命令的使用和源码分析 通过命令来模拟用户在设备上的各种操作,从而进行测试、调试或其他目的。通过阅读源码来深入了解Android 13系统的输入事件管理机制。 阅读详情

相关推荐

AHB总线协议

1. 简介         AHB总线规范是AMBA总线规范的一部分,AMBA总线规范是ARM公司提出的总线规范,被大多数SoC设计采用,它规定了AHB (Advanced High-performance Bus)、ASB (Advanced System Bus)、APB (Advanced Peripheral Bus)。AHB用于高性能、高时钟频率的系统结构,典型的应用如ARM核与系统内

ivy_reny的专栏 8万+

Android Input系统1 输入系统概述

一 概述 当用户触摸屏幕或者按键操作,首次触发的是硬件驱动,驱动收到事件后,将该相应事件写入到输入设备节点, 这便产生了最原始的内核事件。接着,输入系统取出原始的输入事件,经过层层封装后成为 KeyEvent 或者 MotionEvent,最后交付给相应的目标窗口 (Window) 来消费该输入事件。可见,输入系统在整个输入事件处理过程中起到了承上启下的衔接作用。 二 Android输入事件模型 输入事件肯定要先捕获才能传给窗口,因此,首先应该有一个线程在不断的监听屏幕或其它输入端,一旦有触摸或其它输入事件

liuwg1226的专栏 5354

瑞芯微RK3576上手实测:8nm新U配6TOPS NPU,做AIoT项目选它还是RK3588/RK3568?

本文深度评测瑞芯微RK3576芯片在中高端AIoT项目中的表现,对比RK3588和RK3568的性能差异。RK3576采用8nm工艺,配备6TOPS NPU,在解码能力、AI推理效率和功耗控制方面表现均衡,是中端项目的黄金选择。实测数据显示其在多路视频解码和AI加速性能上优势明显,特别适合智能摄像头和工业HMI设备。

weixin_42627853的博客 717

AndroidP/Q/R/S编译系统

Android编译环境的初始化过程,在编译环境初始化完成后,我们就可以用m/mm/mmm/make命令编译源代码了。当然,这要求每一个模块都有一个Android.mk文件。Android.mk实际上是一个Makefile脚本,用来描述模块编译信息。Android编译系统通过整合Android.mk文件完成编译过程。 mmm命令的编译过程,需要依赖会make命令全部模块编译完成,下面使用编译mmm.........

zhzhangnews的博客 3万+

医药行业新零售项目数据分析报告——基于Excel的分析与可视化

不同平台客户支付金额用数字+百分比展示更直观。各大区支付金额分析较为粗浅,后续可加入不同大区人数、配送费等进行细分分析。图表略微单一,可采用组合图,运用两个及以上维度对数据进行分析。数据来源本项目数据来源于某机构的项目案例,以上分析内容均为本人原创,不涉嫌抄袭。原做项目,新平台首发。

2401_84213513的博客 1495

RK3576 USB3.0 DWC3控制器调试:PHY初始化失败排查指南

DWC3 是 Synopsys 公司推出的 USB3.0/3.1 控制器 IP,支持双角色(DRD)模式,可配置为 Host、Device 或 OTG。

小灰灰的博客 1177

Android源码分析 - InputManagerService与触摸事件

我们这里以触摸事件为例,梳理流程 - 点击屏幕 - InputManagerService的InputReader线程通过EventHub捕获输入事件 - 经过处理后将消息发给InputDispatcher线程 - InputDispatcher找到触摸的目标窗口,通过InputChannel的 socket将事件发送给客户端的主线程Looper - 主线程Looper通过socket的fd,找到对应的窗口,将事件交给这个window - 具体window下的View处理具体的事件。

深海流浪汉 1512

由于找不到mfc110u.dll,无法继续执行代码,重新安装程序可能会解决此问题的 解决方案

本文主要介绍了由于找不到mfc110.dll,无法继续执行代码的解决方案,希望能对使用Windows的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 5万+

InputReader源码分析

版本:android 13。

优快云NETVIP的博客 925

看懂 SAP S/4HANA 产品主数据里的 GTIN:一串号码背后的全球商品识别与业务协同

SAP S/4HANA中的GTIN管理是企业供应链运营的关键环节。本文深入解析GTIN的业务内涵及其在SAP系统中的实现方式:1) GTIN是全球通用的商品标识码,不同于企业内部物料编码;2) SAP主数据中GTIN与计量单位强绑定,需为不同包装层级维护独立GTIN;3) 同一产品可能因渠道、供应商差异存在多个GTIN;4) GTIN贯穿零售POS、仓储管理、EDI订单等核心业务流程;5) 通过典型案例说明错误维护GTIN将导致收银异常、仓库作业低效等运营问题。文章强调GTIN管理需结合包装层级、计量单位等

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1433

【虚幻引擎UE】UE5 阴影异常与优化

【虚幻引擎UE】UE5 阴影异常与优化解决方案合集

灵境引路人 3万+

【安卓12源码】Input子系统(1) - input启动流程

Android Input 体系中,大致有两种类型的事件:实体按键 key 事件,屏幕点击触摸事件。如果根据事件类型的不同我们还能细分为基础实体按键的 key(power,volume up/down,recents,back,home),实体键盘按键,屏幕点击 (多点,单点),屏幕滑动等等的事件。在 Android 整个 Input 体系中有三个格外重要的成员:Eventhub,InputReader,InputDispatcher。

mike_jun的博客 2588

AI上推荐 之 协同过滤

㐇

Miracle8070 1万+

android Input专题- Q/R/S 10/11/12 InputManager源码分析

1、SystemServer中InputManagerService创建与启动 base/services/java/com/android/server/SystemServer.java private void startOtherServices() { //省略部分 traceBeginAndSlog("StartInputManagerService"); inputManager = new InputManagerService

learnframework的博客 2973

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

千里马Android Framework-input系统专题blog目录集合

千里马Android Framework-input系统专题blog目录集合 这里将会列出视频课程中所有的可能用的相关资料集合blog链接

learnframework的博客 2189

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Android Input源码分析

bool InputDispatcherThread::threadLoop() { dispatchOnceInnerLocked(&nextWakeupTime); dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) { /*1. 记录到Trace,并调用PowerMa.

seiyaaa的专栏 285

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Android 12系统源码_输入系统(二)InputManagerService服务

结合Android12系统源码梳理InputManagerService服务的启动流程,梳理IMS模块的设计架构。

AfinalStone的专栏 1814

Input系统之InputDispatcher

这里新增加了 按键视角部分,以按键的流程来解读整个IMS的数据流走向的框架。新增的派发数据流程截图如下。

qq_42282862的博客 1330

【安卓13 源码】Input子系统(4)- InputReader 数据处理

/ up 的事件为 AMOTION_EVENT_ACTION_POINTER_UP,事件保存再 cookedPointerData.pointerCoords:走dispatchMotion 方法。类型B特有的,实际上,每个slot会和一个ID相对应,一个非负数的表示一次接触,-1表示这是一个无用的slot(或者理解为一次接触的结束)。根据事件获得相应的设备类型,然后将事件交给相应的设备处理,给触摸设备相关的类去处理。// 2-1-1)同步触摸事件 syncTouch,调用的是子类的方法。

mike_jun的博客 1663

Android 5.0输入系统分析之InputReader和InputDispatcher线程启动过程

Android 5.0输入系统分析之InputReader和InputDispatcher线程启动过程

100度多0点01度 838

Android11 InputReader分析

多指触摸类型InputReader线程情景分析

littleyards的博客 1498

Android 源码 输入系统之 InputReader

InputReaderThread 线程负责读取事件。InputReaderThread 启动后会执行 threadLoop 函数。threadLoop 函数返回 true,InputReaderThread 就会循环执行 threadLoop 函数。具体可以参见关于 Native Thread 实现一节《Android 源码 Native Thread 分析》。InputReaderThread(称为“ InputReader”)读取并预处理原始输入事件,应用策略,并将消息发布到由 InputDispat

洪伟的专栏 1111

Android 10.0 Input System 源码分析

##前言 这篇文章主要解决以下问题: 什么是Linux标准输入协议? Android Input System架构是怎样的? Android ANR产生的原理是什么?如何避免ANR? 如何调试Android Input System? 本文结构 1、功能介绍 2、总体设计 3、详细设计 4、开发调试 5、总结 6、资料 一、功能介绍 Linux 输入协议在 linux/input.h 内核头文...

jackingzheng的专栏 1549
上一篇: android Input专题- Q/R/S 10/11/12 InputManager源码分析
下一篇: android framework开发-Input中触摸圆点与触摸轨迹源码分析
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值