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
setView
    inputChannel = new InputChannel();
@frameworks/base/services/core/java/com/android/server/wm/Session.java
    mWindowSession.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.java
            win.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.cpp
                                status_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.cpp
                                sp<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);  //复制给outInputChannel
            if (focusChanged) { displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus, false /*updateInputWindows*/);
@frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
            displayContent.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.java
                                        mInputTransaction.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.cpp
                                                        SurfaceFlinger::handleMessageTransaction
                                                            if (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::onMessageInvalidate
                                                                                    updateInputFlinger();
@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.java
        super(inputChannel, looper);
@frameworks/base/core/jni/android_view_InputEventReceiver.cpp
            mReceiverPtr = 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::handleEvent
    NativeInputEventReceiver::consumeEvents(env, false /*consumeBatches*/, -1, nullptr)
@frameworks/native/libs/input/InputTransport.cpp
        mInputConsumer.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.java
                onFocusEvent
                    windowFocusChanged(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.java
                onInputEvent(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.mfbz.cn/a/761303.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch:Painless scripting 语言(一)

Painless 是一种高性能、安全的脚本语言&#xff0c;专为 Elasticsearch 设计。你可以使用 Painless 在 Elasticsearch 支持脚本的任何地方安全地编写内联和存储脚本。 Painless 提供众多功能&#xff0c;这些功能围绕以下核心原则&#xff1a; 安全性&#xff1a;确保集群的…

【征服数据结构】:期末通关秘籍

【征服数据结构】&#xff1a;期末通关秘籍 &#x1f498; 数据结构的基本概念&#x1f608; 数据结构的基本概念&#x1f608; 逻辑结构和存储结构的区别和联系&#x1f608; 算法及其特性&#x1f608; 简答题 &#x1f498; 线性表&#xff08;链表、单链表&#xff09;&…

RPC架构基本结构和核心技术

当你在构建一个分布式系统时&#xff0c;势必需要考虑的一个问题是&#xff1a;如何实现服务与服务之间高效调用&#xff1f;当然&#xff0c;你可以使用Dubbo或Spring Cloud等分布式服务框架来完成这个目标&#xff0c;这些框架帮助我们封装了技术实现的复杂性。那么&#xff…

【论文阅读】-- 研究时间序列可视化,提升用户体验

Investigating Time Series Visualisations to Improve the User Experience 摘要1 引言2 相关工作互动技巧视觉编码坐标系 3 用户研究时间序列可视化互动技巧任务实验设计 4 结果交互技术的效果视觉编码的影响坐标系的影响 5 讨论交互技术的效果视觉编码的影响坐标系的影响 6 …

[JS]正则表达式

介绍 正则表达式是定义匹配字符串的规则, 在JS中, 正则表达式也是对象, 通常用于查找或替换符合规则的文本 许多语言都支持正则表达式, 在前端中常见的场景就是表单验证和敏感词替换 语法 正则字面量 / / const str 好好学习,天天向上 // 1.定义规则: const reg /好///…

17964 水桶打水

这是一个优先队列&#xff08;堆&#xff09;和贪心算法的问题。我们可以使用C来解决这个问题。 首先&#xff0c;我们需要创建一个优先队列来存储每个水龙头的结束时间。然后&#xff0c;我们将所有人的打水时间从小到大排序。接着&#xff0c;我们将每个人分配给最早结束的水…

深入解析Flowable:工作流与业务流程管理引擎

深入解析Flowable&#xff1a;工作流与业务流程管理引擎 引言 在数字化时代&#xff0c;企业对流程自动化的需求日益增长。有效的工作流和业务流程管理系统可以帮助组织提高生产力、优化资源分配以及增强决策支持。Flowable是一款开源的工作流和业务流程管理&#xff08;BPM&a…

MeterSphere v3.0全新启航,让软件测试工作更简单、更高效

2024年7月1日&#xff0c;MeterSphere v3.0版本正式发布。MeterSphere v3.0是新一代的测试管理和接口测试工具&#xff0c;致力于让软件测试工作更简单、更高效&#xff0c;不再成为持续交付的瓶颈。 在团队协作方面&#xff0c;针对目前企业软件测试团队所面临的测试工具不统…

springboot项目requestId设置、统一responsebody封装以及切面

利用filter设置requestId import cn.hutool.core.lang.UUID; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.s…

绿联NAS进入SSH的方法

1. 进入【设备管理】&#xff0c;在调试功能中&#xff0c;开启远程调试功能&#xff0c;发送手机验证码&#xff0c;你将得到一个3天有效期的验证码&#xff0c;就是ssh登录密码。 2. 使用终端工具或ssh命令直接登录SSH。 端口是922&#xff0c;账号是&#xff1a;root&#…

界面组件DevExpress WPF v24.1 - 增强的可访问性 UI自动化

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 DevExpress WPF控件日…

全网最详细的 gin框架请求数据绑定Bind 源码解析 -- 帮助你全面了解gin框架的请求数据绑定原理和方法

在gin框架中&#xff0c;我们可以将多种请求数据&#xff08;json, form,uri&#xff0c;header等&#xff09;直接绑定到我们定义的结构体&#xff0c;底层是通过反射方式获取我们定义在结构体上面的tag来实现请求数据到我们的结构体数据的绑定的。 在gin的底层有2大体系的数据…

华为HCIP Datacom H12-821 卷19

1.多选题 如图所示,RTA 的 GE0/0/0、GE0/0/1 接口分别连接部门 1 和 2,其网段分别为 10.1.2.0/24、 10.1.3.0/24 网段,为限制部门 1 和 2 之间的相互访问,在 RTA 上部署 traffic-filter,以下哪些部署方式是正 确? A、配置 ACL3000 拒绝源为 10.1.2.0/24 目的为 10.1.3.0…

matlab仿真 通信信号和系统分析(上)

&#xff08;内容源自详解MATLAB&#xff0f;SIMULINK 通信系统建模与仿真 刘学勇编著第三章内容&#xff0c;有兴趣的读者请阅读原书&#xff09; 一、求离散信号卷积和 主要还是使用卷积函数conv&#xff0c;值得注意的是&#xff0c;得到的卷积和长度结果为81&#xff0…

【正点原子K210连载】第十四章 按键输入实验 摘自【正点原子】DNK210使用指南-CanMV版指南

1&#xff09;实验平台&#xff1a;正点原子ATK-DNK210开发板 2&#xff09;平台购买地址https://detail.tmall.com/item.htm?id731866264428 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/docs/boards/xiaoxitongban 第十四章 按键输入实…

短信验证码API的防护策略?怎么优化更新?

短信验证码API的定制化服务怎么样&#xff1f;如何选择API服务&#xff1f; 短信验证码API成为保护用户账户和数据的重要工具&#xff0c;对短信验证码API的防护也显得尤为重要。AoKSend将探讨短信验证码API的防护策略&#xff0c;帮助企业和开发者确保系统的安全性和可靠性。…

FatFs(文件系统)

1官网 FatFs - 通用 FAT 文件系统模块 (elm-chan.org) FatFs 是用于小型嵌入式系统的通用 FAT/exFAT 文件系统模块。FatFs 模块是按照 ANSI C &#xff08;C89&#xff09; 编写的&#xff0c;并且与磁盘 I/O 层完全分离。因此&#xff0c;它独立于平台。它可以集成到资源有限…

2024 vue3入门教程:01vscode终端命令创建第一个vue项目

参考vue官网手册&#xff1a;https://cn.vuejs.org/guide/quick-start.html 一、找个盘符&#xff0c;新建文件夹存储以后得vue项目 我的是e盘下创建了vueproject 二、使用vscode打开存储vue项目的文件夹 因为我生成过项目&#xff0c;所以有文件&#xff0c;你们初次是没有…

【第五节】C/C++数据结构之图

目录 一、图的基本概念 1.1 图的定义 1.2 图的其他术语概念 二、图的存储结构 2.1 邻接矩阵 2.2 邻接表 三、图的遍历 3.1 广度优先遍历 3.2 深度优先遍历 四、最小生成树 4.1 最小生成树获取策略 4.2 Kruskal算法 4.3 Prim算法 五、最短路径问题 5.1 Dijkstra算…

WPF----自定义滚动条ScrollViewer

滚动条是项目当中经常用到的一个控件&#xff0c;大部分对外项目都有外观的需求&#xff0c;因此需要自定义&#xff0c;文中主要是针对一段动态的状态数据进行展示&#xff0c;并保证数据始终在最新一条&#xff0c;就是需要滚动条滚动到底部。 1&#xff0c;xaml中引入 <…