当前位置: 首页 > article >正文

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

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_UNTRUSTED
    transform (ROT_0) (TRANSLATE)
        1.0000  0.0000  -1677.0000
        0.0000  1.0000  -127.0000
        0.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]

代码跟踪:

   @VisibleForTesting
    void 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 modal
            getTouchableRegion(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.kler.cn/a/570864.html

相关文章:

  • DNS 详细过程 与 ICMP
  • aiohttp、httpx 和 requests 的区别
  • 五分钟快速学习优秀网站的HTML骨架布局设计
  • 比亚迪“灵鸢”来袭,汽车+无人机梦幻联动!
  • Qt:day1
  • LeetCode 热题 100 链表章节
  • 爬虫:一文掌握WebSocket爬虫案例实战
  • Kotlin 类委托与属性委托
  • 大白话跨域问题的原理与多种解决方法的实现
  • mac Homebrew安装、更新失败
  • 广义线性模型下的数据分析(R语言)
  • Android -- 使用Sharepreference保存List储存失败,原因是包含Bitmap,drawable等类型数据
  • UI自动化框架介绍
  • SpringBoot集成Netty实现Ws和Tcp通信
  • 【mysql】有索引和没有索引字段更新时锁的不同
  • C# OnnxRuntime部署DAMO-YOLO香烟检测
  • Spring Boot 自动装配深度解析与实践指南
  • React 源码揭秘 | bailout策略Memo
  • 力扣每日一题——分割回文串
  • Skyeye 云智能制造办公系统 VUE 版本 v3.15.11 发布