8.3 KiB
STEP-053 Windy-style Field 与 Host Submission Codex 完成报告
1. 基线与状态
- Starting HEAD:
285d23a58f6ecb16f360748df688d9d03dad6b3d - 分支:
particle/main - STEP-051:
CLOSED / PASS - STEP-052:调查完成;STEP-053 按任务书修正了 Weather/Manifest 所有权,MapLibre 仅从 Host 已规范化 Field 开始负责。
- 当前状态:
IMPLEMENTED / WAITING_ANDROID_VALIDATION
2. 最终实际设计
新增唯一低频入口 RasterArraySource::submitHostField(metadataText, payload)。Host 每次提交一个 maplibre-particle-field/v1 metadata 和一段 contiguous binary U/V payload。入口复用 LocalParticleFieldFeed、ParticleFieldDataAdapter 和 immutable ParticleFieldSnapshot,再路由到既有 initial T0/T1 与同一个 Core-owned Timeline。
没有新增 Descriptor 或 Snapshot,因为 STEP-049 的结构已经表达 identity、generation、validTime、grid geometry、bounds、layout、encoding、noData、byte length、dataVersion 和可选 checksum。也没有建立第二套 Adapter、Timeline、Window 或 cache。
Canonical layout 为 north-west origin、row-major、north-to-south rows、west-to-east columns,float32-le interleaved-uv:U=eastward-positive,V=northward-positive。大 Field 走二进制 bytes,不走巨大 JSON/JS number array。metadata 可以是小型 JSON;STEP-054 可把 ArrayBuffer/TypedArray/native buffer/file reference 映射到同一 Native bytes boundary。
3. API 与路径
Core/C++
RasterArraySource(std::string id):创建空 Host ingress Source。RasterArraySource::submitHostField(metadata, payload):单 Field 正式提交。RasterArrayHostFieldSubmitResult:区分 pending initial、initial ready、next accepted、duplicate,以及 source mode/adapter/incompatible/non-monotonic/capacity rejection。RasterArrayTimelineRuntime::append():仅追加低频、严格递增、capacity-bound Snapshot;不改变 Playback 状态机所有权。- style validation seam:
{"type":"raster-array","host-field-submission":true}。
Android/Validation
MapLibreMap.submitRasterArraySourceHostField(String, String, byte[])。- Java
NativeMap/NativeMapView→ JNINativeMapView→RasterArraySource::submitHostField()。 - API 返回与 C++ structured result 对齐的整数常量;JNI 只在一次 Field arrival 时复制 contiguous bytes,不做 per-frame JNI。
- MORE 菜单新增
HOST FIELD SUBMIT、HOST DUPLICATE、INVALID HOST。
Initial / Next / Duplicate / Invalid
- Field #0:pending T0。
- Field #1:复用
submitInitialRuntimeFieldWindow(),建立 T0/T1 和 Timeline READY。 - Field #2/#3:append 到同一个 Timeline,继续由既有 renderer window revision 路径消费。
- Duplicate:
DUPLICATE_NOOP,Timeline size 与 active field 不变。 - Invalid/unsupported/non-monotonic:结构化拒绝,最后有效 Snapshot/Timeline frame 不变,符合 fail-closed。
4. 架构影响
- Public/internal API:新增 Core Host submission API、Android MapLibreMap binary submission API、Host Source style validation flag;Timeline 增加内部有界 append/read helpers。
- Adapter contract:未放宽、未复制;仍只接受合法
interleaved-uv/float32-le。 - Runtime Field Window:未重写,
OLD_T1 → NEW_T0与 only NEW_T1 upload 不变。 - Timeline/Playback:状态机、clock、cursor、speed、pause/gap/invalid ownership 未改变。
- Renderer/GPU/Trail:未修改;不含 provider/network/vendor/manifest/cache 业务。
- WeatherColorLayer:未修改,继续与 RasterParticleLayer 分离。
- Network/Provider/Weather Service/React Native:未实现。
5. 测试与结果
构建
cmake --build build-linux-opengl --target mbgl-test-runner -j3:PASS。cmake --build build-linux-opengl --target mbgl-render mbgl-render-test-runner -j3:PASS。
定向测试
Source.CanonicalFieldUsesEastwardUAndNorthwardVSource.HostFieldSubmissionBuildsOneCoreOwnedTimelineSource.HostFieldSubmissionStyleContractCreatesEmptyIngressSource.HostFieldSubmissionRejectsInvalidWithoutChangingLastValidField
结果:4/4 PASS。覆盖 east U / north V、vortex corner orientation、initial T0/T1、T2/T3、strict validTime/generation、Duplicate、invalid identity/dimensions、wrong byte length、unsupported layout/encoding、non-monotonic 和 last-valid hold。
Source.*:44/44 PASS,包含既有 Adapter、STEP-051 local feed、Timeline READY/Playback、Runtime Window/reuse/NOOP 回归。- RasterParticle property 回归:2/2 PASS。
- JNI signature/registration、Host style property、Validation action resource ID:静态核对 PASS。
xmllint:环境未安装,未执行。- checksum mismatch:Host contract 当前未启用 checksum 校验,按任务书条件未伪造测试结果。
git diff --check:PASS。
最初新增 style conversion 测试使用 dynamic_cast,精确编译暴露项目 -fno-rtti 约束;已改为项目正式 Source::as<T>(),后续构建/测试通过,无遗留阻塞。
6. 未执行项
- Android Gradle:未执行。
- APK build/copy/install:未执行。
- ADB/App 启动/设备测试:未执行。
- Jest:未新增、未修改、未执行。
- 用户正式 canonical dataset:尚未提供,未声称已验证。
7. 用户 Android 手工验收
- 在 Windows 11 构建并安装新的 Android OpenGL Debug APK。
- 打开
Particle Core Layer Validation → MORE → HOST FIELD SUBMIT。 - 确认日志依次出现
HOST_FIELD_SUBMIT_REQUEST、HOST_FIELD_SNAPSHOT_READY、HOST_FIELD_INITIAL_WINDOW_READY、HOST_FIELD_NEXT_SUBMIT与ParticleTimeline: event=READY。 - 进入 TIME,执行
PLAY / RESTART,观察 east/north/vortex 变化、自动 MIX 和至少两个 Window Boundary。 - 确认
reuse=OLD_T1_TO_NEW_T0、only NEW_T1 upload、simulationRebuild=false、trailCleared=false。 - 执行
MORE → HOST DUPLICATE,确认DUPLICATE_NOOP且 upload/reset 不增长。 - 执行
MORE → INVALID HOST,确认 Adapter reject、最后有效 Field 保持、Renderer 连续、无黑屏、无 crash。
日志采集必须显式指定设备,例如:
adb -s 192.168.1.146 logcat | findstr /I "HOST_FIELD ParticleTimeline WINDOW_BOUNDARY FIELD_REUSE FIELD_UPLOAD DUPLICATE INVALID simulationRebuild trailCleared"
8. 文件与 Git
实际代码/测试修改文件:
include/mbgl/particle/field/field_data_adapter.hppinclude/mbgl/style/sources/raster_array_source.hppsrc/mbgl/style/sources/raster_array_source.cppsrc/mbgl/style/sources/raster_array_source_impl.hppsrc/mbgl/style/conversion/source.cpptest/style/source.test.cppplatform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.javaplatform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.javaplatform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.javaplatform/android/MapLibreAndroid/src/cpp/native_map_view.hppplatform/android/MapLibreAndroid/src/cpp/native_map_view.cppplatform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.ktplatform/android/MapLibreAndroidTestApp/src/main/res/layout/activity_particle_core_layer_validation.xml
文档修改:本 Step、粒子开发记录.md 和本报告。
- commit hash:
1e8eca79125e36284d8893e3134203d3f5289ce7。 - commit message:
feat: add host particle field submission contract - push result:SUCCESS,已推送至
origin/particle/main。 - remote branch:
origin/particle/main - Final HEAD(功能实现与验收文档提交):
1e8eca79125e36284d8893e3134203d3f5289ce7。 - 无关 untracked 文件:保持未修改、未 stage、未提交;包括历史 diff、任务书、临时文档等。
9. Remaining risks
- Android JNI/Kotlin/visual 行为尚待用户同一 APK 手工验证。
- 当前 validation dataset 复用 STEP-051 T0~T3;用户指定正式数据尚未提供。
- Host metadata checksum 尚未启用;若正式要求 integrity,需后续以同一 Descriptor 字段实现,不另建 contract。
- Validation UI MIX/WAITING/INVALID observability 与 Rotation/Viewport 继续是 NON-BLOCKING 技术债。
阻塞项:无代码或 Linux 验证阻塞。当前不能写 CLOSED / PASS。