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

快速了解Android6.0系统触摸事件工作原理——InputManagerService 简介 Android的事件处理是在Linux基础上完成的。事件的最开始是由硬件监听到,然后通过硬件分到Kernel,Kernel在分到框架层,最后最后框架层把事件分布到应用程序的UI中。下面就以触摸事件为例进行分析。 当有事件发生的时候,硬件首先监听到,然后InputDriver起作用,而框架层的EventHub类一直在InputDriver中读事件;当EventHub类读到事件之后,Even... 阅读详情
AI摘要

本文深入分析Android Q/R/S 10/11/12版本中InputManagerService的启动流程,涵盖SystemServer中服务创建、JNI层NativeInputManager初始化、InputManager核心组件(InputReader、InputDispatcher、EventHub)构造与关联,以及基于epoll的/dev/input设备事件监听机制。重点阐述InputReader与InputDispatcher线程的初始化与启动逻辑,揭示Android输入事件处理框架底层架构。

1、SystemServer中InputManagerService创建与启动

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

    private void startOtherServices() {
 			//省略部分
            traceBeginAndSlog("StartInputManagerService");
            inputManager = new InputManagerService(context);
            traceEnd();
               traceBeginAndSlog("StartWindowManagerService");
            // WMS needs sensor service ready
            ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
            mSensorServiceStart = null;
            wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                    new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
            ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
            traceEnd();
 			//省略部分
 			   traceBeginAndSlog("StartInputManager");
            inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
            inputManager.start();//这里再调用start
            traceEnd();
           //省略部分
 }

这里以前讲过在SystemServer中会对系统中很多service进行启动,这里我们就发现有对InputManagerService进行对应的构造和添加

2、Native层面的InputManager启动

 public InputManagerService(Context context) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
		
     //省略部分
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());

     //省略部分
    }

这里InputManagerService构造方法中就是调用了nativeInit,这个方法是native方法
来看看对应的native方法:
base/services/core/jni/com_android_server_input_InputManagerService.cpp


static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == nullptr) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

这里主要就是构造了一个NativeInputManager:
base/services/core/jni/com_android_server_input_InputManagerService.cpp

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    //省略部分
    mInputManager = new InputManager(this, this);
    defaultServiceManager()->addService(String16("inputflinger"),
            mInputManager, false);
}

这里主要就是对我们InputManager进行构造,然后把它添加到了servicemanager,而且传递的两个参数都是NativeInputManager类本身
这里它的类结构其实是实现了几个接口方便InputManager里面传递和调用:
base/services/core/jni/com_android_server_input_InputManagerService.cpp

class NativeInputManager : public virtual RefBase,
    public virtual InputReaderPolicyInterface,
    public virtual InputDispatcherPolicyInterface,
    public virtual PointerControllerPolicyInterface 

那么接下来重点就分析我们的InputManager构造:
native/services/inputflinger/InputManager.cpp


InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mClassifier = new InputClassifier(mDispatcher);
    mReader = createInputReader(readerPolicy, mClassifier);
    initialize();
}

这里首先是进行了new InputDispatcher,再是把构造对象作为InputClassifier的构造参数,然后再是createInputReader,而且把InputClassifier对象也传递给了InputReader,看看createInputReader:

sp<InputReaderInterface> createInputReader(
        const sp<InputReaderPolicyInterface>& policy,
        const sp<InputListenerInterface>& listener) {
    return new InputReader(new EventHub(), policy, listener);
}

InputReader::InputReader(const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& policy,
        const sp<InputListenerInterface>& listener) :
        mContext(this), mEventHub(eventHub), mPolicy(policy),
        mNextSequenceNum(1), mGlobalMetaState(0), mGeneration(1),
        mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    mQueuedListener = new QueuedInputListener(listener);//listener是作为后面连接InputDispatcher纽带

    { // acquire lock
        AutoMutex _l(mLock);
//第一次执行时候,一般都是一些初始化的,还没获取到真正一些devices相关信息
        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    } // release lock
}

这里就是构造出了InputReader,而且传递了一个EventHub,也是立即构造的,整个input系统其实就是InputReader和InputDispatcher最为重要。而且二者其实也是间接相连的:
在这里插入图片描述

这样才方便后面InputReader读取加工好了数据就传递到InputDispatcher中,让InputDispatcher做下一步的传递工作。

再来看到有new一个EventHub,来看看它是干啥的:
native/services/inputflinger/EventHub.cpp

EventHub::EventHub(void) :
        mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
        mOpeningDevices(nullptr), mClosingDevices(nullptr),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false), mNeedToScanDevices(true),
        mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);

    mEpollFd = epoll_create1(EPOLL_CLOEXEC);
//省略部分
    mINotifyFd = inotify_init();
    mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
//省略部分

    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    eventItem.data.fd = mINotifyFd;
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
  //省略部分
    int wakeFds[2];
    result = pipe(wakeFds);
  
    mWakeReadPipeFd = wakeFds[0];
    mWakeWritePipeFd = wakeFds[1];

    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);

    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
  
    eventItem.data.fd = mWakeReadPipeFd;
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
   //省略部分
}

我相信看到这里的EventHub,大家应该会有非常非常熟悉的想到getevent源码,二者其实本质的功能都是一样的,这里使用的epoll来监听各个fd的变化,getevent中使用是poll。
这里大概可以看出EventHub职责就是来获取/dev/input/路径设备的,及对数据进行获取,和getevent职责一样,后面再使用到的时候再进行具体分析。

接下来继续分析InputManager构造的最后一个方法initialize:

void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

这里把mReaderThread和mDispatcherThread构造出来了,它们就是native层面的Thread对象,这里在入门课时候就已经讲解过了,但是这里只是创建了线程并没有启动,那么到这里构造部分就分析完成了,但是还没看到最关键的两个线程启动。其实这个启动是在文章一开始的SystemServer类中startOtherServices触发的,通过调用inputManager.start()方法:
base/services/core/java/com/android/server/input/InputManagerService.java

   public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);
   //省略部分
    }

这里调用是nativeStart方法,有到了我们的native层:
base/services/core/jni/com_android_server_input_InputManagerService.cpp

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:
native/services/inputflinger/InputManager.cpp

status_t InputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher",
            PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
   //省略部分
    result = mReaderThread->run("InputReader",
            PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
   //省略部分
    return OK;
}

这里其实就是干了把InputDispatcher和InputReader两个线程启动运行起来,那本节课就先分析到这里,目前就算把InputDispatcher和InputReader开始执行部分引出来了。

更多fw实战干货参考课程:https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw

[Android 13]Input系列--InputFlinger的启动 Android T。 阅读详情

相关推荐

0018-量化第五天:QMT—日内回转回测注释

日内做T算法框架

m0_68750710的博客 4145

Android 12 Input系统理解

android 12 Input系统流程理解与梳理

TSK_Amine的博客 2379

视觉辅助RIS波束追踪:用摄像头“看见”用户,实现毫秒级波束对准

在无线通信领域,波束成形技术是提升高频段信号覆盖与质量的核心手段,其原理是通过调整天线阵列的相位,使信号能量在特定方向相干叠加,形成高增益定向波束。这项技术的价值在于能有效克服高频信号路径损耗大、穿透性差的瓶颈,广泛应用于5G/6G、毫米波通信及室内定位等场景。然而,传统波束追踪依赖信道估计或波束扫描,存在训练开销大、实时性差的问题。本文聚焦于一种创新解决方案:将计算机视觉与可重构智能表面(RIS)相结合。通过摄像头直接感知用户位置,并利用RIS快速重构反射波束方向,实现了近乎零开销、毫秒级延迟的波束追踪,

weixin_33552698的博客 620

AndroidP/Q/R/S编译系统

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

zhzhangnews的博客 3万+

网络抓包实战:如何捕获与解析802.1Q VLAN标签报文

在网络通信中,数据包是信息传输的基本单元,而VLAN(虚拟局域网)技术通过在数据链路层插入802.1Q标签,实现了网络流量的逻辑隔离与高效管理。其核心原理是在标准以太网帧头中嵌入4字节的VLAN标识,使交换机能够根据VID(VLAN ID)进行精准转发。掌握VLAN报文的捕获与解析技术,对于网络故障排查、安全审计和性能优化具有重要价值,尤其在需要验证网络隔离策略或诊断Trunk链路异常时。本文聚焦于使用Wireshark工具,结合端口镜像等实操方法,详细演示如何抓取并解读携带802.1Q标签的原始报文,帮助

weixin_33417488的博客 383

Minecraft Forge模组开发入门:从环境搭建到事件监听实战

事件驱动编程是一种基于事件和事件监听器的软件架构模式,其核心原理是通过事件总线实现组件间的松耦合通信。在游戏开发领域,这种模式能够有效处理玩家交互、状态变更等异步操作,具有高度的灵活性和可扩展性。Java作为面向对象编程语言,通过注解和反射机制为事件驱动提供了天然支持。Minecraft模组开发正是事件驱动编程的典型应用场景,开发者可以利用Forge框架提供的事件总线监听游戏内各种行为。本文以Minecraft Forge模组开发为例,详细讲解如何通过Gradle构建工具搭建开发环境,并实现自定义方块注册和

culi3182的博客 395

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

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

深海流浪汉 1512

从Android到鸿蒙:UI框架迁移的实战指南与最佳实践

本文为Android开发者提供了将应用UI框架迁移至鸿蒙系统的实战指南。文章深入对比了Android命令式编程与鸿蒙ArkUI声明式编程的核心差异,详细讲解了从环境配置、布局迁移(如RecyclerView转List)、逻辑处理到多设备适配与性能优化的全流程最佳实践,帮助开发者高效完成迁移工作。

weixin_29208077的博客 434

Android12特性“不受信任的触摸事件被屏蔽”其他细节

Android12特性“不受信任的触摸事件被屏蔽”其他细节 android12-release Android 12关于Input触摸事件的行为变更 这篇介绍了input实际的拦截findTouchedWindowTargetsLocked “不受信任的触摸事件被屏蔽”相关属性 mBlockUntrustedTouchesMode 三种属性值:DISABLED不拦截;PERMISSIVE拦截判断最后没拦截;BLOCK拦截 frameworks\base\core\java\android\hardwar

许浑的博客 1万+

医疗影像配准与融合: 使用MATLAB对医学影像进行配准和融合,实现不同影像模态之间的对准和结构信息融合等

医疗影像配准与融合是医学影像处理的重要技术,它用于将不同来源、不同时间或不同模态的医学影像进行配准和融合,以获得更加完整、准确的患者解剖信息。基于MATLAB的医疗影像配准与融合可以帮助医生更准确地诊断疾病,制定更有效的治疗方案。医疗影像配准与融合是医学影像处理的关键技术,它对于提高医学影像诊断和治疗的准确性至关重要。MATLAB是一种功能强大的数学和科学计算软件,它可以为医疗影像配准与融合提供强大的工具和支持。

走向CTO的路上... 713

减法平均优化器(SABO)算法详解:从数学原理到工程应用

减法平均优化器(SABO)是一种基于数学概念的新型元启发式优化算法,由Trojanovský和Dehghani于2023年提出。该算法通过v-减法运算和平均值计算实现搜索优化,核心创新是采用目标函数值差异符号引导搜索方向。SABO具有参数少、结构简单、收敛快等特点,在高维复杂问题中表现优异。算法通过种群平均值保持多样性,利用符号函数确保搜索方向改进,自然平衡探索与开发。MATLAB实现显示其计算复杂度为O(N²·D),与主流群体智能算法相当。SABO不依赖生物或物理隐喻,数学基础坚实,在工程优化和机器学习领

qq_42212808的博客 165

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

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

learnframework的博客 2189

I2C 协议在 Camera Sensor 驱动中的典型配置方式与实战应用

在 Linux Camera 系统中,Sensor 与主控之间的控制信令几乎都依赖于 I2C 总线完成。I2C 协议不仅承载了 Sensor 初始化、模式切换、AE/AF 等关键功能的指令传输,也是构建 v4l2\_subdev 驱动框架的核心基础。本文将围绕 Sensor 驱动中的 I2C 通信机制展开分析,从设备树节点声明到驱动代码中的传输接口调用,结合主流平台工程实战经验,详解如何构建稳定、高效、可维护的 I2C 控制路径。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 1713

Android 12 Watchdog(3) monitor实现

文章托管在gitee上 Android Notes , 同步csdn 这一篇看一些系统模块的monitor实现。接下来看3个比较典型的场景: ActivityManagerService的monitor实现 InputManagerService的monitor实现,涉及native检查 Binder线程的monitor实现 Watchdog.Monitor定义如下,实现该接口的类,可以注册到Watchdog作为一个被监听的对象: public interface Monitor { voi.

pecuyu 1386

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

android中输入系统之内核到InputManagerService过程(源码)

这是一个系列的文章,今天先分析内核到ims的过程,以后有时间分析ims到wms以及从wms到viewRoot的过程。

陈德山 1336

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

[Android]-[Input]-个人对input子系统的理解_v2

Android input初步了解目录结构(基于安卓O) 1. open event device在里,这里应该是最接近kernel driver的部分了 frameworks/native/services/inputflinger

大王来巡山 352

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

新课程优惠获取请加入千里马老师qq群:422901085 上节课已经讲到了InputReaderThread和InputDispatchThread已经启动了,调用了对应的run方法,这里会导致对应的threadLoop方法执行: native/services/inputflinger/InputReaderBase.cpp bool InputReaderThread::threadLoop() { mReader->loopOnce(); return true; } 这里会调

liaosongmao1的专栏 319

android 事件管理器,Android输入管理InputManager之读一次事件的流程

流程图如下所示:读一次事件的流程.png读取线程InputReaderThread执行InputReader#loopOnce一次void InputReader::loopOnce() {int32_t oldGeneration;int32_t timeoutMillis;bool inputDevicesChanged = false;Vector inputDevices;....size...

weixin_27605509的博客 589

InputManager(1)--InputManager的创建和启动

文章目录InputManagerService和输入事件①. InputManagerService的创建1. `InputManagerService()`2. `nativeInit()`3. `NativeInputManager()`4. `InputManager()`5. InputReader 和 InputDispatcher 线程的创建:5.1.1. `createInputDispatcher()`5.1.2. `InputDispatcher()`5.2.1. `createInp

super_marie的博客 1575

android 4.2 input 流程分析,Android InputManager分析

本篇为鸡生蛋系列第二篇文章主要讲一下inputmanager相关的,即驱动把数据上报到用户空间后,用户空间到应用这么个流程,在上一遍讲内核的input子系统时候,我们采取的反向分析,即由驱动出发,最后到input core,input子系统架构这么个由点到面的分析方法,那分析inputmanager是否可采用这种方法如何呢?实际上,对于Android上层(Native framework/fram...

weixin_39845461的博客 400

Android R input (一) 之 InputManagerService 的建立

文章托管在gitee上 Android Notes , 同步csdn InputManagerService 介绍 InputManagerService是重要的系统服务,负责Android输入系统的管理,职责包括但不限于: 输入设备的管理 输入事件的加工m 输入事件的派发与反馈 输入事件的派发ANR的检测 常见的输入设备是触摸屏/按键,其他支持的设备还有键盘,鼠标等. 当有新输入设备可用时,Linux内核会在/dev/input/下创建对应的名称类似eventX(X>=0)的设备节点。当输入.

pecuyu 1799

Linux/Android——Input系统之frameworks层InputManagerService (六)

版权声明:免责声明: 本人在此发文(包括但不限于汉字、拼音、拉丁字母)均为随意敲击键盘所出,用于检验本人电脑键盘录入、屏幕显示的机械、光电性能,并不代表本人局部或全部同意、支持或者反对观点。如需要详查请直接与键盘生产厂商法人代表联系 .挖井挑水无水表,不会网购无快递 目录(?)[-] input服务的启动InputDispatcher分发InputReader读取

UPON的博客 751
上一篇: android多指控制协议详细解答
下一篇: android Input专题- Q/R/S 10/11/12 InputReader源码分析1
千里马学框架
博客等级 码龄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、付费专栏及课程。

余额充值