Skip to content

fix: 防止无障碍事件源节点索引越界导致崩溃 - #573

Open
DeanTMaxim wants to merge 1 commit into
SuperMonster003:masterfrom
DeanTMaxim:fix/accessibility-event-wrapper-index
Open

fix: 防止无障碍事件源节点索引越界导致崩溃#573
DeanTMaxim wants to merge 1 commit into
SuperMonster003:masterfrom
DeanTMaxim:fix/accessibility-event-wrapper-index

Conversation

@DeanTMaxim

Copy link
Copy Markdown

Closes #572

问题

脚本通过 auto.registerEvent 注册窗口变化事件后,AccessibilityService 会在调用脚本回调前构造 AccessibilityEventWrapper

getIndexInParent() 会持续递增索引,直到 parent.getChild(index) 等于事件源节点,但没有按 parent.childCount 限界。页面切换期间节点树可能变化,事件源节点可能已经从父节点移除;此时循环会访问越界索引,并由 Android 框架抛出 ArrayIndexOutOfBoundsException,导致 AutoJs6 进程、无障碍服务和当前脚本一起退出。

修改

  • 将父节点索引查找限制在 0 until childCount 范围内。
  • 父节点为空、目标节点未找到或节点读取抛出 RuntimeException 时返回安全哨兵 -1
  • 提取不依赖 Android 运行时的 findIndexInParent(),以便用本地单元测试稳定复现节点消失和节点失效场景。
  • 保持 getDepth() 不变:当前崩溃证据只指向 getIndexInParent(),本次不加入任意深度上限或扩大重构范围。

选择 -1 是因为它与 UiObject 构造器的缺省 indexInParent 一致,用来表示没有可用的父级索引;本次不改变 UiObject 的其他导航行为。

测试

新增 AccessibilityNodeIndexTest,覆盖:

  1. childCount = 1 且目标节点已消失时,不读取索引 1,返回 -1
  2. 读取子节点抛出 RuntimeException 时返回 -1
  3. 目标节点正常存在时返回正确索引。

TDD 证据:

  • 修复前,第一个用例以 IndexOutOfBoundsException: Index: 1, Size: 1 失败。
  • 加入边界后,第二个用例以 IllegalStateException: stale node 失败。
  • 临时将实现改为恒返 -1 时,正常路径用例以 expected:<1> but was:<-1> 失败。
  • 恢复最终实现后,独立 JUnit 4.13.2 运行结果为 OK (3 tests)
  • AccessibilityEventWrapper.ktAccessibilityNodeIndex.kt 连同 Android 36 android.jar 的窄化 Kotlin 编译通过。
  • git diff --check 无空白错误。

提交前再次运行完整 Gradle 任务 :app:testAppDebugUnitTest --no-daemon --offline

BUILD SUCCESSFUL in 14s
tests=3, skipped=0, failures=0, errors=0

当前 origin/master@ed3eb10e 首先存在以下资源链接错误;测试时仅在本地临时补充了两个颜色资源别名:

bottom_sheet_log.xml: resource color/console_debug not found
bottom_sheet_log.xml: resource color/console_verbose not found

资源链接通过后暴露出同一上游日志面板变更中的第二组既存错误:

LogBottomSheet.kt:82:29 Unresolved reference 'getInstance'
LogBottomSheet.kt:84:47 Unresolved reference 'globalConsole'
LogBottomSheet.kt:101:20 Unresolved reference 'getInstance'

测试时仅在本地把其中的 AutoJs.getInstance() 调整为项目现有的 AutoJs.instance 写法,随后完整 Gradle 目标测试通过。

上述两项临时基线补丁均已删除,未包含在本 PR 中;本 PR 只包含事件包装修复及其回归测试。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

auto.registerEvent 包装无障碍事件时可能因子节点索引越界导致应用崩溃

1 participant