第1章 无障碍线程架构全景

本章界定AOSP无障碍子系统在Android系统中的位置,从进程、线程维度拆解整体层次结构,明确各核心线程的角色与通信边界。通过一张分层架构图建立全局视角,并深入数据流向、控制信任链路及工程落地要点。

学习目标:读完本章后,你应该能够口头描述无障碍子系统涉及哪些进程/线程、数据如何从物理操作流转到AccessibilityService,以及为什么当前架构如此设计。
无障碍线程架构全景分层图 无障碍线程架构全景分层图 第1层 · 应用框架层(UI进程) 主线程(UI Thread) ViewRootImpl · ViewAccessibilityDelegate 无障碍节点树生成 · 事件派发 第2层 · 系统服务层(system_server) AccessibilityManagerService(AMS) Binder线程池 · HandlerThread(事件分发) 窗口变更监听 · 触控/手势注入 第3层 · 辅助服务层(AccessibilityService进程) 主线程(Service主线程) 事件回调 · 手势识别 · 焦点管理 Binder接收 · 高优先级线程池(可选) Binder IPC Binder + 回调 核心线程角色 • UI主线程:节点生成 • AMS Handler:事件路由 • 服务主线程:业务处理

1.1 边界定义

无障碍子系统跨越三个进程边界:

  • UI进程(每个应用主进程)—— 生成AccessibilityNodeInfo树,响应触摸/滚动事件。
  • 系统服务进程(system_server)—— 运行AccessibilityManagerService(AMS),负责全局调度、窗口管理、注入事件。
  • 辅助服务进程(AccessibilityService所在进程)—— 接收被筛选的事件,执行自动化操作或反馈。

线程边界:每个进程的主线程(UI Thread/Service主线程)主导无障碍交互;AMS内部使用独立HandlerThread处理事件路由,避免阻塞主线程。

1.2 分层与组件职责

层级 核心组件 线程角色 职责
应用框架层 ViewRootImpl, ViewAccessibilityDelegate UI主线程 监听系统AccessibilityState,构建并推送节点树,响应探索点击
系统服务层 AccessibilityManagerService Binder线程、HandlerThread 注册/注销服务、事件分发、焦点管理、手势注入、窗口追踪
辅助服务层 AccessibilityService 主线程 + 可选工作线程 解析事件,执行自定义逻辑(如朗读、自动化点击)

1.3 关键数据流向与信任链路

  1. 输入事件:用户触控 → InputDispatcher → ViewRootImpl(UI线程)
  2. 节点推送:UI线程通过Binder将AccessibilityEvent及节点信息发送至AMS。
  3. AMS分发:AMS HandlerThread按服务注册的packageNames、eventTypes过滤,通过Binder回调目标AccessibilityService。
  4. 服务处理:AccessibilityService主线程收到回调,可再派发到工作线程避免ANR。
  5. 信任链路:Binder验证调用方UID;AMS校验服务是否拥有BIND_ACCESSIBILITY_SERVICE权限;节点数据仅允许系统进程或已绑定的服务读取。
信任链路关键点:AccessibilityService无法直接访问其他应用的内存,所有节点信息通过AMS中转,且AMS会校验窗口所属包名与服务注册的filter是否匹配。避免恶意服务窥探隐私。

1.4 选型权衡

  • Binder IPC vs ContentProvider:Binder提供同步/异步双向通信,适合高频率事件流;ContentProvider更重且仅适合数据查询。选择Binder是性能最优解。
  • HandlerThread vs ExecutorService:AMS内部使用HandlerThread保证事件顺序处理,避免多线程并发导致状态不一致;辅助服务可选用ExecutorService处理CPU密集型任务,但需自行同步。
  • 每应用单进程模型:每个AccessibilityService运行在独立进程中,与UI进程隔离,牺牲部分进程间通信开销,但提升了安全性和稳定性(服务crash不影响应用)。

1.5 风险点

常见风险:
  • ANR:AccessibilityService在主线程中执行耗时操作(如网络请求、大量节点遍历)。应优先将重任务移入工作线程。
  • 优先级翻转:当服务线程优先级低于UI线程时,可能长时间竞争锁。建议使用android:process="xxx"并设置适当线程优先级。
  • 内存泄漏:节点树过大或未及时释放节点引用,导致服务进程OOM。应按需复用AccessibilityNodeInfo实例。
  • 死锁:AMS在分发事件时若持有锁而服务Btinder回调中又反向调AMS,可能形成循环等待。AMS设计上使用非重入锁,且回调在独立Handler线程执行。

1.6 落地步骤

  1. 在AndroidManifest中声明服务并绑定android.permission.BIND_ACCESSIBILITY_SERVICE。
  2. 在onAccessibilityEvent()中接收事件;若需耗时处理,立即使用HandlerThread或Executors切换线程。
  3. 通过getWindows()或findFocus()获取节点树,提取数据。
  4. 使用performAction()执行点击、长按等操作时注意检查isEnabled()和isImportantForAccessibility()。
  5. 调用setServiceInfo()动态调整事件过滤,避免接收无关事件浪费CPU。
  6. 监控性能:使用StrictMode检测主线程磁盘/网络访问,确保无ANR。

1.7 验收标准

验收项 期望指标 验证方法
事件响应延迟 ≤ 50 ms(从物理触摸到服务收到事件) 在事件回调中记录时间戳,对比InputDispatch时间
节点获取耗时 ≤ 10 ms(单个窗口) System.currentTimeMillis()前后差值
主线程空闲率 ≥ 90%(服务进程主线程无阻塞) Profile工具 / 插桩
无ANR 连续24小时运行无ANR日志 日志监控 + 系统anr目录检查