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

前言

"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 提前消费
相关推荐
console.log('npc')5 分钟前
2026 实测:Grok 4.5 与 Grok 4.6 怎么选?前端开发、教程写作、Figma 还原选型指南
前端·大模型·ai编程·figma·grok
yyt36304584120 分钟前
一次鼠标交互触发两次 Vue flushJobs:把高频交互从 VDOM 里拆出来
前端·vue.js·计算机外设
YUJIANYUE27 分钟前
查立得万用查分安卓版(web环境+查询系统免安装单文件一键运行包)
android·前端
慧都小项1 小时前
从 Figma 到 Qt:Qtitan 能减少哪些界面还原工作?
前端·qt·嵌入式·figma·图形界面·工业界面·qtitan
YWL1 小时前
OpenLayers导出功能:地图截图+GeoJSON导出完整方案,从Canvas合并到PDF生成
前端·vue·openlayers
苦瓜小生1 小时前
【前端】【力扣与手撕】十天带你刷完前端算法与手撕,全是最简单好记的最优解法!day4
前端·数据结构·算法·leetcode·面试
mayaairi1 小时前
Vue2 实战进阶:表单数据收集、指令系统与自定义指令全解析
前端·javascript·vue.js
计算机魔术师1 小时前
实测GPT-6 Astra后,我发现过去十年的专业门槛正在失效
前端
虎头金猫1 小时前
Pic Smaller 本地部署:压缩图片、转换格式,再搭建自己的 Web 工具
运维·前端·开源·aigc·ai编程·ai写作
hunterandroid2 小时前
Android ANR 排查实战:从线上告警到主线程卡点定位
android·前端