8295智能座舱弹窗点击问题,点击window之外的区域,window不消失的问题。touchableRegion的问题分析(android 13)

ops/2025/3/4 11:24:56/

1.问题描述
在项目开发过程中,遇到input的问题。用户点击status bar的Wifi图标之后,会弹出wifi列表的window,而点击这个window之外的区域,wifi列表的窗口不会消失的问题。
在这里插入图片描述
2. 问题分析定位

分析触摸问题,必不可少的会用到下面的两个dump命令,用来查询当前window的信息,以及window对应的inputManager的信息。

adb shell dumpsys window w > ws.log
adb shell dumpsys input > input.log

  2: name='a0f96b1 com.android.carsettings', id=265, displayId=0, inputConfig=PREVENT_SPLITTING | TRUSTED_OVERLAY | WATCH_OUTSIDE_TOUCH, alpha=1.00, frame=[1677,127][2397,847], globalScale=1.000000, applicationInfo.name=, applicationInfo.token=<null>, touchableRegion=[-2560,-1440][5120,2880], ownerPid=11831, ownerUid=1000, dispatchingTimeout=5000ms, hasToken=true, touchOcclusionMode=BLOCK_UNTRUSTEDtransform (ROT_0) (TRANSLATE)1.0000  0.0000  -1677.00000.0000  1.0000  -127.00000.0000  0.0000  1.0000

从input info可以看出来Wifi列表的弹框对应的
window:‘a0f96b1 com.android.carsettings’
frame,也就是window的位置和大小:frame=[1677,127][2397,847]
touchableRegion,也就是触摸区域:touchableRegion=[-2560,-1440][5120,2880]

代码跟踪:

   @VisibleForTestingvoid populateInputWindowHandle(final InputWindowHandleWrapper inputWindowHandle,final WindowState w) {// Add a window to our list of input windows.inputWindowHandle.setInputApplicationHandle(w.mActivityRecord != null? w.mActivityRecord.getInputApplicationHandle(false /* update */) : null);inputWindowHandle.setToken(w.mInputChannelToken);inputWindowHandle.setDispatchingTimeoutMillis(w.getInputDispatchingTimeoutMillis());inputWindowHandle.setTouchOcclusionMode(w.getTouchOcclusionMode());inputWindowHandle.setPaused(w.mActivityRecord != null && w.mActivityRecord.paused);inputWindowHandle.setWindowToken(w.mClient);inputWindowHandle.setName(w.getName());// Update layout params flags to force the window to be not touch modal. We do this to// restrict the window's touchable region to the task even if it requests touches outside// its window bounds. An example is a dialog in primary split should get touches outside its// window within the primary task but should not get any touches going to the secondary// task.int flags = w.mAttrs.flags;if (w.mAttrs.isModal()) {flags = flags | FLAG_NOT_TOUCH_MODAL;}inputWindowHandle.setLayoutParamsFlags(flags);inputWindowHandle.setInputConfigMasked(InputConfigAdapter.getInputConfigFromWindowParams(w.mAttrs.type, flags, w.mAttrs.inputFeatures),InputConfigAdapter.getMask());final boolean focusable = w.canReceiveKeys()&& (mService.mPerDisplayFocusEnabled || mDisplayContent.isOnTop());inputWindowHandle.setFocusable(focusable);final boolean hasWallpaper = mDisplayContent.mWallpaperController.isWallpaperTarget(w)&& !mService.mPolicy.isKeyguardShowing()&& !mDisableWallpaperTouchEvents;inputWindowHandle.setHasWallpaper(hasWallpaper);// Surface insets are hardcoded to be the same in all directions// and we could probably deprecate the "left/right/top/bottom" concept.// we avoid reintroducing this concept by just choosing one of them here.inputWindowHandle.setSurfaceInset(w.mAttrs.surfaceInsets.left);// If we are scaling the window, input coordinates need to be inversely scaled to map from// what is on screen to what is actually being touched in the UI.inputWindowHandle.setScaleFactor(w.mGlobalScale != 1f ? (1f / w.mGlobalScale) : 1f);boolean useSurfaceBoundsAsTouchRegion = false;SurfaceControl touchableRegionCrop = null;final Task task = w.getTask();if (task != null) {if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {// 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;if (w.mAttrs.isModal()) {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);if (!useSurfaceBoundsAsTouchRegion) {Slog.w("InputWindow", "setTouchableRegion,  mTmpRegion = " + mTmpRegion  + ", w = " + w);w.getSurfaceTouchableRegion(mTmpRegion, w.mAttrs);inputWindowHandle.setTouchableRegion(mTmpRegion);}}

在这里插入图片描述

接下来看看WindowState计算touchableRegion的过程:

   void getSurfaceTouchableRegion(Region region, WindowManager.LayoutParams attrs) {final boolean modal = attrs.isModal();Slog.w("InputWindow", "getSurfaceTouchableRegion,  region = " + region  + ", attrs= " + attrs + ", this = " + this+ ", modal = " + modal + ", mTouchableInsets = " + mTouchableInsets + ", mFrame = " + mWindowFrames.mFrame+ ", mWindowFrames = " + mWindowFrames);if (modal) {if (mActivityRecord != null) {// Limit the outer touch to the activity root task region.updateRegionForModalActivityWindow(region);Slog.w("InputWindow", "getSurfaceTouchableRegion-1,  region = " + region  + ", attrs= " + attrs + ", this = " + this);} else {// Give it a large touchable region at first because it was touch modal. The window// might be moved on the display, so the touchable region should be large enough to// ensure it covers the whole display, no matter where it is moved.getDisplayContent().getBounds(mTmpRect);final int dw = mTmpRect.width();final int dh = mTmpRect.height();region.set(-dw, -dh, dw + dw, dh + dh);Slog.w("InputWindow", "getSurfaceTouchableRegion-2,  region = " + region  + ", attrs= " + attrs + ", this = " + this);}subtractTouchExcludeRegionIfNeeded(region);Slog.w("InputWindow", "getSurfaceTouchableRegion-3,  region = " + region  + ", attrs= " + attrs + ", this = " + this);} else {// Not modalgetTouchableRegion(region);Slog.w("InputWindow", "getSurfaceTouchableRegion-4,  region = " + region  + ", attrs= " + attrs + ", this = " + this);}// Translate to surface based coordinates.final Rect frame = mWindowFrames.mFrame;if (frame.left != 0 || frame.top != 0) {region.translate(-frame.left, -frame.top);Slog.w("InputWindow", "getSurfaceTouchableRegion-5,  region = " + region  + ", attrs= " + attrs + ", this = " + this);}if (modal && mTouchableInsets == TOUCHABLE_INSETS_REGION) {// The client gave us a touchable region and so first// we calculate the untouchable region, then punch that out of our// expanded modal region.mTmpRegion.set(0, 0, frame.right, frame.bottom);mTmpRegion.op(mGivenTouchableRegion, Region.Op.DIFFERENCE);region.op(mTmpRegion, Region.Op.DIFFERENCE);Slog.w("InputWindow", "getSurfaceTouchableRegion-6,  region = " + region  + ", attrs= " + attrs + ", this = " + this);}// TODO(b/139804591): sizecompat layout needs to be reworked. Currently mFrame is post-// scaling but the existing logic doesn't expect that. The result is that the already-// scaled region ends up getting sent to surfaceflinger which then applies the scale// (again). Until this is resolved, apply an inverse-scale here.if (mInvGlobalScale != 1.f) {region.scale(mInvGlobalScale);}Slog.w("InputWindow", "getSurfaceTouchableRegion,  region = " + region  + ", attrs= " + attrs + ", this = " + this+ ", mInvGlobalScale = " + mInvGlobalScale);}

log如下:

01-01 16:00:07.572  1704  1729 W InputWindow: setTouchableRegion,  mTmpRegion = SkRegion((0,0,2560,1440)), w = Window{7542c78 u0 com.android.carsettings}
01-01 16:00:07.572  1704  1729 W InputWindow: getSurfaceTouchableRegion,  region = SkRegion((0,0,2560,1440)), attrs= {(163,127)(720x720) gr=TOP END CENTER sim={adjust=resize} ty=NAVIGATION_BAR_PANEL fmt=RGBA_8888
01-01 16:00:07.572  1704  1729 W InputWindow:   fl=LAYOUT_IN_SCREEN LAYOUT_NO_LIMITS WATCH_OUTSIDE_TOUCH HARDWARE_ACCELERATED
01-01 16:00:07.572  1704  1729 W InputWindow:   pfl=USE_BLAST
01-01 16:00:07.572  1704  1729 W InputWindow:   bhv=DEFAULT
01-01 16:00:07.572  1704  1729 W InputWindow:   fitTypes=NAVIGATION_BARS CAPTION_BAR}, this = Window{7542c78 u0 com.android.carsettings}, modal = true, mTouchableInsets = 0, mFrame = Rect(1677, 127 - 2397, 847), mWindowFrames = com.android.server.wm.WindowFrames@e67a3a8
01-01 16:00:07.573  1704  1729 W InputWindow: getSurfaceTouchableRegion-2,  region = SkRegion((-2560,-1440,5120,2880)), attrs= {(163,127)(720x720) gr=TOP END CENTER sim={adjust=resize} ty=NAVIGATION_BAR_PANEL fmt=RGBA_8888
01-01 16:00:07.573  1704  1729 W InputWindow:   fl=LAYOUT_IN_SCREEN LAYOUT_NO_LIMITS WATCH_OUTSIDE_TOUCH HARDWARE_ACCELERATED
01-01 16:00:07.573  1704  1729 W InputWindow:   pfl=USE_BLAST
01-01 16:00:07.573  1704  1729 W InputWindow:   bhv=DEFAULT
01-01 16:00:07.573  1704  1729 W InputWindow:   fitTypes=NAVIGATION_BARS CAPTION_BAR}, this = Window{7542c78 u0 com.android.carsettings}
01-01 16:00:07.573  1704  1729 W InputWindow: getSurfaceTouchableRegion-3,  region = SkRegion((-2560,-1440,5120,2880)), attrs= {(163,127)(720x720) gr=TOP END CENTER sim={adjust=resize} ty=NAVIGATION_BAR_PANEL fmt=RGBA_8888
01-01 16:00:07.573  1704  1729 W InputWindow:   fl=LAYOUT_IN_SCREEN LAYOUT_NO_LIMITS WATCH_OUTSIDE_TOUCH HARDWARE_ACCELERATED
01-01 16:00:07.573  1704  1729 W InputWindow:   pfl=USE_BLAST
01-01 16:00:07.573  1704  1729 W InputWindow:   bhv=DEFAULT
01-01 16:00:07.573  1704  1729 W InputWindow:   fitTypes=NAVIGATION_BARS CAPTION_BAR}, this = Window{7542c78 u0 com.android.carsettings}
01-01 16:00:07.574  1704  1729 W InputWindow: getSurfaceTouchableRegion-5,  region = SkRegion((-4237,-1567,3443,2753)), attrs= {(163,127)(720x720) gr=TOP END CENTER sim={adjust=resize} ty=NAVIGATION_BAR_PANEL fmt=RGBA_8888
01-01 16:00:07.574  1704  1729 W InputWindow:   fl=LAYOUT_IN_SCREEN LAYOUT_NO_LIMITS WATCH_OUTSIDE_TOUCH HARDWARE_ACCELERATED
01-01 16:00:07.574  1704  1729 W InputWindow:   pfl=USE_BLAST
01-01 16:00:07.574  1704  1729 W InputWindow:   bhv=DEFAULT
01-01 16:00:07.574  1704  1729 W InputWindow:   fitTypes=NAVIGATION_BARS CAPTION_BAR}, this = Window{7542c78 u0 com.android.carsettings}
01-01 16:00:07.575  1704  1729 W InputWindow: getSurfaceTouchableRegion,  region = SkRegion((-4237,-1567,3443,2753)), attrs= {(163,127)(720x720) gr=TOP END CENTER sim={adjust=resize} ty=NAVIGATION_BAR_PANEL fmt=RGBA_8888
01-01 16:00:07.575  1704  1729 W InputWindow:   fl=LAYOUT_IN_SCREEN LAYOUT_NO_LIMITS WATCH_OUTSIDE_TOUCH HARDWARE_ACCELERATED
01-01 16:00:07.575  1704  1729 W InputWindow:   pfl=USE_BLAST
01-01 16:00:07.575  1704  1729 W InputWindow:   bhv=DEFAULT
01-01 16:00:07.575  1704  1729 W InputWindow:   fitTypes=NAVIGATION_BARS CAPTION_BAR}, this = Window{7542c78 u0 com.android.carsettings}, mInvGlobalScale = 1.0
01-01 16:00:07.575  1704  1729 W InputWindow: setTouchableRegion,  region = SkRegion((-4237,-1567,3443,2753)), mHandle = 7542c78 com.android.carsettings, frame=[0,0,0,0], touchableRegion=SkRegion((-4237,-1567,3443,2753)), scaleFactor=1.0, transform=null, windowToken=android.os.BinderProxy@30d22ea, isClone=false, callstack = 
01-01 16:00:07.575  1704  1729 W InputWindow: java.lang.Throwable: xxxx
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.InputWindowHandleWrapper.setTouchableRegion(InputWindowHandleWrapper.java:143)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.InputMonitor.populateInputWindowHandle(InputMonitor.java:316)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.InputMonitor$UpdateInputForAllWindowsConsumer.accept(InputMonitor.java:657)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.InputMonitor$UpdateInputForAllWindowsConsumer.accept(InputMonitor.java:529)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.WindowContainer$ForAllWindowsConsumerWrapper.apply(WindowContainer.java:2728)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.WindowContainer$ForAllWindowsConsumerWrapper.apply(WindowContainer.java:2718)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.WindowState.applyInOrderWithImeWindows(WindowState.java:4957)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.WindowState.forAllWindows(WindowState.java:4801)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1699)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1699)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1699)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1699)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1716)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.InputMonitor$UpdateInputForAllWindowsConsumer.updateInputWindows(InputMonitor.java:569)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.InputMonitor$UpdateInputForAllWindowsConsumer.-$$Nest$mupdateInputWindows(Unknown Source:0)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.wm.InputMonitor$UpdateInputWindows.run(InputMonitor.java:137)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at android.os.Handler.handleCallback(Handler.java:942)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at android.os.Handler.dispatchMessage(Handler.java:99)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at android.os.Looper.loopOnce(Looper.java:201)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at android.os.Looper.loop(Looper.java:288)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at android.os.HandlerThread.run(HandlerThread.java:67)
01-01 16:00:07.575  1704  1729 W InputWindow: 	at com.android.server.ServiceThread.run(ServiceThread.java:44)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
wifi列表弹框,没有FLAG_NOT_TOUCH_MODAL ,且没有FLAG_NOT_FOCUSABLE,这样的行为,就是让所有的input event全部给这个window,所以出现bug这个的,点击window之外的区域,不会退出的现象。

3.问题解决方案
wifi列表弹框,加上FLAG_NOT_FOCUSABLE,最终验证PASS。


http://www.ppmy.cn/ops/163030.html

相关文章

攻防世界WEB(新手模式)18-easyphp

打开题目&#xff0c;直接开始代码审计 条件1&#xff1a;$a 必须存在&#xff0c;且 intval($a) 必须大于 6000000&#xff0c;同时 strlen($a) 必须小于等于 3。 这意味着 $a 必须是一个字符串&#xff0c;且它的整数值大于 6000000&#xff0c;但字符串长度不能超过 3。这看…

JS宏进阶:数据分类之逻辑回归

一、逻辑回归介绍 逻辑回归(Logistic Regression)是一种用于解决分类问题的统计学习方法,特别是适用于二分类问题。 1、原理 线性模型与逻辑函数:逻辑回归基于线性回归的概念,但通过使用逻辑函数(也称为 sigmoid 函数)将线性模型的输出映射到 [0, 1] 的概率范围内。这…

机器学习:特征提取

介绍 &#xff08;一&#xff09;原理 特征提取的核心概念是将高维、复杂的原始数据转换为低维且具有代表性的特征集合。原始数据往往包含大量冗余或无关信息&#xff0c;直接使用这些数据进行模型训练不仅会增加计算成本&#xff0c;还可能导致模型性能下降。通过特征提取&a…

一文了解:部署 Deepseek 各版本的硬件要求

很多朋友在咨询关于 DeepSeek 模型部署所需硬件资源的需求&#xff0c;最近自己实践了一部分&#xff0c;部分信息是通过各渠道收集整理&#xff0c;so 仅供参考。 言归正转&#xff0c;大家都知道&#xff0c;DeepSeek 模型的性能在很大程度上取决于它运行的硬件。我们先看一下…

通往 AI 之路:Python 机器学习入门-语法基础

第一章 Python 语法基础 Python 是一种简单易学的编程语言&#xff0c;广泛用于数据分析、机器学习和人工智能领域。在学习机器学习之前&#xff0c;我们需要先掌握 Python 的基本语法。本章将介绍 Python 的变量与数据类型、条件语句、循环、函数以及文件操作&#xff0c;帮助…

开源模型应用落地-DeepSeek-R1-Distill-Qwen-7B-Docker助力-模型部署 “光速” 指南

一、前言 在人工智能的浪潮里,大语言模型不断迭代更新,DeepSeek-R1-Distill-Qwen-7B 模型凭借出色的表现,吸引着无数开发者的目光。然而,想要将这个强大的模型顺利部署并投入使用,过程却并不轻松。传统的部署方式仿佛布满荆棘,从底层环境搭建到各种依赖项的适配,每一步都…

Halcon图像预处理算子 sobel算子、傅里叶变换算子、卷积算子

滤波类型算子适用噪声特点均值滤波mean_image高斯噪声平滑均匀&#xff0c;可能额模糊边缘中值滤波median_image椒盐噪声保留边缘&#xff0c;抑制脉冲噪声高斯滤波gauss_filter高斯噪声加权平均&#xff0c;边缘更平滑 均值滤波 mean_image(Image,ImageMean,MaskWidth,MaskHe…

【C++】使用 CMake 在 Windows 上自动化发布 C++/Qt 应用程序

对于使用 MinGW 编译 C/Qt 项目的开发者来说&#xff0c;发布程序时常常面临目标机器缺少必要运行时库&#xff08;DLL&#xff09;的情况。传统方法需要手动收集依赖文件&#xff0c;不仅繁琐&#xff0c;还容易遗漏。本文将展示如何利用 CMake 构建系统&#xff0c;结合 Qt 官…