InputChannel发送Input给App-Android12

2023-10-27 15:10

本文主要是介绍InputChannel发送Input给App-Android12,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

InputChannel发送Input给App-Android12

android12-release


1. App的ViewRootImpl建立InputChannel

查看 InputChannel通道建立-Android12 1. APP界面建立InputChannel,下面看图:

  • InputChannel / WindowInputEventReceiver建立联系,并建立服务端Connection
  • InputStage责任链:SyntheticInputStage - ViewPostImeInputStage - NativePostImeInputStage - EarlyPostImeInputStage - ImeInputStage - ViewPreImeInputStage - NativePreImeInputStage

在这里插入图片描述

2. InputChannel通过socket发送Input给App

2.1 InputChannel通过socket发送

查看 InputDispatcher线程分发事件-Android12 ,InputPublisher::publishKeyEvent通过mChannel->sendMessage(&msg)发送

  • nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL)目标Fd写入

frameworks/native/libs/input/InputTransport.cpp

status_t InputChannel::sendMessage(const InputMessage* msg) {const size_t msgLength = msg->size();InputMessage cleanMsg;msg->getSanitizedCopy(&cleanMsg);ssize_t nWrite;do {nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);} while (nWrite == -1 && errno == EINTR);if (nWrite < 0) {int error = errno;
#if DEBUG_CHANNEL_MESSAGESALOGD("channel '%s' ~ error sending message of type %d, %s", mName.c_str(),msg->header.type, strerror(error));
#endifif (error == EAGAIN || error == EWOULDBLOCK) {return WOULD_BLOCK;}if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {return DEAD_OBJECT;}return -error;}if (size_t(nWrite) != msgLength) {
#if DEBUG_CHANNEL_MESSAGESALOGD("channel '%s' ~ error sending message type %d, send was incomplete",mName.c_str(), msg->header.type);
#endifreturn DEAD_OBJECT;}#if DEBUG_CHANNEL_MESSAGESALOGD("channel '%s' ~ sent message of type %d", mName.c_str(), msg->header.type);
#endifreturn OK;
}

2.2 WindowInputEventReceiver接收input消息

  • WindowInputEventReceiver中LooperCallback回调handleEvent()在android_view_InputEventReceiver.cpp中,最终调用到WindowInputEventReceiver.onInputEventNativeInputEventReceiver::handleEvent -- consumeEvents -- gInputEventReceiverClassInfo.dispatchInputEvent -> InputEventReceiver.onInputEvent(event) -> WindowInputEventReceiver.onInputEvent

frameworks/base/core/java/android/view/InputEventReceiver.java
frameworks/base/core/jni/android_view_InputEventReceiver.cpp
在这里插入图片描述 在这里插入图片描述

2.3 ViewRootImpl中执行InputStage 责任链

  1. 通过enqueueInputEvent -> doProcessInputEvents -> deliverInputEvent -> stage.deliver(q)调用执行InputStage 责任链
    在这里插入图片描述 在这里插入图片描述
  2. InputStage的各子类Input事件result = onProcess(q)处理,再判断是forward()向下传递,还是finish()结束
abstract class InputStage {// ... ...public final void deliver(QueuedInputEvent q) {if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {forward(q);} else if (shouldDropInputEvent(q)) {finish(q, false);} else {traceEvent(q, Trace.TRACE_TAG_VIEW);final int result;try {result = onProcess(q);} finally {Trace.traceEnd(Trace.TRACE_TAG_VIEW);}apply(q, result);}}/*** Marks the the input event as finished then forwards it to the next stage.*/protected void finish(QueuedInputEvent q, boolean handled) {q.mFlags |= QueuedInputEvent.FLAG_FINISHED;if (handled) {q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;}forward(q);}/*** Forwards the event to the next stage.*/protected void forward(QueuedInputEvent q) {onDeliverToNext(q);}/*** Applies a result code from {@link #onProcess} to the specified event.*/protected void apply(QueuedInputEvent q, int result) {if (result == FORWARD) {forward(q);} else if (result == FINISH_HANDLED) {finish(q, true);} else if (result == FINISH_NOT_HANDLED) {finish(q, false);} else {throw new IllegalArgumentException("Invalid result: " + result);}}/*** Called when an event is ready to be processed.* @return A result code indicating how the event was handled.*/protected int onProcess(QueuedInputEvent q) {return FORWARD;}/*** Called when an event is being delivered to the next stage.*/protected void onDeliverToNext(QueuedInputEvent q) {if (DEBUG_INPUT_STAGES) {Log.v(mTag, "Done with " + getClass().getSimpleName() + ". " + q);}if (mNext != null) {mNext.deliver(q);} else {finishInputEvent(q);}}// ... ...
}

3. 例如ViewPostImeInputStage中processKeyEvent

关注KeyEvent事件分发给APP界面窗口。mView就是App的RootViewImpl.setView设置,涉及PhoneWindow.java、DecorView.java,查看DecorView.dispatchKeyEvent 最终会分发到真正需要处理该时间的窗口。这里handled可以判断应用是否拦截KeyEvent事件,但是需要明白的是不管应用拦不拦截,Input事件都已经发送给应用了。
在这里插入图片描述 在这里插入图片描述

3.1 Activity设置的回调Window.Callback

cb.dispatchKeyEvent(event) 调用到Activity中,这里app可以重载拦截事件。win.superDispatchKeyEvent(event)通过此方法进入view层级中。其具体实现是在PhoneWindow中。
在这里插入图片描述 在这里插入图片描述

3.2 finishInputEvent(q)

最终socket通信发送给服务端执行InputDispatcher::handleReceiveCallback,进行 gotOne 下一个事件发送【IMS:InputDispatcher 接收反馈进行下一次发送】
在这里插入图片描述 在这里插入图片描述

这篇关于InputChannel发送Input给App-Android12的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/286483

相关文章

Java发送SNMP至交换机获取交换机状态实现方式

《Java发送SNMP至交换机获取交换机状态实现方式》文章介绍使用SNMP4J库(2.7.0)通过RCF1213-MIB协议获取交换机单/多路状态,需开启SNMP支持,重点对比SNMPv1、v2c、v... 目录交换机协议SNMP库获取交换机单路状态获取交换机多路状态总结交换机协议这里使用的交换机协议为常

uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)

《uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)》在uni-app开发中,文件上传和图片处理是很常见的需求,但也经常会遇到各种问题,下面:本文主要介绍uni-app小程序项目中实... 目录方式一:使用<canvas>实现图片压缩(推荐,兼容性好)示例代码(小程序平台):方式二:使用uni

基于Python实现自动化邮件发送系统的完整指南

《基于Python实现自动化邮件发送系统的完整指南》在现代软件开发和自动化流程中,邮件通知是一个常见且实用的功能,无论是用于发送报告、告警信息还是用户提醒,通过Python实现自动化的邮件发送功能都能... 目录一、前言:二、项目概述三、配置文件 `.env` 解析四、代码结构解析1. 导入模块2. 加载环

使用Python的requests库来发送HTTP请求的操作指南

《使用Python的requests库来发送HTTP请求的操作指南》使用Python的requests库发送HTTP请求是非常简单和直观的,requests库提供了丰富的API,可以发送各种类型的HT... 目录前言1. 安装 requests 库2. 发送 GET 请求3. 发送 POST 请求4. 发送

基于Python编写自动化邮件发送程序(进阶版)

《基于Python编写自动化邮件发送程序(进阶版)》在数字化时代,自动化邮件发送功能已成为企业和个人提升工作效率的重要工具,本文将使用Python编写一个简单的自动化邮件发送程序,希望对大家有所帮助... 目录理解SMTP协议基础配置开发环境构建邮件发送函数核心逻辑实现完整发送流程添加附件支持功能实现htm

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁

python运用requests模拟浏览器发送请求过程

《python运用requests模拟浏览器发送请求过程》模拟浏览器请求可选用requests处理静态内容,selenium应对动态页面,playwright支持高级自动化,设置代理和超时参数,根据需... 目录使用requests库模拟浏览器请求使用selenium自动化浏览器操作使用playwright

Python办公自动化实战之打造智能邮件发送工具

《Python办公自动化实战之打造智能邮件发送工具》在数字化办公场景中,邮件自动化是提升工作效率的关键技能,本文将演示如何使用Python的smtplib和email库构建一个支持图文混排,多附件,多... 目录前言一、基础配置:搭建邮件发送框架1.1 邮箱服务准备1.2 核心库导入1.3 基础发送函数二、

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

HTML input 标签示例详解

《HTMLinput标签示例详解》input标签主要用于接收用户的输入,随type属性值的不同,变换其具体功能,本文通过实例图文并茂的形式给大家介绍HTMLinput标签,感兴趣的朋友一... 目录通用属性输入框单行文本输入框 text密码输入框 password数字输入框 number电子邮件输入编程框