systemserver的inputdispatcher直接产生CANCEL事件原理分析-讨厌的android触摸面试题

news2025/1/17 13:53:39

背景回顾:

上一个blog已经重点讲解了app层面自己产生的Cancel触摸事件,大概产生的原理如下:
上一个blog地址:https://blog.csdn.net/learnframework/article/details/124086882
在这里插入图片描述即可以看出来,在服务端systemserver其实传递的触摸事件依然是move,只是move事件到了app端后,由于app端自己的业务把这个传递的move事件变成的cancel
视频讲解:https://www.bilibili.com/video/BV1nY4y1e713/
在这里插入图片描述那么疑问来了?这个有没有存在systemserver传递事件时候就是已经变成cancel了呢?
如下图:

在这里插入图片描述

答案当然是有的。下面就进行详细分析

2、systemserver端变成cancel事件

复现场景:
1、手机设置成导航按键模式桌面点击
在这里插入图片描述

2 、点击一个应用进入,然后手指一直触摸再应用内
3、然后另一个手点击导航键home按键,让回到桌面

以上3步即可以复现点击进去的应用内接受到一个Cancel事件,因为手其实一直触摸在屏幕,所以当然不存在接受到up,但是毕竟这个时候应用已经被退到后台,所以就只能给一个cancel事件给应用。这个cancel事件就是systemserver中inputdispatcher传递给应用的。

下面来进行源码分析cancel事件在inputdispatcher产生

1、开启日志
开放DEBUG_OUTBOUND_EVENT_DETAILS日志,这里可以用adb 命令也可以直接修改变成true

/**
 * Log detailed debug messages about each outbound event processed by the dispatcher.
 * Enable this via "adb shell setprop log.tag.InputDispatcherOutboundEvent DEBUG" (requires restart)
 */
const bool DEBUG_OUTBOUND_EVENT_DETAILS =
       true;// __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "OutboundEvent", ANDROID_LOG_INFO);

2、复现时候查看日志

09-10 22:49:50.775  2231  2357 D InputDispatcher: channel 'a1b72df com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity (server)' ~ Synthesized 1 cancelation events to bring channel back in sync with reality: touched window was removed, mode=1.

这里即可以看出有同步一个cancel事件给com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity,大家注意这个原因是“touched window was removed”

可以根据这个reason来追一下相关代码:

test@test:~/nx563j_xiaomi/frameworks/native$ grep "touched window was removed" ./ -rn
./services/inputflinger/dispatcher/InputDispatcher.cpp:4759:                                               "touched window was removed");

找到了在InputDispatcher的4759行:

/**
 * Called from InputManagerService, update window handle list by displayId that can receive input.
 * A window handle contains information about InputChannel, Touch Region, Types, Focused,...
 * If set an empty list, remove all handles from the specific display.
 * For focused handle, check if need to change and send a cancel event to previous one.
 * For removed handle, check if need to send a cancel event if already in touch.
 */
void InputDispatcher::setInputWindowsLocked(
        const std::vector<sp<WindowInfoHandle>>& windowInfoHandles, int32_t displayId) {
   //省略部分
   //把inputdispatcher的window相关信息变成最新
       updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId);

   //最为关键的mTouchStatesByDisplay变量,一般保存就是当前触摸事件的派发情况,主要保存了派发触摸相关的window信息
    std::unordered_map<int32_t, TouchState>::iterator stateIt =
            mTouchStatesByDisplay.find(displayId);
    if (stateIt != mTouchStatesByDisplay.end()) {
        TouchState& state = stateIt->second;
        for (size_t i = 0; i < state.windows.size();) {
            TouchedWindow& touchedWindow = state.windows[i];
            //拿正在触摸的window信息与最新的window的信息比较看看是否还存在,如果不在说明消失了
            if (getWindowHandleLocked(touchedWindow.windowHandle) == nullptr) {
              
                std::shared_ptr<InputChannel> touchedInputChannel =
                        getInputChannelLocked(touchedWindow.windowHandle->getToken());
                if (touchedInputChannel != nullptr) {
                //开始触发相关的cancel事件
                    CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
                                               "touched window was removed");
                    synthesizeCancelationEventsForInputChannelLocked(touchedInputChannel, options);
               
                    }
                }
                state.windows.erase(state.windows.begin() + i);
            } else {
                ++i;
            }
        }
//省略
}


setInputWindowsLocked主要是在系统有窗口window更新时候才会触发调用,比如我们上面演示场景的,按home按键后应用画面要退出后台,这个时候肯定应用的window就没有了,就会触发改方法。
1、updateWindowHandlesForDisplayLocked
这里会把最新的window信息更新到inputdispatcher的mWindowHandlesByDisplay变量中
2、方法内主要变量有一个mTouchStatesByDisplay:

最为关键的mTouchStatesByDisplay变量,一般保存就是当前触摸事件的派发情况,主要保存了派发触摸相关的window信息

即代表当前的触摸事件派发相关window的的记录

3、还有另一个关键方法getWindowHandleLocked

sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(
        const sp<IBinder>& windowHandleToken) const {
    if (windowHandleToken == nullptr) {
        return nullptr;
    }
		//就是拿传入的windowHandleToken去mWindowHandlesByDisplay遍历看看是否有
    for (auto& it : mWindowHandlesByDisplay) {
        const std::vector<sp<WindowInfoHandle>>& windowHandles = it.second;
        for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
            if (windowHandle->getToken() == windowHandleToken) {
                return windowHandle;
            }
        }
    }
    return nullptr;
}

4、找到对应删除的window的inputchannel,传递对应的cancel事件
//获取touchedInputChannel
std::shared_ptr touchedInputChannel =
getInputChannelLocked(touchedWindow.windowHandle->getToken());
//派发cancel事件到touchedInputChannel
synthesizeCancelationEventsForInputChannelLocked(touchedInputChannel, options);

如果发现更新之后的window的中已经没有了正在派发事件的window,那么说明window已经被移除,然后就会触发相关的cancel事件到原来的window。

最后更多干货直接找千里马可以+w ; androidframework007

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

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

相关文章

国家信息中心举办“数字政府建设暨数字安全技术”研讨会:海云安提出数字政府软件供应链安全解决方案

近日&#xff0c;由国家信息中心主办&#xff0c;复旦大学研究院承办的“数字政府建设暨数字安全技术研讨会”在义乌顺利召开。国家信息中心信息与网络安全部副主任禄凯&#xff0c;复旦大学党委常委、宣传部部长陈玉刚&#xff0c;义乌市委常委、常务副市长喻新贵为会议致辞。…

三、C#—变量,表达式,运算符(3)

&#x1f33b;&#x1f33b; 目录 一、变量1.1 变量1.2 使用变量的步骤1.3 变量的声明1.4 变量的命名规则1.5 变量的初始化1.6 变量初始化的三种方法1.7 变量的作用域1.8 变量使用实例1.9 变量常见错误 二、C#数据类型2.1 数据类型2.2 值类型2.2.1 值类型直接存储值2.2.2 简单类…

【rust/egui】(十)使用painter绘制一些图形—connections

说在前面 rust新手&#xff0c;egui没啥找到啥教程&#xff0c;这里自己记录下学习过程环境&#xff1a;windows11 22H2rust版本&#xff1a;rustc 1.71.1egui版本&#xff1a;0.22.0eframe版本&#xff1a;0.22.0上一篇&#xff1a;这里 绘制连接 在上一节我们使用painter绘制…

《深度学习初探:使用TensorFlow和Keras构建你的第一个神经网络》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

GCP之Google Cloud Infrastructure

Google Cloud 的物理网络是如何连接的&#xff1f; Google Cloud 分为 regions&#xff0c;regions 又分为 zones。 region 是一个地理区域&#xff0c;其中一个 VM 到另一个 VM 的往返时间 &#xff08;RTT&#xff09; 通常小于 1毫秒&#xff1b;zone 是 region 中的部署区…

canvas基础笔记

一、简介 Canvas是HTML5中的一个元素&#xff0c;它提供了一个可以使用JavaScript绘制图形的区域。它提供了一个强大的绘图API&#xff0c;可以用于创建各种图形&#xff0c;包括线条、矩形、圆形、文本等 Canvas 是 HTML5 中的一个元素&#xff0c;用于绘制图形、动画和图像。…

架构核心技术之微服务架构

小熊学Java&#xff1a;https://www.javaxiaobear.cn/&#xff0c;文末有免费资源 本文我们来学习微服务的架构设计 主要包括如下内容。 单体系统的困难&#xff1a;编译部署困难、数据库连接耗尽、服务复用困难、新增业务困难。 微服务框架&#xff1a;Dubbo 和 Spring Clou…

sdkman 的安装配置与 sdk 管理

sdkman 的安装配置与 sdk 管理 记录一下项目使用的工具&#xff0c;目前环境的管理有以下几个&#xff1a; sdkmanpyenvnvm 这里主要讲一下 sdkman&#xff0c;我们项目是通过 sdkman 进行 java 和 maven 的管理&#xff0c;这个写的挺简单的&#xff0c;加上一个自己写的自…

unipush2.0实现APP消息推送(2)云函数多个方法的创建与使用

问题&#xff1a;上篇文章我们已经介绍到了unipush2.0消息推送的实现思路&#xff0c;但是遇到一个问题就是如何在一个云函数里写多个方法供传统服务端调用&#xff1f; 这样做的目的&#xff1a;这样传统服务端就可以调用一个云函数url路径传递不同的参数标识走不同的方法了 …

uni-app--》基于小程序开发的电商平台项目实战(一)

&#x1f3cd;️作者简介&#xff1a;大家好&#xff0c;我是亦世凡华、渴望知识储备自己的一名在校大学生 &#x1f6f5;个人主页&#xff1a;亦世凡华、 &#x1f6fa;系列专栏&#xff1a;uni-app &#x1f6b2;座右铭&#xff1a;人生亦可燃烧&#xff0c;亦可腐败&#xf…

《AI一键生成抖音商品种草文案》让你秒变带货王!

在这个数字化的时代&#xff0c;我们的生活被各种应用所包围&#xff0c;其中&#xff0c;抖音作为一款短视频分享平台&#xff0c;已经成为了我们生活中不可或缺的一部分。然而&#xff0c;作为一名抖音创作者&#xff0c;你是否曾经遇到过这样的困扰&#xff1a;在创作商品种…

Linux C : select简介和epoll 实现

目录 一、基础知识 二、select 模型服务流程 二、select 模式的缺点。 三、poll 概要 四、epoll 服务端实现流程 1.epoll_create&#xff1a; 2.epoll_ctl 3.epoll_wait 五、epoll示例代码实现 1.epoll实现服务端 2.客户端采用tcp进行访问 一、基础知识 首先要知道&…

flink的几种常见的执行模式

背景 在运行flink时&#xff0c;我们经常会有几种不同的执行模式&#xff0c;比如在IDE中启动时&#xff0c;通过提交到YARN上&#xff0c;还有通过Kebernates启动时&#xff0c;本文就来记录一下这几种模式 flink的几种执行模式 flink嵌入式模式&#xff1a; 这是一种我们在…

基于keras中Lenet对于mnist的处理

文章目录 MNIST导入必要的包加载数据可视化数据集查看数据集的分布开始训练画出loss图画出accuracy图 使用数据外的图来测试图片可视化转化灰度图的可视化可视化卷积层的特征图第一层卷积 conv1 和 pool1第二层卷积 conv2 和 pool2 MNIST MNIST&#xff08;Modified National …

从零开始的PICO教程(4)--- UI界面绘制与响应事件

从零开始的PICO教程&#xff08;4&#xff09;— UI界面绘制与响应事件 文章目录 从零开始的PICO教程&#xff08;4&#xff09;--- UI界面绘制与响应事件一、前言1、大纲2、教程示例 二、具体步骤1、PICO VR环境配置2、XR的UI Canvas画布创建与调整&#xff08;1&#xff09;C…

【雷达原理】雷达信号级建模与仿真

目录 前言一、LFMCW信号概述1.1 优点1.2 缺点 二、LFMCW信号模型2.1 发射信号模型2.2 接收信号模型2.3 信号混频 三、MATLAB仿真3.1 仿真结果3.2 代码 四、参考文献 前言 雷达信号形式多种多样&#xff0c;按照雷达的体制进行分类&#xff0c;有脉冲雷达和连续波雷达。脉冲雷达…

C#程序到底从哪里开始看,从Main函数开始,那么Main函数是什么?

视觉人机器视觉粉丝问我,拿到自己公司得架构,问我,C#程序到底从哪里看,从Main函数开始,那么Main函数是什么? Main()函数 Main()是C#应用程序的入口点,执行这个函数就是执行应用程序。也就是说,在执行过程开始时,会执行Main()函数,在Main()函数执行完毕时,执行过…

微信小程序上拉触底事件

一、什么是上拉触底事件 上拉触底是移动端的专有名词&#xff0c;通过手指在屏幕上的上拉滑动操作&#xff0c;从而加载更多数据的行为。 二、监听上拉触底事件 在页面的.js文件中&#xff0c;通过onReachBottom()函数即可监听当前页面的上拉触底事件。 三、配置上拉触底距…

vue组件库开发,webpack打包,发布npm

做一个像elment-ui一样的vue组件库 那多好啊&#xff01;这是我前几年就想做的 但webpack真的太难用&#xff0c;也许是我功力不够 今天看到一个视频&#xff0c;早上6-13点&#xff0c;终于实现了&#xff0c;呜呜 感谢视频的分享-来龙去脉-大家可以看这个视频&#xff1a;htt…

【List篇】ArrayList 的线程不安全介绍

ArrayList 为什么线程不安全&#xff1f; 主要原因是ArrayList是非同步的,没有同步机制,并且其底层实现是基于数组&#xff0c;而数组的长度是固定的。当对 ArrayList 进行增删操作时&#xff0c;需要改变数组的长度&#xff0c;这就会导致多个线程可能同时操作同一个数组&…