公开研究副本:本地绝对路径、实验主机地址已脱敏。NA 保留,完整可执行库存恢复为 0。角色与功能关联是可审核离线推断,未经人工金标或独立外部审查。历史代表截图不认证当次控件对齐。原件 SHA 只认证原件,公开字节 SHA 见发布清单。

APE 真实动作库存与选择机制审计

审计当前HEAD 9a5b577b77a6a87efcd8e6e218693af6faed17ce。以下路径均相对 native/src/com/android/commands/monkey/;含行号摘录与SHA用于复核,不凭旧论文或最终UTG推导运行机制。

实际调用链

MonkeySourceApe.generateEvents:425–474 获取 top Activity 与 Accessibility root(源码承认不是原子观察) → ApeAgent.updateState:278–292 → StatefulAgent.buildAndValidateNewState:537–543 → GUITreeBuilder/Naming/State → validateAllNewActions:833–837 → adjustActionsByGUITree:859–860 → SataAgent.selectNewActionInRound:399–473 → Graph.markVisited(输入前) → ApeAgent.checkInput:175–185 → MonkeySourceApe.generateEventsForAction:548–565 → 注入回执 → JevRuntime.inputSummary:764–793 → 下一GUI观察形成 NATIVE_TRANSITION。

  1. 保留树与理论GUI不同。 tree/GUITreeBuilder:480–516 根据 excludeInvisibleNode/excludeEmptyChild/alwaysIgnoreWebView 剪枝;263–285,309–351 应用XPathlets、父子click补丁、图像文本和WebView策略。Config:79–104 给默认值,不代表每个归档覆盖配置均已记录。可见但未暴露交互属性、被剪除或未映射的控件不自动成为动作;图像生成文本会改变原生Naming。
  2. State模型动作。 model/State:50–65,210–216 从 StateKey widgets 的 NamerFactory.decodeActions 建 ModelAction[],并加无target Back。naming/ActionPatchNamer:51–77 对 clickable/checkable 建Click、longClickable建LongClick、scrollType建各方向Scroll;构造动作类型本身不先过滤disabled。Naming.addNamedNode:212–242 可过滤空/屏外节点。输入框没有独立的全字符串动作全集。
  3. 每动作的控件匹配成员。 tree/GUITree:198–209 在当前Naming缓存 currentNames/currentNodes 中查Name,得到节点数组;State.resolveAction:346–358 从数组随机选一个代表。ModelAction:35–43,208–228 保存 resolvedNodes、resolvedNode、resolvedTree、timestamp和单个 GUITreeAction。所以不是“直到选中才第一次解析”:每个新模型动作会先解析,但也不是“所有Concrete已逐项验证”。
  4. 有效性、enabled、优先级。 StatefulAgent.validateNewAction:813–830 可能复用同timestamp缓存,否则重解析随机代表;委托 MonkeySourceApe.validateResolvedAction:338–375 对该代表检查非空、与root相交(不是完整hit-test或业务成功);Back有效。AgentActionScorer:48–94 依据代表节点设置enabled与priority,结合unvisited、别名数量及图上后继。Action:59–86 存enabled/valid,二者不是每个兄弟节点的表。未验证成员应记UNKNOWN,而不是复制代表valid。
  5. 选择是一串策略,不是一个Concrete清单。 SataAgent:399–473 按buffer、Activity返回、早期/局部greedy、远程greedy、trivial、backward、epsilon、fallback尝试。ActionFilter 包含enabled-valid-unvisited/unsaturated集合。SataAgent.getGreedyActions:599–621 在useActionDiffer时调用 model/StateActionDiffer:43–110,比较相邻State的Name/Type和饱和;否则 Graph.isActionUnvisitedByName:177–193 查同Activity+抽象Name+Type历史。后者并非精确Concrete历史。档案未逐轮保存这些完整中间名单/未选原因,不能声称enabled-valid中的每个成员当轮都有被所有策略选择的机会。
  6. 输入参数后置。 ApeAgent.checkInput:175–185 在模型动作选出后可能随机从 StringCache 选择输入文本;XPathlet也可预设(GUITreeBuilder:129–145)。MonkeySourceApe:480–522 用代表bounds生成click/longclick/scroll/Back;MonkeySourceApeInput:80–130 清文本、直接sendText、失败后key fallback。一次控件动作可包含多条低层事件/文本参数,不能按输入事件条数算Concrete执行,不能枚举无限文本组合为完整覆盖分母。

必须分开的五层集合

集合 运行时载体 有无完整性 归档可证范围
GUI理论交互控件 Accessibility tree,经Native预处理后保留GUITree 仅保留树完整,不是全部App交互 2,280抽样树;不认证模型资格
State识别的ModelAction State.actions[] + Back 当前State完整模型名单 23,971次有总数;2,131次可从unvisited IDs∪selected ID恢复全部ID,仍缺全属性
当前解析Concrete成员 各ModelAction.resolvedNodes,tree/timestamp必须一致 已解析成员数组,需标识缓存新鲜度 仅选中node及选中动作成员数量;全数组未记录
已验证有效Concrete 每动作的resolvedNode与action.valid/enabled 仅随机代表验证,无逐成员有效性全集 已确认选中输入事实,不是其他成员资格
策略实际可选动作 各策略局部列表、路径、当前代表绑定 顺序/随机/阶段相关,无统一物化全Concrete集合 仅选中策略/计数,没有每个未选动作的理由

因此,回答Q1是:有有限的模型动作与匹配控件缓存;没有一个可直接读出的“全部有效、策略可选、含全部输入实例”的完整Concrete库存。 对控件层可做更好的被动采集,但仍须分别解释模型成员、缓存代表与策略实际触达。

历史与身份

现有日志为何仍不够

JevRuntime.stateTelemetry:1022–1062 记录各类数量、unvisited IDs;recordSelectionDecision:848–872 记录选中类型/visit/饱和/fingerprint及resolvedNodeCount。JevEvidenceAudit:203–239 只对满足抽样条件的source/target保留树图;input_event_inventory 的“inventory”是单个选中输入的低层事件数组,不是当前页面动作库存。Pure未运行Region/审核候选机制,其context缺失不能靠决策组日志冒补。

详见 字段完整性矩阵 和 Shadow设计。本轮未运行Java重解析旧树,更没有把当前源码运行结果当作历史真实候选。