学员答疑:安卓分屏窗口的TouchableRegion设置流程追踪

Android5.1 双输入的处理--理解inputChannel 近期在处理双屏异显双触摸屏的问题, 发现副屏上的事件处理区域只能和主屏一样大,当副屏小于主屏时不会有问题,但是当副屏大于主屏时问题就比较明显;跟代码发现副屏在设置触摸区域大小时是按照主屏大小设置的,看了很多代码,还是总结下窗口接收按键和自更新的过程。... 阅读详情

背景:

vip学员在群里问到了一个分屏触摸区域设置的问题,开始以为就是和普通Activity设置区域没啥差别,都是在InputMonitor中进行的设置,但是仔细研究下来其实并不是哈。本文就带大家来手把手分析一下分屏情况下的触摸区域是怎么设置的。
在这里插入图片描述

dumpsys input
在这里插入图片描述短信的触摸区域为上半屏幕
com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity
touchableRegion=[0,0][1440,1463]

电话的触摸区域为下半屏幕
com.android.dialer/com.android.dialer.main.impl.MainActivity
touchableRegion=[0,1498][1440,2960]

下面就来剖析出分屏情况下的touchableRegion是如何正确设置获取的。

原因分析追踪:

先来一个正常touchableRegion的传递流图
在这里插入图片描述这里看Region设置的本质来源还是system_server发起的,dumpsys input看到的Region是SurfaceFlinger直接传递的,有了上面的知识基础后,开始分析这个分屏Region设置问题。

分析思路1–从systemserver进程设置源头出发进行打印堆栈分析
具体可以使用InputWindowHandleWrapper的setTouchableRegion进行堆栈打印,既可以很方便的追到哪里设置的touch矛,但是正常使用InputWindowHandleWrapper的setTouchableRegion发现根本没发现有分屏相关区域的任何设置。
分屏情况下的打印setTouchableRegion,发现并没有在system_server层面进行设置
在这里插入图片描述

分析思路2-从SurfaceFlinger角度出发分析Region的设置
从SurfaceFlinger看看给InputDispatcher的Region是如何设置的,这个其实在前面sf,input课程都有讲解,这里就不进行这块源码分析,主要还是针对Region的获取部分分析。

在这里插入图片描述下面来看看buildWindowInfos方法

在这里插入图片描述

在fillInputInfo方法中主要看核心部分

WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform, bool displayIsSecure) {
//省略
//明显看到这个地方有对touchableRegion进行额外的设置,而不是直接用systemserver端设置的,估计就是这个地方对分屏的Region进行了重新设置
    auto cropLayer = mDrawingState.touchableRegionCrop.promote();
    if (info.replaceTouchableRegionWithCrop) {
        std::string str;
        const Rect bounds(cropLayer ? cropLayer->mScreenBounds : mScreenBounds);
        info.touchableRegion = Region(displayTransform.transform(bounds));
    } else if (cropLayer != nullptr) {
        std::string str;
        info.touchableRegion = info.touchableRegion.intersect(
                displayTransform.transform(Rect{cropLayer->mScreenBounds}));
    }

在fillInputInfo需要加入相关的打印来验证猜想
加入日志后代码如下,主要在 if (info.replaceTouchableRegionWithCrop)前面打印一个Region,在他逻辑后打印一个

    std::string str;
     info.touchableRegion.dump(str,"info.touchableRegion");
    ALOGE(" %s fillInputInfo info str %s ",getName().c_str(),str.c_str());
    auto cropLayer = mDrawingState.touchableRegionCrop.promote();
    if (info.replaceTouchableRegionWithCrop) {
        std::string str;
        const Rect bounds(cropLayer ? cropLayer->mScreenBounds : mScreenBounds);
        info.touchableRegion = Region(displayTransform.transform(bounds));
        info.touchableRegion.dump(str,"info.touchableRegion");
        ALOGE("111111111111 %s   fillInputInfo info str %s cropLayer %s",getName().c_str(),str.c_str(),cropLayer!=nullptr ? cropLayer->getName().c_str():"null");
    } else if (cropLayer != nullptr) {
        std::string str;
        info.touchableRegion = info.touchableRegion.intersect(
                displayTransform.transform(Rect{cropLayer->mScreenBounds}));
        info.touchableRegion.dump(str,"info.touchableRegion");
        ALOGE("22222222222222 %s  fillInputInfo info str %s ",getName().c_str(),str.c_str());
    }

然后进入分屏,查看日志结果如下

在这里插入图片描述
得到结论如下:
1、分屏的相关window设置的TouchRegion是开始就是0
2、因为replaceTouchableRegionWithCrop标志设置成了true,代表要使用task的bounds覆盖TouchRegion
3、具体使用哪个task的bounds需要靠mDrawingState.touchableRegionCrop这个参数

那么这个replaceTouchableRegionWithCrop和mDrawingState.touchableRegionCrop是哪里设置的呢?

设置堆栈如下:
在这里插入图片描述

void populateInputWindowHandle(final InputWindowHandleWrapper inputWindowHandle,
            final WindowState w) {
            //省略部分
       if (task != null) {
            // TODO(b/165794636): Remove the special case for freeform window once drag resizing is
            // handled by WM shell.
            //判断task是不是属于分屏
            if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FULLSCREEN
                        && !task.inFreeformWindowingMode()) {
                // If the window is in a TaskManaged by a TaskOrganizer then most cropping will
                // be applied using the SurfaceControl hierarchy from the Organizer. This means
                // we need to make sure that these changes in crop are reflected in the input
                // windows, and so ensure this flag is set so that the input crop always reflects
                // the surface hierarchy.
                //分屏useSurfaceBoundsAsTouchRegion为true
                useSurfaceBoundsAsTouchRegion = true;

                if (w.mAttrs.isModal()) {
                //获取的Task,这个Task就是上面sf的touchableRegionCrop
                    TaskFragment parent = w.getTaskFragment();
                    touchableRegionCrop = parent != null ? parent.getSurfaceControl() : null;
                }
            } else if (task.cropWindowsToRootTaskBounds() && !w.inFreeformWindowingMode()) {
                touchableRegionCrop = task.getRootTask().getSurfaceControl();
            }
        }
        inputWindowHandle.setReplaceTouchableRegionWithCrop(useSurfaceBoundsAsTouchRegion);
        inputWindowHandle.setTouchableRegionCrop(touchableRegionCrop);
//省略部分
        }

代码总结:
1、遍历windowstate的WindowMode是否属于非全屏非自由窗口,如果分屏模式,则需要设置setReplaceTouchableRegionWithCrop为true

2、遍历分屏窗口的父亲Task,把Task设置为TouchableRegionCrop,最后会设置到sf中

整体总结:

在framework系统是属于一个很复杂的体系,每个小分支都会有很多不同的处理方式等,所以当使用正规的思路打堆栈分析不出来时候,不应该直接放弃,更应该从逆向,或者多角度来尝试探索分析,这样才符合实际项目中遇到各种问题都可以使用学习的知识灵活应对,而不是仅仅套一下模板,一旦有一些异常变化就又不知道如何分析,教给各位粉丝的知识一定要活学活用哈,整体理解多角度分析。

更多framework实战干货,请关注下面“千里马学框架”

Android InputDispatch事件派发->选择目标窗口 WindowManagerService的主要两大作用: 1 和surfaceflinger交互,创建surface, 通知surfacelinger窗口的层级、大小、位置等属性。 2 和inputflinger交互, 告知inputflinger当前窗口大小位置,是否可以接受input事件以及窗口可以处理什么类型的事件。 surfacelinger和inputflinger都是系统里面两个负载较重的服务。为了分心WindowManagerService我准备先从inputflinger这端着手,因为这端 阅读详情

相关推荐

别再只设接触压力了!用ANSYS Workbench模拟O型圈密封泄漏的完整流程

本文详细介绍了在ANSYS Workbench中模拟O型圈密封泄漏的完整流程,重点解析了流体渗透压力载荷的设置与应用。通过双物理场耦合模型和精确的参数配置,帮助工程师准确评估密封性能,避免传统方法仅考虑接触压力的局限性。文章还提供了常见问题的解决方案和工程实践建议,提升密封设计的可靠性。

weixin_30372371的博客 401

十分钟了解Android触摸事件原理(InputManagerService)

从手指接触屏幕到MotionEvent被传送到Activity或者View,中间究竟经历了什么?Android中触摸事件到底是怎么来的呢?源头是哪呢?本文就直观的描述一个整个流程,不求甚解,只求了解。 Android触摸事件模型 触摸事件肯定要先捕获才能传给窗口,因此,首先应该有一个线程在不断的监听屏幕,一旦有触摸事件,就将事件捕获;其次,还应该存在某种手段可以找到目标窗口,因为可能有多个APP的...

weixin_34266504的博客 910

OpenVPN 新增 windows 客户端

虚拟私人网络(Virtual Private Network,简称VPN)是一种网络技术,它允许用户通过公共网络(如互联网)建立一个安全的连接通道。本文介绍如何添加 windows 客户端。

利昂的技术存档 3769

为了讲清楚Android触摸事件,我“拆了部手机”

本篇文章稍微有点长,从硬件驱动,系统内核,到 Framework 都有涉及。其中,了解 IMS 的实现原理,APP 和 IMS 通信的建立,以及 ViewGroup 的 dispatchTouchEvent() 方法的事件派发逻辑,是本篇文章比较重要的内容。

chuyouyinghe的专栏 865

用ESP32-S3和USB摄像头DIY一个无线图传监控(附完整代码和接线图)

本文详细介绍了如何利用ESP32-S3开发板和USB摄像头打造一套高性价比的无线图传监控系统。从硬件选型、接线图到代码实现,提供了完整的DIY方案,特别适合家庭监控、宠物看护等场景。通过优化WiFi传输和双核任务分配,实现了稳定的视频流传输,整套方案成本控制在200元以内。

weixin_33701251的博客 519

超详细neo4j安装教程

一、neo4j简介 最近开始学习知识图谱,所以首先想先学习一下neo4j的使用。 Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。由于知识图谱中存在大量的关系型信息(实体—关系—实体), 使用结构化数据库进行存储将产生大量的冗余存储信息, 因此将图数据库作为知识图谱的存储容器成为流行的选择。当前较为常用的图数据库主要有 Neo4j 等。 二、neo4j的安装 功能快捷键 撤销:Ctrl/Command + Z 重做:Ctrl/Command + Y 加粗:Ctrl/Co

qq_38335648的博客 9万+

ActivityRecordInputSink的触摸区域TouchRegion详细解读

到这里就完美解释清楚了ActivityRecordInputSink巨大区域是哪里来的,本质还是因为replaceTouchableRegionWithCrop设置成了true,在sf计算时候会使用getMaxDisplayBounds作为Region。那这里没有设置这个TouchRegion,但是input中又有TouchRegion,那么难道是Sf或者input中设置的?上面是针对普通的WindowState来说都是这样一个设置流程,最后的input相关信息都是上面流程设置到sf的。

liaosongmao1的专栏 418

2025实战|C#上位机+STM32实现LED串灯控制:串口通信+PWM调光+自定义帧协议(附上下位机源码)

粘包:一次收到“BRIGHT:50LED_OFF”,解析完全错乱;乱码:串口波特率/编码不匹配,指令变成“??H??50”;丢帧:数据传输中少字符,比如“BRIGHT:5”,解析出亮度5而非50。因此我们设计字节级自定义帧协议协议先行:无论简单还是复杂场景,先定义清晰的帧协议,避免数据错乱;串口稳字当头:下位机用环形缓冲区接收,上位机加锁发送,避免丢包/粘包;跨线程必处理:C#上位机所有UI更新必须用Invoke,否则必崩溃;硬件是基础:接线、供电、共地这些细节,比代码更易出问题;

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 756

Android6.0 WMS(五) WMS计算Activity窗口大小的过程分析(一)应用进程

转载: https://blog.youkuaiyun.com/kc58236582/article/details/53781071 这篇文章很多参考博客:http://blog.youkuaiyun.com/luoshengyang/article...

jiangnan2222的博客 786

2026 Claude Code 标准化前端UI SKILL——Frontend Design

是 Anthropic 官方开源的技能包,在 Claude 官方插件站中排名第一,超过 52k 的下载量。场景推荐方案快速体验批量安装官方 Skills深度设计策略叠加完整打磨流程集成终端跑claude一句话总结:Frontend Design 不是给 AI 加新能力,而是给 AI 加审美标准。它让 AI 从“能画”变成“会设计”——先想清楚风格,再动手写代码。

十年老程序猿,AI 疯狂研究专家,前沿硬核知识分享 3612

【Flutter 问题系列第 16 篇】如何防止软键盘弹出后顶掉内容

Flutter 如何防止软键盘弹出后顶掉内容

“Allen Su”的博客 3317

揭秘Android系统返回手势的实现原理

/ 今日科技快讯 /近日,中国信息通信研究院推出了手机号“一键查询”和“一键解绑”服务,可以查询并解除本人手机账号或前手机账号主人所绑定的互联网关联账号。尽管很快有工作人员向媒体回应称,该功能尚处于内测阶段,还没有正式对外发布,但网友对此呼声极高。/ 作者简介 /明天就是周五啦,提前祝大家周末愉快!本篇转自TechMerger的博客,文章主要分享了系统返回...

郭霖 2176

流体仿真软件:COMSOL Multiphysics二次开发_(11).COMSOL与外部软件的数据交换

通过上述方法,您可以实现 COMSOL Multiphysics 与外部软件的数据交换,从而更好地集成和分析仿真结果。无论是从文本文件导入数据,导出数据到 MATLAB,还是通过 API 和 COMSOL Server 实现实时通信,都能满足不同场景下的需求。希望这些内容对您在流体仿真领域的开发工作有所帮助。

kkchenjj的博客 1553

WindowState笔记,windowstate

WindowState笔记,windowstate 这片文章将详细分析WindowState中的各个关键成员变量及成员函数。 1、Session类对象mSession 每一个WindowState都有一个Session类成员变量,那么每一个窗口保存的都是同一个mSession吗?还是每一个窗口的mSession都不同呢?dump一下便知道了,dump日志告诉我上述两种情况都不

3416

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Region.Op

1. 裁剪注意在Android自定义View使用绘图的裁剪功能的时候,我们最好manifest中的<application/> 或者<activity/>或者<fragment/>标签中添加如下属性:android:hardwareAccelerated="false"因为裁剪功能是不支持硬件加速的.没有设置的话,有可能绘图裁剪的效果出不来.2.裁剪枚举类型android原生api裁剪方法中clip

怪咖先森的博客 703

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Android触控事件处理机制(基于Android 11)

作者:安卓M豆先生 1 概述 用户手指点击按压屏幕后,屏幕触控驱动产生中断,Linux内核会将硬件产生的触控事件包装成Event放在设备的dev/input/目录下。此后Android系统需要解决以下几个问题以实现整个触控事件的分发处理: 如何从设备上读取触控事件? 读取到触控事件后该如何派发事件? 派发事件时如何找到接收事件的目标应用窗口? 找到目标应用窗口后如何将事件传递到目标窗口? 目标应用窗口内部中的事件如何处理? 下面将结合最新Android 11系统源码,通过分析回答这些问题来了解And.

4173

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

如何改进车载三分屏SplitScreen启动交互方式?

上面这2个需求其实在真正的车机分屏中也是非常常见的哈,所以这里马哥收到学员的疑问后立即就给大家针对课程的三分屏进行相关的交互改善,实现了三分屏的动态进入,三分屏的Task内容的动态控制等。还有三分屏的各个Task是否可以不通过最近任务进行操作,有没有更简单的进入三分屏方式?这里面的componentName1,componentName2,componentName3就是三分屏的每个Task的对应Activity的名字。进入后发现第三屏Task内容就是设置的我的文件对应的FilesActivity。

learnframework的博客 414

framework 窗口动画缩放修改(Android 10)

framework 窗口动画缩放修改(Android 10) 窗口缩放方法 // frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java final WindowHashMap mWindowMap = new WindowHashMap(); public void performAnimationByHome(boolean enterScale) { Log.i("scale_w

wg_mlo的博客 3098

【Android】【input子系统】【Focus Application、Focus Window、Focus Display02】

我们经常会遇到一种Application does not hava focused window的ANR异常,这种异常一般是没有焦点窗口FocusedWindow导致,且这类异常只会发生在key事件的派发,因为key事件是需要找到一个焦点窗口然后再派发,而触摸事件只需要找到当前显示的窗口即可。焦点窗口是指当前正在与用户交互的窗口,该窗口负责接收键事件和触摸事件。当启动新的Activity、添加新的窗口、移除旧窗口、分屏来回操作时,都会涉及到焦点窗口的更新。

super_sun_shine的博客 375

Dumpsys

Dumpsys The dumpsys tool runs on the device and dumps interesting information about the status of system services. Usage The input system is part of the window manager. To dump its state, run the f

小龙龙起飞 706

Android Framework 常见解决方案(28)system分区自定义方案

一般在定制系统时,都会做预置apk和各类其他资源,很有可能超出系统默认设置的系统分区大小,也就会导致编译system时因超出默认设置的分区大小而失败。一般的做法是修改android framework时,修改对应项目的BOARD_SYSTEMIMAGE_PARTITION_SIZE的值。BOARD_SYSTEMIMAGE_PARTITION_SIZE是在 Android 系统构建过程中使用的板级配置变量之一。它在 Android 框架中的主要作用是指定系统镜像(system partition)的大小。

wangdsh的博客 2714

Android焦点之InputWindows的更新(二)

再次回到InputMonitor#updateInputWindows(),调用SurfaceControl.Transaction#merge,之后,当WindowAnimator.java的animate()时发起apply();可以是线程"android.anim"或"binder"线程;

薛文旺 486

深入分析 Android 系统返回手势的实现原理

Android 10 正式引入了全屏手势导航(Gesture Navigation),Home 键和 History 键的功能借助上滑和悬停手势得以保留,而 Back 键则以返回手势(Back Gesture)重新与大家见面。 相较 iOS 早期便有的全局返回功能,Android 直到版本 10 才姗姗来迟。但 Google 给这个功能添加了视图、动画和角度展示,更是向用户开放了手势敏感度的设置入口。 本文就这个系统功能一探其实现原理,了解之后: 作为 FW 开发者可以在 SystemUI 中优..

allisonchen的专栏 6995

WindowState注意事项

本文将分析具体WindowState个别关键的成员变量和成员函数。 Window #3 Window{20dd178e u0 com.android.mms/com.android.mms.ui.ConversationList}: mDisplayId=0 mSession=Session{cb5d53 25296:u0a10013} mClient=androi...

aofan9566的博客 1095
上一篇: 干货答疑分享记录:as导入问题,LSP含义,分屏进入SplashScreen
下一篇: aosp系统源码aidl文件如何查看对应生成的java文件-安卓系统开发实战小技巧分享
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值