Android InputChannel连接

InputChannel是InputDispatcher 和应用程序 (InputTarget) 的通讯桥梁,InputDispatcher 通知应用程序有输入事件,通过InputChannel中的socket进行通信。

连接InputDispatcher和窗口

WinodwManagerService:addwindow: WMS 添加窗口时,会创建一对 InputChannel,其中一个保存在 WindowState 中,并注册给 IMS,它是服务端,另一个则通过传出参数 outInputChannel 交给调用者,是客户端

1.服务端连接的建立

addwindow 函数中,有以下三项工作:

通过 WindowState.setInputChannel 函数保存服务端的 InputChannel

通过 IMS.registerInputChannel 将 InputChannel 注册到 IMS

通过 InputMonitor.updateInputWindowsLw 将所有窗口的信息更新到 IMS

2.窗口端连接的建立

当窗口端通过 addwindow 函数获取 InputChannel,便会使用它创建一个 InputEventReceiver 对象,可以接收来自InputChannel 的输入事件,触发 onInputEvent 回调

InputEventRecevier 如何工作?将 InputChannel 的可读事件注册到 Looper,然后在事件到来时从 InputChannel 中读取 InputMessage,并翻译成 InputEvent,然后回调 InputEventReceiver 的 onInputEvent

详细调用栈如下: 

@frameworks/base/core/java/android/view/ViewRootImpl.java
setViewinputChannel = new InputChannel();
@frameworks/base/services/core/java/com/android/server/wm/Session.javamWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes, mDisplay.getDisplayId(), userId, inputChannel
@frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java    Service.addWindow(this, window, attrs, viewVisibility, displayId, userId, requestedVisibilities, outInputChannel,    //WinodwManagerService:addwindow
@frameworks/base/services/core/java/com/android/server/wm/WindowState.javawin.openInputChannel(outInputChannel);
@frameworks/base/services/core/java/com/android/server/input/InputManagerService.java            mInputChannel = mWmService.mInputManager.createInputChannel(name);
@frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp                nativeCreateInputChannel(mPtr, name);NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);base::Result<std::unique_ptr<InputChannel>> inputChannel = im->createInputChannel(env, name);
@frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp                        mInputManager->getDispatcher()->createInputChannel(name);
@frameworks/native/libs/input/InputTransport.cppstatus_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)std::string serverChannelName = name + " (server)";outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);std::string clientChannelName = name + " (client)";outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);
@frameworks/native/services/inputflinger/dispatcher/Connection.cppsp<Connection> connection = new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);inputChannel(inputChannel),inputPublisher(inputChannel),std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback, this, std::placeholders::_1, token);mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);mInputChannel.copyTo(outInputChannel);  //复制给outInputChannelif (focusChanged) { displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus, false /*updateInputWindows*/);
@frameworks/base/services/core/java/com/android/server/wm/InputMonitor.javadisplayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);scheduleUpdateInputWindows();mHandler.post(mUpdateInputWindows);run()mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);updateInputFocusRequest(mRecentsAnimationInputConsumer);requestFocus(recentsAnimationInputConsumer.mWindowHandle.token, recentsAnimationInputConsumer.mName);
@frameworks/base/core/java/android/view/SurfaceControl.javamInputTransaction.setFocusedWindow(mInputFocus, windowName, mDisplayId);     nativeSetFocusedWindow(mNativeObject, token,  windowName, null /* focusedToken */, null /* focusedWindowName */, displayId);
@frameworks/native/libs/gui/SurfaceComposerClient.cpp                                            transaction->setFocusedWindow(request);mInputWindowCommands.focusRequests.push_back(request);
@frameworks/native/services/surfaceflinger/SurfaceFlinger.cppSurfaceFlinger::handleMessageTransactionif (getTransactionFlags(eTransactionFlushNeeded)) { flushTransactionQueues();}applyTransactionState(transaction.states,  transaction.displays, transaction.inputWindowCommands,transactionFlags |= addInputWindowCommands(inputWindowCommands);
@frameworks/native/libs/gui/LayerState.cpp                                                                    bool hasChanges = mInputWindowCommands.merge(inputWindowCommands);focusRequests.insert(focusRequests.end(), std::make_move_iterator(other.focusRequests.begin()),SurfaceFlinger::onMessageInvalidateupdateInputFlinger();
@frameworks/native/services/inputflinger/InputManager.cpp                                                                                    for (const auto& focusRequest : mInputWindowCommands.focusRequests) { mInputFlinger->setFocusedWindow(focusRequest);}mDispatcher->setFocusedWindow(request);
@frameworks/base/core/jni/android_view_SurfaceControl.cpp                            mInputEventReceiver = new WindowInputEventReceiver(inputChannel, Looper.myLooper());
@frameworks/base/core/java/android/view/InputEventReceiver.javasuper(inputChannel, looper);
@frameworks/base/core/jni/android_view_InputEventReceiver.cppmReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this), inputChannel, mMessageQueue);sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env, receiverWeak, inputChannel, messageQueue);status_t status = receiver->initialize();setFdEvents(ALOOPER_EVENT_INPUT);mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);// Set up the input pipeline.mSyntheticInputStage = new SyntheticInputStage();InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage, "aq:native-post-ime:" + counterSuffix);InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);InputStage imeStage = new ImeInputStage(earlyPostImeStage,  "aq:ime:" + counterSuffix);InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage, "aq:native-pre-ime:" + counterSuffix);mFirstInputStage = nativePreImeStage;mFirstPostImeInputStage = earlyPostImeStage;//InputDispatcher向InputChannel使用socket写入输入事件,触发InputEventReceiver调用来接收输入事件
@frameworks/base/core/jni/android_view_InputEventReceiver.cpp
NativeInputEventReceiver::handleEventNativeInputEventReceiver::consumeEvents(env, false /*consumeBatches*/, -1, nullptr)
@frameworks/native/libs/input/InputTransport.cppmInputConsumer.consume(&mInputEventFactory, consumeBatches, frameTime, &seq, &inputEvent);status_t result = mChannel->receiveMessage(&mMsg);nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT);   //从socket中读输入事件case InputMessage::Type::FOCUS: {initializeFocusEvent(focusEvent, &mMsg);case InputMessage::Type::MOTION: {initializeMotionEvent(motionEvent, &mMsg);//构造java的event事件case AINPUT_EVENT_TYPE_FOCUS: { env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.onFocusEvent, jboolean(focusEvent->getHasFocus()), jboolean(focusEvent->getInTouchMode()));
@frameworks/base/core/java/android/view/ViewRootImpl.javaonFocusEventwindowFocusChanged(hasFocus, inTouchMode);msg.what = MSG_WINDOW_FOCUS_CHANGED;mHandler.sendMessage(msg);case MSG_WINDOW_FOCUS_CHANGED: { handleWindowFocusChanged(); }                                case AINPUT_EVENT_TYPE_MOTION: {inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);if (inputEventObj) {  env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
@frameworks/base/core/java/android/view/InputEventReceiver.java    dispatchInputEvent
@frameworks/base/core/java/android/view/ViewRootImpl.javaonInputEvent(event);enqueueInputEvent(event, this, 0, true);if (processImmediately) { doProcessInputEvents(); }deliverInputEvent(q);  //在deliverInputEvent函数中做输入事件的实际分发stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;  //这里开始选择 责任链的入口,具体请看InputStage的处理流程stage.deliver(q);  //这里主要调用InputStage的deliver方法进行分发,InputStage代表了输入事件的处理阶段,使用责任链模式设计模式。result = onProcess(q);NativePreImeInputStage::onProcess

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

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

相关文章

互联网场景下人脸服务基线方案总结

1.简介 1.1目的 在过去的一段时间里&#xff0c;因为听见业务对人脸服务方案的需求&#xff0c;针对网络视频中关键人物定位的检索任务&#xff0c;完成了基于互联网场景的人脸基线服务的构建。本文档是对当前基线服务以后之后解决方案的优化进行总结。 1.2范围 本文档描述的人…

c++读取文件时出现中文乱码

原因&#xff1a;UTF-8格式不支持汉字编码 解决&#xff1a;改成ANSI&#xff0c;因为ANSI编码支持汉字编码

Python学习路线图(2024最新版)

这是我最开始学Python时的一套学习路线&#xff0c;从入门到上手。&#xff08;不敢说精通&#xff0c;哈哈~&#xff09; 一、Python基础知识、变量、数据类型 二、Python条件结构、循环结构 三、Python函数 四、字符串 五、列表与元组 六、字典与集合 最后再送给大家一套免费…

FFmpeg开发笔记(四十二)使用ZLMediaKit开启SRT视频直播服务

《FFmpeg开发实战&#xff1a;从零基础到短视频上线》一书在第10章介绍了轻量级流媒体服务器MediaMTX&#xff0c;通过该工具可以测试RTSP/RTMP等流媒体协议的推拉流。不过MediaMTX的功能实在是太简单了&#xff0c;无法应用于真实直播的生产环境&#xff0c;真正能用于生产环境…

KVB App:中国制造业数据支撑澳元,分析师预计挑战0.6750阻力

摘要&#xff1a; 中国6月财新制造业PMI上升至51.8&#xff0c;反映出制造业生产经营活动的持续扩张。这一数据不仅高于预期&#xff0c;还为澳元提供了强有力的支撑。技术分析显示&#xff0c;澳元/美元可能会在短期内挑战0.6750阻力水平。 中国制造业数据解析 6月&#xff0…

python异常、模块与包

目录 了解异常异常的捕获方法python模块python包安装第三方包 了解异常 什么是异常 当检测到一个错误时&#xff0c;python解释器就无法继续执行了&#xff0c;反而出现了一些错误的提示&#xff0c;这就是所谓的“异常”&#xff0c;也就是我们常说的BUG bug单词的诞生 早期…

Python入门-基本数据类型-常用的字符串方式

1.字符串大小转换 方法说明sname.title()将字符串中的每个单词首字母大写sname.lower()将字符串中所有字母转为小写sname.upper()将字符串中所有字母转为大写 2.判断字符内容 方法说明sname.isupper()当字符串中所有字符都是大写时返回True&#xff0c;否则返回Falsesname.i…

Python tkinter: 开发一个目标检测GUI小程序

程序提供了一个用户友好的界面&#xff0c;允许用户选择图片或文件夹&#xff0c;使用行人检测模型进行处理&#xff0c;并在GUI中显示检测结果。用户可以通过点击画布上的检测结果来获取更多信息&#xff0c;并使用键盘快捷键来浏览不同的图片。 一. 基本功能介绍 界面布局&am…

智芯开发板----时钟的使用

一、开发板时钟概述 介绍 Z20K11xM 的时钟结构&#xff0c;分布以及各个外设时钟源的选择。SCC 模块用于选择系统时钟&#xff0c;产生 core clock、bus clock 和 flash clock&#xff0c;分 别用于驱动 core 及高速外设、普通外设和 flash。PARCC 模块用于单独设置 每个外设的…

中霖教育怎么样?税务师通过率高吗?

中霖教育怎么样?税务师通过率高吗? 我们在税务师考试培训方面有着不错的成绩&#xff0c;这都是老师与学员共同努力的结果。 采用小班教学模式&#xff0c;确保每位学员都能得到足够的关注和指导&#xff0c;在学习过程中针对学员的薄弱环节进行专项突破。 因为大部分学员…

spring @Autowire注解作用

终于有人把Autowired注解讲清楚了&#xff0c;赞&#xff01;&#xff01;&#xff01;_autowired-CSDN博客

【C语言】常见的字符串函数

©作者:末央&#xff06; ©系列:C语言初阶(适合小白入门) ©说明:以凡人之笔墨&#xff0c;书写未来之大梦 目录 strlen函数模拟实现 strstr子串查找函数模拟实现 strtok字符串分割 strlen函数 strlen函数是一个用于求字符串长度的库函数。它的参数是被求长度的字…

【爱上C++】详解string类2:模拟实现、深浅拷贝

在上一篇文章中我们介绍了string类的基本使用&#xff0c;本篇文章我们将讲解string类一些常用的模拟实现&#xff0c;其中有很多细小的知识点值得我们深入学习。Let’s go&#xff01; 文章目录 类声明默认成员函数构造函数析构函数拷贝构造函数深浅拷贝问题传统写法现代写法…

泛型的使用(<T>)

文章目录 前言一、泛型是什么&#xff1f;二、泛型的使用 1.定义泛型类2.泛型的常规用法总结 前言 强制类型转换存在一定隐患&#xff0c;如数据丢失、内存溢出、运行时错误、程序逻辑错误等。所以提供了泛型机制&#xff0c;使程序员可以定义安全的数据类型进行操作。通俗的理…

Java 图书管理系统

## 构建一个完整的图书管理系统 本文将介绍如何使用Spring Boot和MySQL构建一个完整的图书管理系统&#xff0c;并进一步丰富和完善其功能&#xff0c;包括用户管理、借阅记录、书籍搜索、分类管理、评论和评分等功能。我们还将生成REST API文档&#xff0c;并创建一个前端界面…

docker配置镜像源

1&#xff09;打开 docker配置文件 sudo nano /etc/docker/daemon.json 2&#xff09;添加 国内镜像源 {"registry-mirrors": ["https://akchsmlh.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc…

CEPH 系统盘挂了,如何使用数据盘恢复

硬盘损坏是早晚的时&#xff0c;CEHP数据盘坏了&#xff0c;使用CEPH的基本都轻车熟路了&#xff0c;如果系统盘坏了呢&#xff1f;不知道的可能会采取整个系统盘全做的方式 前提条件&#xff1a;使用cephadm搭建集群 如果换服务器&#xff0c;请确保CEPH数据盘放到其它服务器上…

第四十四章 在 SOAP 消息中使用数据集 - 控制数据集格式

文章目录 第四十四章 在 SOAP 消息中使用数据集 - 控制数据集格式控制数据集格式 第四十四章 在 SOAP 消息中使用数据集 - 控制数据集格式 控制数据集格式 默认情况下&#xff0c;数据集以 Microsoft DiffGram 格式编写&#xff0c;并在其前面加上 XML 架构。以下显示了一个示…

Python基础教程——一次搞懂 Python 字典!Python字典的20种神奇用法

Python 字典&#xff08;Dictionary&#xff09;是数据结构中的一种重要类型。它以键值对的形式存储数据&#xff0c;具有快速查找的特性。今天我们将通过生动有趣的案例&#xff0c;来探讨字典的20个经典操作&#xff0c;帮助大家深入理解和掌握这些概念。 1. 创建字典 字典…

Python从0到100(三十四):Python中的urllib模块使用指南

1. urllib模块概述 在Python中&#xff0c;除了广泛使用的requests模块之外&#xff0c;urllib模块也是处理HTTP请求的重要工具。urllib模块在Python 2中分为urllib和urllib2两个模块&#xff0c;而在Python 3中&#xff0c;它们被合并为一个urllib模块。本文将重点介绍Python…