记一次从“按钮点不动”到“窗口派发缺失”的排查过程

前言

"xx机型 进入待支付页面之后,【<】按钮点击没反应"

------ 这是测试同事最初的反馈。很多时候,我们会下意识把它当成:按钮被遮挡 / 没绑定监听 / 点击区域偏移 / 压力测试后状态异常。

但当我接手复测后,发现问题并不只是"一个按钮点不了",而是"整个上半屏(Dialog 之外的背景区域)完全没有触摸响应"。

这个"问题再界定"过程,直接决定了后续排查维度:从"控件级"转向"窗口输入命中级"。

最终根因是:一个看似纯视觉效果的窗口 Flag ------ FLAG_DIM_BEHIND ------ 在特定 ROM 上被策略层放大为"模态化处理",导致外部区域触摸事件被系统直接吞掉,没有分发进应用。下面详细展开全过程,并总结出可复用的输入排查方法论。

现象精确描述

场景:订单待支付页面,底部弹出一个自定义 Dialog(类似 Bottom Sheet 样式)。

  • Dialog 内部:按钮、列表项点击全部正常
  • 上半屏(Dialog 之外的可见 Activity 背景区域):完全无触摸响应(点击不触发埋点、也不触发全局触摸监控)
  • 预期:点击背景区域应允许关闭弹层或继续交互(例如点击返回)
  • 复现范围:特定 OEM(定制 ROM)出现;其他主流品牌正常
  • 伴随现象:无异常崩溃日志;无明显 ANR;

分层排查策略总览

Android 输入链路(简化):

sql 复制代码
物理触摸 → InputReader(读取设备事件)→ InputDispatcher(命中并派发)→ 应用 Window → DecorView / ViewGroup 分发 → 具体控件

目标:判断事件卡在哪一层。我们采用"自外向内"策略:先确认系统是否把事件派发给应用,再看应用内部是否消费/拦截。

事件是否进入应用窗口(系统派发层)

推荐 Perfetto 手指在本该响应的触摸区域,按下 滑动,抬起,重复多次,抓取 trace

  • Outbound(俗称 oq):InputDispatcher 针对目标窗口的派发队列事件

发现 没有对应oq分配到 app的 Window

查看APP 对应window 属性

adb shell dumpsys window

xml 复制代码
  Window #9 Window{11b6259 u0 xxx.xxx.xxx.xx/xxx.xxx.xxx.xx.ui.runningorder.OrderActivity}:
    mDisplayId=0 rootTaskId=462 mSession=Session{894b5d8 1199:u0a10560} mClient=android.os.BinderProxy@fde26a0
    mOwnerUid=10560 showForAllUsers=false package=xxx.xxx.xxx.xx appop=NONE
    mAttrs={(0,0)(fillxwrap) gr=BOTTOM CENTER_VERTICAL sim={adjust=pan} ty=APPLICATION fmt=TRANSPARENT wanim=0x7f120322 surfaceInsets=Rect(93, 93 - 93, 93) mSaturation=-2.0
    // DIM_BEHIND 这个 FLAG : 猜测某机型 会把带 DIM_BEHIND 的窗口仍当成"模态"对待,外区域不下发触摸(或被直接丢弃)
      fl=DIM_BEHIND NOT_TOUCH_MODAL SPLIT_TOUCH HARDWARE_ACCELERATED
      ...
    Requested w=1080 h=918 mLayoutSeq=5622
  Window #10 Window{344f9c2 u0 xxx.xxx.xxx.xx/xxx.xxx.xxx.xx.ui.runningorder.OrderActivity}:
    mDisplayId=0 rootTaskId=462 mSession=Session{894b5d8 1199:u0a10560} mClient=android.os.BinderProxy@125460d
    mOwnerUid=10560 showForAllUsers=false package=xxx.xxx.xxx.xx appop=NONE
    mAttrs={(0,0)(fillxfill) sim={state=always_hidden adjust=resize forwardNavigation} layoutInDisplayCutoutMode=always ty=BASE_APPLICATION wanim=0x1030309 mSaturation=-2.0
      fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
      ...

11b6259 (dialog 弹窗) ->

344f9c2 背景Activity ->

修改验证

java 复制代码
// dialog window设置
...
//增加这一行: 手动清除 FLAG_DIM_BEHIND ,目前项目中有设置展开Dialog时,显示背景,所以这个属性,是不需要的
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.setFlags(
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
            );
...

验证

adb shell dumpsys window

xml 复制代码
// 弹窗
Window #11 Window{682c4ff u0 xxx.xxx.xxx.xx/xxx.xxx.xxx.xx.ui.runningorder.OrderActivity}:
    mDisplayId=0 rootTaskId=467 mSession=Session{f6119c4 1473:u0a10560} mClient=android.os.BinderProxy@72c741e
    mOwnerUid=10560 showForAllUsers=false package=xxx.xxx.xxx.xx appop=NONE
    mAttrs={(0,0)(fillxwrap) gr=BOTTOM CENTER_VERTICAL sim={adjust=pan} ty=APPLICATION fmt=TRANSPARENT wanim=0x7f120322 surfaceInsets=Rect(93, 93 - 93, 93) mSaturation=-2.0
    // fl 已经没有那个属性了
      fl=NOT_TOUCH_MODAL SPLIT_TOUCH HARDWARE_ACCELERATED
     ...
    //背景层
  Window #12 Window{acf7b41 u0 xxx.xxx.xxx.xx/xxx.xxx.xxx.xx.ui.runningorder.OrderActivity}:
    mDisplayId=0 rootTaskId=467 mSession=Session{f6119c4 1473:u0a10560} mClient=android.os.BinderProxy@670f228
    mOwnerUid=10560 showForAllUsers=false package=xxx.xxx.xxx.xx appop=NONE
    mAttrs={(0,0)(fillxfill) sim={state=always_hidden adjust=resize forwardNavigation} layoutInDisplayCutoutMode=always ty=BASE_APPLICATION wanim=0x1030309 mSaturation=-2.0
      fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
     ...

问题解决:尝试滑动,点击先前无响应的该区域,可以正常响应。

排查思路总结

  1. 先界定范围:单控件?一块区域?全局?(区域性 → 优先怀疑 Window 命中 / 策略)
  2. 抓 trace(Perfetto):
    • 有 outbound(派发到目标窗口)吗?
  3. 无 outbound:
    • 用 dumpsys window 看目标窗口 flags / type / Z 序
    • 用 dumpsys input 看 FocusedWindow、touchableRegion
    • 检查是否被其他高层窗口/遮罩/系统策略截走
  4. 有 outbound 但应用没反应:
    • Activity.dispatchTouchEvent 是否触发?
    • View 层是否被透明遮挡 / intercept / clickable=false
    • 是否被 GestureDetector / OnTouchListener 提前消费
相关推荐
AntoineGriezmann1 分钟前
基于 Unocss 的后台系统 SVG 图标方案实践
前端
小夏卷编程2 分钟前
ant-design-vue 2.0 a-table 中实现特殊行样式,选中样式,鼠标悬浮样式不一样
前端·javascript·vue.js
wulijuan8886662 分钟前
前端性能优化之图片webp
前端
一颗烂土豆4 分钟前
ECharts 水球图不够炫?试试 RayChart 的创意可视化玩法
前端·vue.js·数据可视化
天才熊猫君5 分钟前
Vue 3 命令式弹窗组件
前端
NEXT065 分钟前
CSS基础-标准盒模型与怪异盒模型
前端·css
DaMu7 分钟前
Dreamcore3D ARPG IDE “手搓”游戏引擎,轻量级实时3D创作工具,丝滑操作,即使小白也能轻松愉快的创作出属于你自己的游戏世界!
前端·架构·three.js
代码猎人8 分钟前
什么是尾调用,使用尾调用有什么好处?
前端
AI_56789 分钟前
Webpack从“配置到提速”,4步解决“打包慢、体积大”问题
前端·javascript·vue.js
pinkQQx9 分钟前
手把手搭建前端跨平台服务(IPlatform + iOS / Android / Web)
前端·javascript