Skip to content

Bug: delayed accessibility events can overwrite the foreground cache / 延迟无障碍事件会覆盖前台缓存 #570

Description

@DeanTMaxim

Summary / 问题概述

ActivityInfoProvider may overwrite its current package/activity cache with a delayed TYPE_WINDOW_STATE_CHANGED event after that event's window has already disappeared. As a result, APIs and UI that rely on the cached foreground component can report a stale or unrelated package.

当某个 TYPE_WINDOW_STATE_CHANGED 事件延迟到达、且该事件对应的窗口已经消失时,ActivityInfoProvider 可能仍用该事件覆盖当前包名/Activity 缓存。因此,依赖此前台组件缓存的 API 或界面可能返回过期或无关的包名。

Reproduction / 复现方式

  1. Enable AutoJs6 accessibility service and continuously observe the latest package/activity.

  2. Switch quickly between an application and system surfaces such as the launcher or notification shade.

  3. Let a delayed window-state event arrive after its windowId is no longer present in AccessibilityService.windows.

  4. Compare the event with rootInActiveWindow and observe that the delayed event can replace the foreground cache even though the active root belongs to another window/package.

  5. 开启 AutoJs6 无障碍服务,并持续观察最近包名/Activity。

  6. 在应用与桌面、通知栏等系统界面之间快速切换。

  7. 某个窗口状态事件延迟到达时,其 windowId 已不再存在于 AccessibilityService.windows

  8. 将该事件与 rootInActiveWindow 对比,可以看到:即使当前活动根节点属于其他窗口/包名,延迟事件仍可能覆盖前台缓存。

This was reproduced on an OPPO Android test device using ADB, accessibility-window inspection, and screenshots. Device identifiers, accounts, and application data are intentionally omitted.

已在一台 OPPO Android 测试机上通过 ADB、无障碍窗口检查和截图复现。设备标识、账号及应用数据均已省略。

Expected behavior / 预期行为

  • A focused event window is accepted.

  • An unfocused event window is rejected.

  • If the event window no longer exists, the event is accepted only when both its window ID and package match rootInActiveWindow.

  • 事件窗口存在且聚焦时接纳事件。

  • 事件窗口存在但未聚焦时拒绝事件。

  • 事件窗口不存在时,仅当事件的窗口 ID 和包名均与 rootInActiveWindow 一致时才接纳。

Actual behavior and root cause / 实际行为与根因

The current condition is:

if (window?.isFocused != false)

When getWindow(event.windowId) returns null, window?.isFocused is null, and null != false evaluates to true. The event is therefore treated like a focused event and can overwrite mLatestPackage/mLatestActivity.

getWindow(event.windowId) 返回 null 时,window?.isFocused 也是 null,而 null != false 的结果为 true。因此该事件会被当作聚焦事件处理,并可能覆盖 mLatestPackage/mLatestActivity

Both maintained namespaces contain the same condition:

  • org.autojs.autojs.core.activity.ActivityInfoProvider
  • com.stardust.autojs.core.activity.ActivityInfoProvider

Proposed fix / 建议修复

Apply the acceptance policy described above to both namespaces and add unit tests covering focused, unfocused, missing-window, mismatched-window, mismatched-package, and missing-package cases.

在两个命名空间中应用上述接纳策略,并为聚焦、未聚焦、窗口缺失、窗口 ID 不匹配、包名不匹配及包名证据缺失等情况增加单元测试。

Related symptom report / 相关现象:#529

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions