docs: record STEP-057 weather runtime facade
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
OpenAI Codex
2026-09-07 10:43:59 +08:00
parent a81b464d9b
commit efaa3e61c9
4 changed files with 105 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
# STEP-057 Android Host 天气运行时接口契约
## 入口与线程
公开入口为 `org.maplibre.android.maps.WeatherRuntime`,由 Android 主线程创建和调用。`MapLibreMap` 同样要求主线程访问;本 facade 不创建 Timer、线程或 per-frame Java 回调。Core 继续在其既有 Map/Render 线程完成 Timeline、窗口和 GPU 工作。
`WeatherRuntime.Config(sourceId, weatherColorLayerId, particleLayerId)` 绑定一个已存在的 style runtime;ID 不可为空,未硬编码 Test App ID。
## API
- `submitWindField(metadataJson, byte[]) -> FieldSubmitResult`:复用 canonical ingress。结果逐一映射 `REJECTED_*`、`ACCEPTED_PENDING_INITIAL_WINDOW`、`INITIAL_WINDOW_READY`、`ACCEPTED_NEXT_SNAPSHOT`、`DUPLICATE`。
- `clearWindFields() -> CommandResult`:暂停 Timeline,清除 pending T0、Timeline entries、authoritative T0/T1 和 retained snapshots;Source/Layer 可复用。
- `setWeatherEnabled(boolean)`:OFF 暂停、隐藏两层并 clear fields;Render 线程发现空场时释放粒子 State/Trail/draw、field texture 和 WeatherColor 资源。ON 只恢复 visibility,状态为 `WAITING_FOR_FIELDS`,必须重新提交 T0/T1。
- `setWeatherColorVisible` / `setParticleVisible`:仅 visibility,`hide != unload`。
- `setForecastTime(timestampMs)`:Core 按 timestamp 选相邻 T0/T1 并计算 MIX。恰好命中末快照为 MIX=1;中间线性插值;超范围、未 READY、Gap/Invalid 返回 `REJECTED`,不会沿用错误旧时间。正常 seek 不 submit field、不 reset particle、不 clear trail;仅跨窗口时沿用既有 OLD_T1→NEW_T0 reuse。
- `setPlaybackState(PLAY/PAUSE)`、`setPlaybackSpeed(HALF/NORMAL/DOUBLE)`:复用 Source Timeline,不创建 Android Timer。
- `setWeatherColorOpacity`、`setParticleVisual`:低频 visual 更新。
- `setWeatherColorStops(List<ColorStop>)`:2 至 8 个 stop,speed finite 严格递增,RGBA 均为有限 [0,1]。低于/高于边界分别钳到首/末颜色,中间线性插值。无效输入 reject,并保留上一套有效 ramp。
- `setParticleColors(...)`:独立 particle/trail RGBA;不依赖 WeatherColor ramp。legacy `speed-color-enabled=true` 时仅当前 segment 可使用旧 speed 色,不改变 WeatherColor stops。
状态为 `DISABLED`、`WAITING_FOR_FIELDS`、`READY`、`ERROR`,仅由低频命令和 submit result 更新。v1 提供同步 typed result/state query;没有 listener,未来 RN 薄层可在这些调用完成后读取结果。
## JNI 与边界
Java facade 经 `MapLibreMap` / `NativeMapView` 到 JNI:field submit、clear、timestamp seek、Timeline command、layer visibility、particle/trail colour、WeatherColor stops。C++ Renderer 不接触 provider、HTTP、route、ETA 或预测目录;没有向 Host 暴露 T0/T1、MIX、State A/B、Trail A/B、资源代际或 texture 格式。
Shader-visible ramp 是 UBO 的 8 个 stop/颜色槽;改 ramp 不上传 Field,也不重建粒子 simulation。粒子/尾迹颜色也只更新 UBO。

View File

@@ -0,0 +1,15 @@
# STEP-057 Android Host 天气运行时接口基础
状态:`IMPLEMENTED / WAITING_ANDROID_VALIDATION`。
Starting HEAD:`faf7548220e9a1282275711c236987f7faedfa03`,分支 `particle/main`。
已实现:Android `WeatherRuntime` typed facade;canonical byte[] submit result enum;clear fields;timestamp seek;play/pause/0.5/1/2x;独立 visibility;OFF unload;WeatherColor 8-stop dynamic ramp;独立 particle/trail RGBA;Android→JNI→C++ 接线;REAL WEATHER Test App submit/playback 改走 facade。
Core 保持 canonical U/V、Timeline、Runtime Field Window、T0/T1 interpolation 和 Renderer 架构边界。正常窗口边界的 GPU content reuse 路径未改变;normal seek 不改变 window revision,跨窗口仍由既有 revision 驱动 reuse。
OFF 会停止 Timeline、clear Host ownership,并在 Render 线程的空 Source path 清理 layer drawables、particle State/Trail/draw targets、field textures 和 WeatherColor resources。结构化日志包括 `TIMELINE_STOP`、`FIELD_WINDOW_CLEAR`、`SNAPSHOT_CLEAR`、`PARTICLE_RESOURCE_RELEASE`、`TRAIL_RESOURCE_RELEASE`、`WEATHER_COLOR_RESOURCE_RELEASE`。
本地验证:shader generator、Linux OpenGL `mbgl-core`、`style_layer.test.cpp` 与 `source.test.cpp` 精确编译;`git diff --check`。Android Gradle/APK/ADB/设备测试和 Jest 未运行。
未完成:Android 手工 T1–T13 验收,特别是 OFF resource log、ON 后重新 T0/T1、dynamic ramp/colour 无 field upload/particle reset、timestamp mid-point 和窗口边界回归。

View File

@@ -0,0 +1,56 @@
# STEP-057 Android Host 天气运行时接口基础 — Codex 完成报告
## 状态
`IMPLEMENTED / WAITING_ANDROID_VALIDATION`。
- Starting HEAD:`faf7548220e9a1282275711c236987f7faedfa03`
- 功能提交:`a81b464d9b6381ae5b2fb953358d25c20d62bb78` — `feat: add Android host weather runtime facade`
- 文档提交:本报告所在提交
- Final HEAD / origin/particle/main:在文档提交并 push 后记录于交付结果。
## 实际完成内容与 API
新增 `org.maplibre.android.maps.WeatherRuntime`,以 `Config(sourceId, weatherColorLayerId, particleLayerId)` 作为唯一 Host 绑定。公开方法为 `submitWindField`、`clearWindFields`、`setWeatherEnabled`、两个 visibility setter、`setForecastTime`、play/pause/speed、WeatherColor opacity、particle visual、`setWeatherColorStops`、`setParticleColors` 和 `getState`。
`FieldSubmitResult` 逐一映射现有 Core result,`CommandResult` 和 `State(DISABLED/WAITING_FOR_FIELDS/READY/ERROR)` 供未来 RN 薄包装读取;无 per-frame callback。Host 不得到 T0/T1、MIX、State/Trail、纹理或 renderer resource。
Android → JNI → C++ 新接线为:visibility、particle/trail RGBA、WeatherColor stop arrays,以及既有 submit/clear/timestamp/timeline command。Test App 的 REAL WEATHER 提交和基础播放控制已走 facade。
`clearWindFields` 清除 pending T0、Timeline、authoritative window 与 Source snapshots。`setWeatherEnabled(false)` 暂停、隐藏两层、clear fields;渲染线程的空 Source path 清理 particle State/Trail/draw、field textures、WeatherColor resources,保留 Source/Layer 以支持 ON 后重新提交。日志包含 `TIMELINE_STOP`、`FIELD_WINDOW_CLEAR`、`SNAPSHOT_CLEAR` 与三类 resource release。
WeatherColor ramp 最多 8 stop,要求 2 个以上、speed finite 严格递增、RGBA 为有限 [0,1];无效更新 reject 且保留上一有效 ramp。UBO 实现低频更新,不上传 wind field。`particleColor` 和 `trailColor` 为独立 UBO 属性;不读取 WeatherColor ramp。legacy speed color 只在显式开启时影响当前粒子 segment。
timestamp 恰好 T0、T1 和中间值均由 Core 选择相邻快照和 MIX;中间插值。超范围、空 timeline、Gap/Invalid 返回 reject。window 未切换的 seek 不增加 revision,因而不造成 field upload、simulation rebuild 或 trail clear;跨窗口仍走 OLD_T1→NEW_T0 reuse。
## 修改文件
功能修改覆盖 Android Java facade/NativeMap/JNI、RasterArraySource Timeline、WeatherColor/RasterParticle style model、particle UBO/shader、两个 renderer、RenderOrchestrator、REAL WEATHER Test App 以及 `test/style/source.test.cpp`、`test/style/style_layer.test.cpp`。完整逐文件清单可由功能提交取得;接口契约见 `docs/30_设计/STEP-057_AndroidHost天气运行时接口契约_v1.md`。
## 本地验证
- `node shaders/generate_shader_code.mjs -o .`:PASS。
- `ninja -C build-linux-opengl -j3 mbgl-core`:PASS。
- `ninja -C build-linux-opengl -j3 test/CMakeFiles/mbgl-test.dir/style/style_layer.test.cpp.o test/CMakeFiles/mbgl-test.dir/style/source.test.cpp.o`:PASS。
- `build-linux-opengl/mbgl-test-runner --gtest_filter='Source.HostFieldClearAndTimestampSeekAreFailClosed:Layer.RasterParticleVisualProperties:Layer.WeatherColorUsesIndependentFixedOpacity'`:PASS。
- `git diff --check`:PASS。
所有 build/codegen/test 命令均通过 `~/.codex/AGENTS.md` 要求的 output-throttle wrapper 执行;日志保存在本机 `/tmp/step057-logs/`,不纳入提交。
## 未执行与风险
Android Gradle:NOT RUN。APK build:NOT RUN。ADB:NOT RUN。Android device validation:NOT RUN。Jest:NOT RUN。
Linux OpenGL 不能证明 Android OpenGL/Vulkan JNI/GLSL runtime 行为;Android 手工验收需确认 OFF 后三个 release 日志、连续 ON/OFF 内存、动态 ramp/particle/trail color 无 field upload 或 reset、timestamp 中点、playback 和 T0/T1 window boundary 的 zero-reset 保护。
建议手工命令(设备固定为 `192.168.1.146`):
```bash
cd platform/android && RENDERER=opengl BUILDTYPE=Debug make apackage
# APK: platform/android/MapLibreAndroidTestApp/build/outputs/apk/debug/MapLibreAndroidTestApp-debug.apk
adb -s 192.168.1.146 install -r MapLibreAndroidTestApp/build/outputs/apk/debug/MapLibreAndroidTestApp-debug.apk
adb -s 192.168.1.146 shell am start -n org.maplibre.android.testapp/.activity.particle.ParticleCoreLayerValidationActivity
adb -s 192.168.1.146 logcat -v time | grep -E 'WeatherRuntime|ParticleTimeline|ParticleGPU|WeatherColorLayer'
```
Windows 安装同样使用:`adb -s 192.168.1.146 install -r <Windows 上实际生成的 MapLibreAndroidTestApp-debug.apk>`;使用同一显式设备序列号。

View File

@@ -449,3 +449,10 @@ WeatherColorLayer 的 `ParticleGpuValidationUBO` designated initializer 补齐 `
- 仓库当前没有 React Native/TurboModule/Fabric/JSI binding;可复用正式入口是 Android `byte[] → JNI → RasterArraySource::submitHostField()`,它已接入 canonical Adapter/Snapshot、Core Timeline/Window 与两个 GPU layer。 - 仓库当前没有 React Native/TurboModule/Fabric/JSI binding;可复用正式入口是 Android `byte[] → JNI → RasterArraySource::submitHostField()`,它已接入 canonical Adapter/Snapshot、Core Timeline/Window 与两个 GPU layer。
- 推荐先建立 Android Host Weather Runtime typed facade:runtime unload/clear、canonical field submit、timestamp playback、visibility/style 和低频 result/event;RN module 应在具备 RN host/build dependency 的后续任务中薄包裹该 facade。 - 推荐先建立 Android Host Weather Runtime typed facade:runtime unload/clear、canonical field submit、timestamp playback、visibility/style 和低频 result/event;RN module 应在具备 RN host/build dependency 的后续任务中薄包裹该 facade。
- 单帧 WeatherV2 payload 为 3,155,976 bytes;RN v1 应先稳定复用 byte[] path,zero-copy/direct ByteBuffer 仅在 profiling 后处理。动态 WeatherColor stops、独立 particle/trail color 和 weather-local targetFps 均是当前缺口;后者应独立性能批次,不能使用全图 `MapView#setMaximumFps()` 冒充。 - 单帧 WeatherV2 payload 为 3,155,976 bytes;RN v1 应先稳定复用 byte[] path,zero-copy/direct ByteBuffer 仅在 profiling 后处理。动态 WeatherColor stops、独立 particle/trail color 和 weather-local targetFps 均是当前缺口;后者应独立性能批次,不能使用全图 `MapView#setMaximumFps()` 冒充。
## 2026-09-07 — STEP-057 Android Host 天气运行时接口基础
- 新增主线程 `WeatherRuntime` typed facade,封装 canonical submit、typed result/state、clear、OFF unload、timestamp seek、play/pause/0.5/1/2x、独立 visibility 和 visual API;未来 RN 只需包裹该 facade。
- clear 后 Source 保持可复用但无 field;Render 线程空场路径释放 Particle State/Trail/draw、field texture 与 WeatherColor resources。OFF 不 reload style,ON 后要求重新 submit T0/T1。
- WeatherColor 支持最多 8 个 validated dynamic stops;particleColor/trailColor 独立 UBO 数据通路,不依赖 WeatherColor ramp。正常 time seek 和 visual/ramp/color 更新均不重新提交 field 或 reset simulation。
- Linux shader generator、OpenGL Core 及相关 Source/Style test translation unit 已验证;Android Gradle/APK/ADB/设备/Jest 留待后续人工验收。