An independent review of the one design door the measurement left open (stop sending
the ~51,000 answers nobody reads, so the 8-slot pool stops churning and the create
window becomes collectable). Verdict: feasible, worth doing, and the proposal AS
WRITTEN would disable the thing it exists to enable.
THE CATCH. The windowed create is wantReply=false AND its answer is read -
WireTables.cpp's drain reads exactly those seqs. A bit keyed on "fire-and-forget"
therefore stops the server answering the creates the window is waiting for: the
window goes from "cannot be collected" to "there is nothing to collect", and the
readfail counter that is the only way to diagnose it disappears with it. It fails
silently, not loudly. The predicate has to be per-record "this answer will never be
read" - true of params / respecify-escape / sub-data, false of a windowed create -
carried as a separate input from wantReply (willReadReply), with
willReadReply && !rowCarriesReplySlot rejected rather than ignored.
VERIFIED HERE, not taken on trust (the reviewer's file:line claims, checked):
- the flag space is RingRecordFlags (Ring.h:281-285), bits 0-4 taken, BIT 5 FREE,
and the header's own table (PipeWire.inc:35-65) says "bit 5 kOptional vs (nothing)
no ring counterpart" - so a new ring bit aliases kOptional, which is exactly what
the assert at PipeWireCodec.cpp:142-145 refuses;
- the three static_asserts that will trip are real and deliberate
(PipeWireCodec.cpp:106, :142-145, RingTest.cpp:740);
- WireFingerprint mixes payload-layout, catalogue, render-state digests + OpCount,
none of which a ring bit moves - so no protocol revision bump is required, and
both cross-version directions degrade to today's behaviour. That makes this
"must upgrade both ends to take EFFECT", not "must upgrade both ends not to
BREAK" - one notch cheaper than handoff-2 section 3.2's protocol surface;
- StreamLink.cpp:564-571 is the independent progress flush (>= 64 records or
>= 1 ms) and :577 is PostReply piggybacking SendProgress on the reply - so
skipping replies coarsens progress granularity. Bounded, but unmeasured.
AND IT CORRECTED TWO OF MY OWN NUMBERS. The frame's reply count is 55,903, not
59,673: op 4 ResourceDestroy carries kNone in the catalogue (PipeWire.inc:179) and
PostReply Fatals on a row with no kReplySlot, so it never answers - I had added its
3,770 records to the total. The derived figures move with it (12.3 replies per create,
0.65 of a create of survival, 6,988 pool churns), and every copy is fixed here:
Config.h, ConfigLoader.cpp, WireTables.cpp's section comment, CONTRACT-P5E.md,
CREATE-WINDOW-MEASURED.md.
TWO MORE THINGS THE FOLLOW-UP MUST CARRY, both recorded in the note's section 7:
- LinkMetricsBeginReply counts ownsReplySlot, so once the flag lands by_op 2 falls
to ~0 - and section 1 of the note tells the reader to use by_op 2 to check whether
the window engaged. That check becomes a FALSE GREEN; the flag needs a
server-side "how many times did this op answer" counter beside it.
- the ~112,000 sendmsg/frame the flag removes are on the apply thread, so the
flag's own value is a measurable claim that nobody has measured.
172/172 and 13/13 after the comment corrections.
P12 — Android 生产窗口路径(「server 自有屏幕窗口」子集已实现,未收官)
本页是该阶段的阶段汇总:阶段表行、实测与落地形状的完整文本(2026-09-24 从上层索引移入,原文照录)都在这里;上层只留摘要——
ROADMAP.md、MEASUREMENTS.md、ARCHITECTURE.md。文中file:line与"今天""当前"按各段写成时的头理解;文中的MEASUREMENTS.md §N/ARCHITECTURE.md §17.x编号保留,对照表见../README.md。
摘要
- 当前阶段。状态摘要在
../../CURRENT_STAGE_PROGRESS.md;计划与交接PLAN-P12.md;任务书BRIEF-onscreen.md;裁定INTEGRATOR-DECISIONS-P12.md(ID-P12-1..15);只读审计map-*.md四份。 - 形状:server APK 自建
ANativeWindow(MobileGLDisplayActivity的 SurfaceView,进程内 TCP server,会话串行)把渲染流上屏;离屏路径保留、同一时刻一条活跃;client 以WindowKind::ServerOwned(控制修订 3)完全无头接入,几何由 server 回传;失窗 →Fatal{ServerWindowLost}→ 干净 device-lost。 - 进展:15 个
(P12)提交 + 审查轮修复(10 个问题,ID-P12-5..11)已并入feat/disaggregated;主机门绿(ID-P12-14)、G1 成立(ID-P12-15);审查后在1fb18d9e上完成 P12 定向 CTest 46/46 和 Redmi 真机七项复测。当前分支0fe01588后续提交只改了文档、文档检查范围和基准脚本说明文字,未改 P12 实现。 - 2026-09-25 追加(会话交接 §4/§5.1):device-lost 的 DECLINED 回复容忍与纹理上传的等待粒度已落地,各有自己的 red-once 门(前者就是进世界后
Fatal{ProtocolCorruption, "Fence.reply"}那条崩溃;后者让单条纯上传的回包等待 1 → 0)。真机端到端(进世界不崩、那一帧墙钟)与 G1 本机复核仍待做,见DEVICELOST-AND-UPLOAD-WAITS.md。 - 未完成:出口门 (a) FCL 同机 spawn + 杀 server 的 device-lost、(b) 跨机 TCP 入世界 + P6.5 必测数;
CONTRACT-P12.md;阶段表行里的其余条目(unix:监听、DirectGLES 去全局、freezer、多 context、FCL 开关接线、D8 白名单)。
阶段表行(原 ROADMAP.md)
- 阶段:P12 Android 生产窗口路径
- 状态:子集已实现、未收官(2026-09-25):上屏 server 窗口、
WindowKind::ServerOwned、无头 client、失窗 device-lost 已落地;审查轮 10 个问题已修(两个大项:批内失窗、会话间 Espryt 单元影子悬空;裁定INTEGRATOR-DECISIONS-P12.mdID-P12-5–11)。审查后 P12 定向 CTest 46/46、真机七项复测通过;出口门 (a) FCL + 杀 server 与 (b) 跨机 TCP 仍未完成(见PLAN-P12.md§3)。 - 落地什么 / 范围:按重审 §6 改小:
Service 收 Java删掉 Surface 传递那一半——server app 拥有自己的 SurfaceView,client 根本没有窗口,于是 minSdk 26 没有扁平化SurfaceANativeWindow的 NDK API 这条约束不再成立;WindowKind::ServerOwned;两个后端各一条CreateEGLWindowSurface臂;m_windowHandle四处写点 +sameHandle去重键(a6 §6);DirectGLESg_Display/g_Surface/g_Context去全局;kEventSurfaceChanged的 Width / Height 缺口(Espryt 只发布格式,server 拥有显示时 client 默认 FBO 会停在 512×512 占位值);client 侧不再无条件发SetWindowHandle(BackendObject_Remote.cpp:215——今天 FCL 里开 spawn,第一次eglCreateWindowSurface就在 server 进程 abort);server app 监听unix:与tcp://(后者 Ph 之后);server 生命周期绑 Activity;cached-app freezer(SPAWN-PLAN §8.2);多 context(契约 §11);FCL env 与 plugin APK 开关表接线 - 验收门 / 证据:两个门:(a) Minecraft 经 FCL 同机 spawn 在 Adreno 830 双后端入世界,杀 server 产生干净 device-lost latch;(b) 另一台机器上的 client 经 TCP 在 Redmi 上进世界(数据面 stream),并记录 P6.5 的必测数
2026-09-25 复测补记
复测针对 P12 实现提交 1fb18d9e(控制协议修订 3);当前 feat/disaggregated@0fe01588 相对它只改了文档、文档检查范围和基准脚本说明文字。测试 APK 为 26.09.1fb18d9-trace(独立包名 top.mobilegl.plugin.p12verify.trace),设备为 Redmi 2f7cbe2e(Adreno 830)。本记录只覆盖 P12 定向用例,不表示两个收官出口门已通过。
主机 P12 定向 CTest:46/46 通过。 包含 ServerDisplayTest、ServerLoopTest、InProcessServer、SupervisorChildren 与 ServerOwnedSurface;不是整套 P12 主机门重跑。
真机七项检查:
| # | 检查 | 审查后结果 |
|---|---|---|
| 1 | Espryt 上屏(OpenRA) | 通过,SSIM 1.000000,server-owned window 640×480 |
| 2 | Magma 上屏(OpenRA)及同进程第二会话(Minecraft startup) | 通过,SSIM 1.000000 / 0.999999511 |
| 3 | 串行会话与 Busy | 第二次 OpenRA 通过,SSIM 1.000000;并发客户端收到 Refuse{Busy}(rc=134),长 Minecraft 会话继续并以 SSIM 0.999999511 完成 |
| 4 | 推流时按 HOME 触发 surfaceDestroyed |
ServerWindowLost 后客户端干净 device-lost;Activity 进程存活,surface 在 15 ms 内释放;重附窗口后的 OpenRA 会话 SSIM 1.000000 |
| 5 | 离屏 service(pbuffer) | OpenRA 通过,SSIM 1.000000 |
| 6 | 离屏 server 收到 ServerOwned 请求 | 服务端和客户端都返回 NoServerDisplay;后续 pbuffer 会话通过,SSIM 1.000000。首次尝试与上一会话回收竞态命中 Busy;临时测试副本等待 2 秒后重跑通过,仓库脚本未修改 |
| 7 | Activity 与离屏 service 互斥 | 启动 Activity 会停止 service 及其活动会话;启动 service 会停止 :mglwin,之后 service 正常监听 |
设备检查通过 adb forward 由 trace_replay 驱动;失窗检查使用 HOME,不是 FCL 杀 server。出口门 (a) 的 FCL 同机 spawn / 杀 server,以及出口门 (b) 的跨机 TCP 入世界与 P6.5 必测数仍未验证。
运行证据保存在测试机器的 /home/swung/w7/logs/p12-verify-1fb18d9e/(build-host/Testing/Temporary/LastTest.log 与 device/);按证据数据规则,大日志、APK 和截图未复制进仓库。
状态记录(原 CURRENT_STAGE_STATUS.md,2026-09-24 历史快照)
本段保留当日记录;其中“审查后未复测”的状态已由上方 2026-09-25 复测补记更新。
更新:2026-09-24(P12 子集) · 计划与交接 notes/p12/PLAN-P12.md。P12「server 自有屏幕窗口」子集已实现、未收官,已并入 feat/disaggregated(15 提交自 9f669e52 起,加审查轮 10 个问题的修复——两个大项:批内失窗、会话间 Espryt 单元影子悬空;裁定 notes/p12/INTEGRATOR-DECISIONS-P12.md ID-P12-5–15,主机门与 G1 见 ID-P12-14/15,审查轮之后未上真机复测,ID-P12-13):Android 上的 server 自建 ANativeWindow(自己的 SurfaceView)把渲染流上屏,离屏路径保留,同一时刻只一条活跃;client 以新的 WindowKind::ServerOwned 完全无头接入(控制修订 3)。主机门除一条既有环境敏感项外全绿,G1(pull 构建 .text 0xa52203、符号 0/0)已独立复核;真机 Redmi 2f7cbe2e 上七项编号检查过了双后端上屏、串行/Busy、失窗 device-lost、离屏不回归、无显示具名拒绝、一台设备一个 server。两个出口门都还没打:跨机 TCP(门 b)完全未做,FCL + 杀 server 的 device-lost(门 a)未做——本轮的真机是 trace_replay 经 adb forward 环路驱动的。上一阶段 P7 已收官(2026-09-23,ID-P7-63):§8 九项全绿——终局窗口 3(p7w8-78e71f2b)门 3 PASS 36/36、门 5 PASS;门 4 以 # P13 读法关闭。
- P12 子集:APK
26.09.29b7b28-trace(控制协议修订 3,与 p7w8 的 server 不兼容),证据notes/p12/device/(九格拼图evidence-strip.png)。七个编号检查在三个 head 上跑过,trial-*/是按 head 归档的旧轮次。
当前状态详情(2026-09-24,原 CURRENT_STAGE_PROGRESS.md 正文)
顶层
CURRENT_STAGE_PROGRESS.md只留摘要;带裁定编号的落地表、门表、余项清单与证据位置在这里。
1. 一句话(2026-09-24 历史快照;现状见上方复测补记)
Android 上的 server 自建窗口(自己的 SurfaceView)把 IPC 渲染流上屏,client 以 WindowKind::ServerOwned 完全无头接入。该快照记录当时审查轮修复后尚欠真机复测;复测现已在上方补记,两个出口门仍未打。
2. 已落地
| 面 | 内容 | 出处 |
|---|---|---|
| wire | WindowKind::ServerOwned、控制修订 2 → 3、SurfaceReply 带回窗口真实尺寸或具名拒绝 |
PLAN-P12 §1 |
| server 窗口 | ServerDisplay(钩子 + 租约 + 有界 3 s Detach);会话表面模式首次创建即闩定(SurfaceModeMismatch);无显示具名拒绝(NoServerDisplay);失窗 → Fatal{ServerWindowLost} → client 读干净 device-lost |
ID-P12-2、ID-P12-3 |
| client | MOBILEGL_IPC_SURFACE=server → 无头窗口 surface,不发 SetWindowHandle;resize 变成对 server 窗口的几何请求,采用 server 回的真实尺寸 |
ID-P12-10 |
| 进程内 server | MobileGLDisplayActivity(:mglwin)里一个线程跑 TCP server:会话串行、会话间重置闩、后端按进程钉住;与离屏 MobileGLServerService 互斥,一台设备同一时刻一个 server |
ID-P12-4 |
| 审查轮 | 10 个问题已修;两个大项:批内失窗检查(DrainRing 每次 pop 前)、会话间 Espryt 单元影子悬空;另有推流中停机、会话结束清理、陈旧尺寸、日志转发 |
ID-P12-5 … 11 |
3. 门
| 门 | 状态 | 证据 |
|---|---|---|
| G1 | ✅ pull 构建同机前后 .text 一致、符号 0 增 0 减 |
ID-P12-15 |
| 主机门 | ✅ unit 2605/2605,spawn / tcp 与三条 Magma 双进程车道全绿;剩余红全部归容器的 CMake/CTest 版本 | ID-P12-14 |
真机七项检查(Redmi 2f7cbe2e) |
✅ 审查轮之前(29b7b284)及审查后(1fb18d9e);审查后详细结果见上方复测补记 |
PLAN-P12 §2、ID-P12-13 |
| 出口门 (a) | ❌ FCL 同机 spawn、双后端入世界、杀 server 产生干净 device-lost(本轮的驱动是 trace_replay,device-lost 由按 HOME 触发) | PLAN-P12 §3 |
| 出口门 (b) | ❌ 另一台机器的 client 经 TCP 在 Redmi 入世界,并记录 P6.5 必测数(本轮 client 是 adb forward 环路) |
PLAN-P12 §3 |
4. 在跑
无。
5. 下一步
- 出口门:先 (b) 跨机 TCP 入世界 + P6.5 必测数,再 (a) FCL + 杀 server。
- 收尾:写
MG_Remote/CONTRACT-P12.md;修notes/p12/gate.sh的 G1 符号比较(与基准不同源,会印出误导的added=N removed=N);按惯例做一次收官审查。 - 阶段表行里的余项(交接时在树上核过,均未做):in-process server 的
unix:监听、DirectGLESg_Display/g_Surface/g_Context去全局、cached-app freezer、多 context、FCL env 与 plugin 开关表接线、D8 窗口种类白名单。 - 其后按
ROADMAP.md:monolith 跑道 P8;IPC 跑道 P9 → P10 → P11;P6.5 残余(39 例 device 矩阵 + 必测数)与 P3b/P4b 余项并行;CONTRACT-P7.md§12 的记录债按阶段认领。
6. 阻塞 / 需要人
- 没有需要用户决策的阻塞。真机复测需要一台装有 NDK、连着 Redmi 的机器(审查轮所在的云容器没有)。
- 已知环境敏感项:
IterationRPProgram203Scenario(integration-magma-full-split)偶发红,按 ID-P7-22 / ID-P12-12 读作"既有、环境敏感"(钉 lavapipe ICD 即绿),不阻塞 P12。
7. 真机与证据
- 当前 APK
26.09.29b7b28-trace(控制修订 3,与 P7 终局窗口的 p7w8 server 不兼容);设备 Redmi2f7cbe2e(Adreno 830),定频协议devices/pin-verification-2026-09-07.md。 - 真机证据
notes/p12/device/(evidence-strip.png九格拼图,trial-*/是按 head 归档的旧轮次);主机门日志notes/p12/gate/;设备脚本notes/p12/android/。
本目录
| 文件 | 内容 |
|---|---|
DEVICELOST-AND-UPLOAD-WAITS.md |
2026-09-25 落地记录:DECLINED 回复容忍(A)与纹理上传等待粒度(B),含门、red-once 与未做项 |
BRIEF-onscreen.md |
P12 subset "on-screen server window" — implementation brief (2026-09-23) |
fix-icd.sh |
钉 lavapipe ICD |
g1-base-names.sh |
G1 基准符号名生成 |
gate-container.sh |
主机门的容器变体 |
gate.sh |
主机门脚本 |
INTEGRATOR-DECISIONS-P12.md |
P12 集成者裁定日志(「server 自有屏幕窗口」子集) |
map-apk-process.md |
MobileGL-disagg: Android APK and process model for an on-screen server path (commit 9f669e52) |
map-client-surface.md |
Client-side surfaces in split mode: map, open questions and change list (commit 9f669e52) |
map-docs-contract.md |
Design docs and contracts for a server-owned on-screen window (P12 subset) |
map-server-surface.md |
Server-side surface path and both backends' window surfaces (commit 9f669e52) |
p203.sh |
IterationRPProgram203Scenario 复核 |
PLAN-P12.md |
P12「server 自有屏幕窗口」子集 — 计划与交接(2026-09-24) |
setup-tree.sh |
包树搭建 |
android/ |
27 个文件:真机与构建脚本(dev.sh、check*.sh、final-run.sh、red-once 工具等) |
device/ |
85 个文件:真机七项检查证据(evidence-strip.png 九格拼图;trial-*/ 为按 head 归档的旧轮次) |
gate/ |
6 个文件:三个 head 的构建日志与主机门日志(含审查轮、CMake 4 对照) |