12 KiB
P12「server 自有屏幕窗口」子集 — 计划与交接(2026-09-24)
接 P7 收官(
../p7/HANDOFF-2026-09-23.md)。基线feat/disaggregated@9f669e52。 包树~/w7/p12-onscreen,分支p12/onscreen(从9f669e52分出,15 个(P12)提交)。 任务书BRIEF-onscreen.md,只读审计map-*.md(四份),本页是交接与余项。
1. 这一包做了什么
按用户裁定(BRIEF-onscreen.md §User rulings,四条):Android 上的 server 自己创建
ANativeWindow(自己的 SurfaceView),把 IPC 渲染流渲染到屏幕上;离屏(pbuffer)与上屏两条路径都保留,
同一时刻只有一条活跃,在 server 初始化 / context 创建时决定;拓扑为进程内 server——display Activity
自己的进程里用一个线程跑 TCP server 并直接渲染进它的 SurfaceView,会话在该进程内串行;client 侧用一个
新的 WindowKind::ServerOwned 接入,且此模式下 client 完全无头(eglCreateWindowSurface 接受 NULL),
窗口几何由 server 回传。
落地的形状(15 提交,53 文件,+4566/−110):
| 面 | 内容 |
|---|---|
| wire | WindowKind::ServerOwned = 7(fbs 追加)、控制修订 2 → 3、SurfaceRefusal / SurfaceReply(width/height/refusal)、codec 的 ServerOwned 规则(仅 CreateWindowSurface、nativeToken == 0、SetWindowHandle 具名拒绝)、非零 token 的 latch 行 |
| server 窗口 | MG_Remote/Server/ServerDisplay.{h,cpp}(不透明窗口 + hooks + lease + 有界 Detach)、ServerOwned 臂的 one-mode-per-session latch、无显示时的具名拒绝、失窗在 apply 线程释放、ServerWindowLost 家族行 |
| client | MOBILEGL_IPC_SURFACE=server(Config.h / ConfigLoader.cpp)→ 无头窗口 surface、一次 ServerOwned CreateWindowSurface、不发 SetWindowHandle、geteometry 进 EGL state 后才返回 |
| 进程内 server | RunSession 改为返回退出码、TcpSupervisor 把已认证会话交给线程(Busy / 会话间 ResetSessionLatch / 后端按进程钉住 / 非阻塞 stop)、fork 出的会话子进程 PR_SET_PDEATHSIG 随监督进程去 |
| Android | MobileGLDisplayActivity(:mglwin,全屏 SurfaceView,aspect-fit,env 在库加载前应用)、display server 的 JNI(DisplayServerJni.cpp + 几何 up-call)、与 MobileGLServerService 共享环境、同一时刻只有一个 server(Activity 停 service,service 杀 :mglwin) |
| 工具 | tcp_device_server.py --surface window|pbuffer、Linux glws 的 MOBILEGL_TRACE_SURFACE=window |
| Espryt | 远端会话的 window-surface extent 随其默认 framebuffer 格式发布(仅 split 构建,pull 构建不动;G1) |
2. 门与证据
G1(硬约束):pull 构建 .text 0xa52203 不变、符号 0 增 0 减。门日志 gate/gate-android1.log 报
a52203,但那一行印的是 added=30570 removed=30570——这是错的读法:比较基准
~/w7/logs/p12/pull-syms-base.txt 是用 nm --defined-only … | awk '{print $3}' 生成的(每个目标文件
的符号头行 + 符号),而比较时用的是无 awk 的全量 nm 输出,两边不同源,于是"全部新增又全部删除"。
交接时已独立复核:在 ~/w7/pipe(pull 构建,恰在 9f669e52)与 p12-onscreen 两个 build-linux 上
直接 nm --defined-only | awk '{print $3}' | sort 后 comm,added 0 / removed 0,符号集各 30570 全同;
readelf -S 两边 .text 都是 a52203。G1 成立;门脚本的那一行输出应在 P12 收尾时修好(见 §4)。
主机门(gate/gate-android1.log,head 29b7b284,dirty=0,2026-09-24 00:55–01:04):
- unit 2601、integration-split 322、spawn 239、tcp 243、magma-split 125、magma-spawn 104、magma-tcp 89、 integration-gpu 2188 × 2(monolith / inproc)全绿。
integration-magma-full-split558 报 1 红(IterationRPProgram203Scenario的 exposure texel)。这不是本包引入的: 交接时独立复核,用 ctest 注册的那组环境变量直跑该用例,p12-onscreen3/3 绿、mismatches=0/262656; 整条车道-j 8重跑两遍也 558/558 绿。它是既有/环境敏感项,树上早有记录:../p05/p05-results/value-types-v1.md判为构建目录 configure 差异(MG_IntegrationTest/CMakeLists.txt只在MOBILEGL_ITEST_VK_ICD匹配lvp_icd|lavapipe时才挂三个MOBILEGL_MAGMA_*修复开关),../p7/magma-a.md§6.2 记它在该 worktree 3/3 稳定红且还原后端改动照样红,../p7/INTEGRATOR-DECISIONS-P7.mdID-P7-22 改判为"环境敏感而非 tcp 专属"。p12-onscreen两个 build 目录的MOBILEGL_ITEST_VK_ICD都已钉到 lavapipe,ctest -N -V确认注册时带着三个修复变量。- 卫生 12 项全 OK;fatal census 79 / link ratchet 171 不变;parity 0;protocol revision pin 报 revision 3 holds。
真机(Redmi 2f7cbe2e,Adreno 830,证据 device/,device/evidence-strip.png 为九格拼图):
七个编号检查在两个 head(984db455、a4a940db、29b7b284)上跑过,trial-*/ 是按 head 归档的旧轮次。
| # | 检查 | 结果 |
|---|---|---|
| 1 | Espryt 上屏(OpenRA,--window-surface,MOBILEGL_IPC_SURFACE=server) |
ssim 1.000000;server 日志 surface=window 640x480 owner=server;屏幕截图非黑 |
| 2 | Magma 上屏(OpenRA)+ 同进程第二个会话(minecraft-1.21.4-startup) |
ssim 1.000000 / 0.999999511;两臂都 owner=server |
| 3 | 串行第二会话 + Refuse{Busy} |
第二会话绿;并发客户端拿到 Refuse{Busy}(rc=134)后长会话照常收尾绿 |
| 4 | 失窗(surfaceDestroyed) |
Fatal{ServerWindowLost} → 会话 latch → client 读干净 device lost;Activity 回来后新会话 ssim 1.0,:mglwin 存活 |
| 5 | 离屏 service(不带旋钮) | ssim 1.0,surface=pbuffer 640x480(离屏路径未被破坏) |
| 6 | 负控:MOBILEGL_IPC_SURFACE=server 打离屏 server |
双侧具名 Refuse ServerOwned (NoServerDisplay);随后同 service 的离屏会话绿 |
| 7 | 一台设备上只有一个 server | Activity 起来杀 service、service 起来杀 :mglwin,互相都验证了 |
审查后复测(feat/disaggregated@1fb18d9e,2026-09-24)
审查修复后的同一 P12 实现 head 已在 Redmi 2f7cbe2e(Adreno 830)重建并复跑七项检查。结果与上表一致:Espryt OpenRA SSIM 1.000000;Magma OpenRA / Minecraft startup 1.000000 / 0.999999511;串行第二会话和 Refuse{Busy} 通过;HOME 失窗得到 ServerWindowLost 干净 device-lost,surface 释放 15 ms,Activity 存活且重附后新会话 SSIM 1.0;pbuffer 与 NoServerDisplay 负控通过;Activity / service 互斥通过。第 6 项初次尝试与上一会话回收竞态命中 Busy;临时测试副本等待 2 秒后重跑,双侧具名拒绝和后续 pbuffer 会话均通过,仓库脚本未改。
审查后主机 P12 定向 CTest 46/46 通过:ServerDisplayTest、ServerLoopTest、InProcessServer、SupervisorChildren、ServerOwnedSurface。这组定向测试不等于完整主机门。证据在测试机 /home/swung/w7/logs/p12-verify-1fb18d9e/;日志、APK 和截图按证据数据规则未入仓库。当前 0fe01588 相对验证 head 只有文档整理及文档检查配置更新。
3. 还没做(P12 未收官)
按 ../ROADMAP.md P12 行的两个出口门,以及本包任务书列出的改小后的条目:
- 出口门 (a) 未达成。 要求 FCL 同机 spawn、双后端入世界、杀 server 产生干净 device-lost latch。
今天验证到的是:trace_replay(不是 FCL)经
--window-surface+MOBILEGL_IPC_SURFACE=server在屏上重放 OpenRA, 双后端都 1.0;device-lost 是**按 HOME(surfaceDestroyed)**触发的,不是杀 server。 - 出口门 (b) 完全未做。 要求另一台机器上的 client 经 TCP 在 Redmi 入世界并记录 P6.5 的必测数。
本轮的 client 是
adb forward后的tcp://127.0.0.1:40613环路(android/dev.sh:7-8写得很清楚), 不是跨机。 - ROADMAP P12 行里仍未落地的条目(交接时在树上核过):
unix:监听(in-process server 只做了 tcp;grep 'unix:' ServerMain.cpp为 0);- DirectGLES
g_Display/g_Surface/g_Context去全局(DirectGLES.cpp仍有 40 处); - cached-app freezer 的"完整处理"(树上 0 处提及);文档从未定义它是什么,
SPAWN-PLAN.md§8.2 只说了它是 P12 的; - 多 context(契约 §11);
- FCL env 与 plugin APK 开关表接线;
AndroidNativeWindow@P12/MetalLayer@P12的 D8 白名单(拒 X11 / Win32Hwnd / None)——map-docs-contract.md§5.3 记它 没落地,且当时SetWindowHandle在 client 侧无条件发;本轮把 ServerOwned 模式下的SetWindowHandle变成了具名拒绝,但 D8 本身(X11/Win32 白名单)仍是独立跟进项。
- 文档债(
map-docs-contract.md§4 列的"落地时要记录的东西"):- 没有
MG_Remote/CONTRACT-P12.md(前几个阶段都有;本页与BRIEF-onscreen.md不是契约); - 没有
INTEGRATOR-DECISIONS-P12.md式的逐条裁定; ARCHITECTURE.md:526仍写着被删掉的 Surface → AIDL →ANativeWindow_fromSurface旧路径,protocol.fbs:258仍写「Android transfers the window out of band」,ARCHITECTURE.md:533仍描述 RESPAWN / IDLE_EXIT 可用;CURRENT_STAGE_PROGRESS.md:244仍把 P12 描述成"real windows cross processes",与 Rule H 冲突;- IPC 顺序(
ROADMAP.md:19的 P6.5 → Ph → P12 → P9 与CURRENT_STAGE_STATUS.md/ HANDOFF 的 P9 → P10 → P11 → P12)两处说法仍不一致; - a6 行 A8-3…A8-15 的处置、CONTRACT-P6 §7.2 D8 的处置都还没写;
- 阶段收尾该有一次 Codex 审查(
ROADMAP.md:17的惯例)。
- 没有
MG_Test/SanityTest.cpp在本包里被改动过——它属于 pull 构建之外的测试目标,但要确认它与 G1 的关系已在门里测到(门已绿,此处只是点名)。
4. 立刻可做的收尾
- 把
~/w7/notes/p12/gate.sh的 G1 符号比较改成与基准同源(nm --defined-only … | awk '{print $3}'), 否则下一个跑门的人还会看到added=N removed=N而误判。 - 决定
IterationRPProgram203Scenario在 P12 的处置:既然 ID-P7-22 已判"环境敏感",把它在门里的 出现方式(钉 ICD 即可绿 / 记为已知偶发)写成一句结论,别再一次次口头带过。 - 若要真正收官 P12:先补跨机 TCP(出口门 b),再补 FCL + 杀 server 的 device-lost(出口门 a),
最后写
CONTRACT-P12.md并按惯例做一次收官审查。
5. 工装在哪
- 任务书与审计:本目录
BRIEF-onscreen.md、map-apk-process.md、map-client-surface.md、map-docs-contract.md、map-server-surface.md。 - 门与包树:
gate.sh、setup-tree.sh、fix-icd.sh、g1-base-names.sh、p203.sh;主机门日志gate/。 - 真机:
android/(dev.sh、check1/3/4/5/7.sh、final-run.sh、precheck.sh、redonce-tools.sh、redonce-twins.sh、hostrepro.sh、verify-apk.sh等),证据device/。 - 没进仓库的(按
../notes/README.md"证据数据"的规则):~/w7/logs/p12/device/**/logcat*.txt等约 66 MB 设备日志、APK、pull-syms-base.txt*(2.5 MB nm 转储)。要复核请去产生它们的机器。