From 5782574c8c003562044fd8df40a2001f2f3e21ba Mon Sep 17 00:00:00 2001 From: OpenAI Codex Date: Thu, 3 Sep 2026 10:35:17 +0800 Subject: [PATCH] fix: bridge Android particle mix property --- .../STEP-043A_40-02C源码审查后最小修正_v1.md | 1 + ...P-043B_40-02C_Android到Core_MIX属性桥接_v1.md | 7 +++++++ ...-02C_Android双时间片GPU时间插值最终修正_v1.md | 1 + ...Android到Core_MIX属性桥接_Codex完成报告_v1.md | 15 +++++++++++++++ .../src/cpp/native_map_view.cpp | 18 ++++++++++++++++++ .../src/cpp/native_map_view.hpp | 1 + .../org/maplibre/android/maps/MapLibreMap.java | 5 +++++ .../org/maplibre/android/maps/NativeMap.java | 2 ++ .../maplibre/android/maps/NativeMapView.java | 9 +++++++++ .../ParticleCoreLayerValidationActivity.kt | 11 +++++------ 粒子开发记录.md | 4 ++++ 11 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 docs/50_Step记录/STEP-043B_40-02C_Android到Core_MIX属性桥接_v1.md create mode 100644 docs/报告/STEP-043B_40-02C_Android到Core_MIX属性桥接_Codex完成报告_v1.md diff --git a/docs/50_Step记录/STEP-043A_40-02C源码审查后最小修正_v1.md b/docs/50_Step记录/STEP-043A_40-02C源码审查后最小修正_v1.md index ccabb5fe4..f819c94da 100644 --- a/docs/50_Step记录/STEP-043A_40-02C源码审查后最小修正_v1.md +++ b/docs/50_Step记录/STEP-043A_40-02C源码审查后最小修正_v1.md @@ -4,3 +4,4 @@ - 状态:`IMPLEMENTED / WAITING FOR ANDROID VALIDATION` - 修正:GPU texture reuse 保留旧 backing 但消费 wanted snapshot revision;MIX_REJECTED 不再改变 timeMix;增加 Layer/Resource/Field upload/reuse/reset 生命周期日志;所有 Style reload 调用点有具体 reason。 - 检查:shader generator、Linux Core/source-test object、format、diff check 通过;未运行 Android Gradle、ADB 或设备。 +- Android 设备验证发现 Java peer lookup 对自定义 raster-particle 不适用,STEP-043B 以最小 Core property bridge 接续修正。 diff --git a/docs/50_Step记录/STEP-043B_40-02C_Android到Core_MIX属性桥接_v1.md b/docs/50_Step记录/STEP-043B_40-02C_Android到Core_MIX属性桥接_v1.md new file mode 100644 index 000000000..173fa34d1 --- /dev/null +++ b/docs/50_Step记录/STEP-043B_40-02C_Android到Core_MIX属性桥接_v1.md @@ -0,0 +1,7 @@ +# STEP-043B Android 到 Core MIX 属性桥接 + +- 状态:`IMPLEMENTED / WAITING FOR ANDROID VALIDATION` +- 根因:Android `Style.getLayer()` 需要自定义 layer 的 Java peer;raster-particle Core layer 无 peer,导致 false `LAYER_NOT_READY`。 +- 实现:最小 `NativeMapView.setStyleLayerFloatProperty(layerId, propertyName, value)`,JNI 通过 `Style::getLayer()` 与正式 `Layer::setProperty()` 更新 Core 属性;没有完整 RasterParticle Java peer。 +- Host:MIX 不再查询 Java Layer peer,bridge 成功后才更新 `timeMix`。 +- 未运行 Android Gradle/ADB;T4--T10 待用户验收。 diff --git a/docs/50_Step记录/STEP-043_40-02C_Android双时间片GPU时间插值最终修正_v1.md b/docs/50_Step记录/STEP-043_40-02C_Android双时间片GPU时间插值最终修正_v1.md index 8c6f355b4..1f7947b33 100644 --- a/docs/50_Step记录/STEP-043_40-02C_Android双时间片GPU时间插值最终修正_v1.md +++ b/docs/50_Step记录/STEP-043_40-02C_Android双时间片GPU时间插值最终修正_v1.md @@ -6,3 +6,4 @@ - 检查:shader generator、Linux Core/source test object、format、diff check 通过;未运行 Android Gradle/ADB。 - Android:T1--T10 仍待用户执行,不能判 PASS。 - STEP-043A 源码审查发现 reuse revision、MIX reject state、diagnostics 与 Style reason 缺口,均已最小修正;状态不变。 +- STEP-043B 处理 Android Java Layer peer 缺失导致的 false LAYER_NOT_READY,改用 Android→Core property bridge;状态不变。 diff --git a/docs/报告/STEP-043B_40-02C_Android到Core_MIX属性桥接_Codex完成报告_v1.md b/docs/报告/STEP-043B_40-02C_Android到Core_MIX属性桥接_Codex完成报告_v1.md new file mode 100644 index 000000000..035c5673f --- /dev/null +++ b/docs/报告/STEP-043B_40-02C_Android到Core_MIX属性桥接_Codex完成报告_v1.md @@ -0,0 +1,15 @@ +# STEP-043B Android 到 Core MIX 属性桥接完成报告 + +开始 HEAD:`0ab94c4eabaeb72be9ec956df5486dfa951c8181`。Android 运行日志证明 Core/Renderer layer 存在但 `Style.getLayer()` 返回 null;其原因是 LayerManager 无 raster-particle Java peer。 + +新增最小 float property bridge:`MapLibreMap -> NativeMapView -> JNI NativeMapView::setStyleLayerFloatProperty -> Style::getLayer -> Layer::setProperty`。它返回 boolean;Host 仅在成功后更新 `timeMix`,失败记录 `CORE_LAYER_NOT_FOUND`。未做完整 layer peer、未 setStyle、未触及 renderer/shader/Field。 + +静态检查:MIX 路径不再使用 `getLayer(PARTICLE_LAYER_ID)` 或 `setStyle`,`git diff --check` 通过。未运行 Android Gradle、ADB、APK 安装或启动。 + +用户: + +```bash +./gradlew :MapLibreAndroidTestApp:assembleOpenglDebug --console=plain +``` + +APK:`platform/android/MapLibreAndroidTestApp/build/outputs/apk/opengl/debug/MapLibreAndroidTestApp-opengl-debug.apk`。T4--T10 仍待 Android 手工验收,状态不得判 PASS。 diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp index f24ee5e0c..552a203b9 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp @@ -1106,6 +1106,23 @@ jni::Local> NativeMapView::getLayer(JNIEnv& env, const jni::S return LayerManagerAndroid::get()->createJavaLayerPeer(env, *coreLayer); } +jni::jboolean NativeMapView::setStyleLayerFloatProperty(JNIEnv& env, + const jni::String& layerId, + const jni::String& propertyName, + const jni::jfloat value) { + auto* layer = map->getStyle().getLayer(jni::Make(env, layerId)); + if (!layer) return false; + if (const auto error = layer->setProperty(jni::Make(env, propertyName), static_cast(value))) { + mbgl::Log::Error(mbgl::Event::JNI, "ParticleGPU: event=STYLE_PROPERTY_SET result=FAILURE " + error->message); + return false; + } + mbgl::Log::Info(mbgl::Event::JNI, + "ParticleGPU: event=STYLE_PROPERTY_SET layerId=" + jni::Make(env, layerId) + + " property=" + jni::Make(env, propertyName) + " value=" + std::to_string(value) + + " result=SUCCESS"); + return true; +} + void NativeMapView::addLayer(JNIEnv& env, jlong nativeLayerPtr, const jni::String& before) { assert(nativeLayerPtr != 0); @@ -1489,6 +1506,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::getLight, "nativeGetLight"), METHOD(&NativeMapView::getLayers, "nativeGetLayers"), METHOD(&NativeMapView::getLayer, "nativeGetLayer"), + METHOD(&NativeMapView::setStyleLayerFloatProperty, "nativeSetStyleLayerFloatProperty"), METHOD(&NativeMapView::addLayer, "nativeAddLayer"), METHOD(&NativeMapView::addLayerAbove, "nativeAddLayerAbove"), METHOD(&NativeMapView::addLayerAt, "nativeAddLayerAt"), diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp index 652589304..be355b89b 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp @@ -281,6 +281,7 @@ public: jni::Local>> getLayers(JNIEnv&); jni::Local> getLayer(JNIEnv&, const jni::String&); + jni::jboolean setStyleLayerFloatProperty(JNIEnv&, const jni::String&, const jni::String&, jni::jfloat); void addLayer(JNIEnv&, jlong, const jni::String&); diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java index f8c73d944..c3d815441 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java @@ -286,6 +286,11 @@ public final class MapLibreMap { return nativeMapView.getNativePtr(); } + /** Updates a constant property on an existing Core style layer without requiring a Java Layer peer. */ + public boolean setStyleLayerFloatProperty(String layerId, String propertyName, float value) { + return nativeMapView.setStyleLayerFloatProperty(layerId, propertyName, value); + } + // Style /** diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java index 24ae9491e..314d1b379 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java @@ -139,6 +139,8 @@ interface NativeMap { Layer getLayer(String layerId); + boolean setStyleLayerFloatProperty(String layerId, String propertyName, float value); + boolean removeLayer(@NonNull String layerId); boolean removeLayer(@NonNull Layer layer); diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java index 735f475be..5fe789d95 100755 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java @@ -950,6 +950,12 @@ final class NativeMapView implements NativeMap { return nativeGetLayer(layerId); } + @Override + public boolean setStyleLayerFloatProperty(String layerId, String propertyName, float value) { + return !checkState("setStyleLayerFloatProperty") + && nativeSetStyleLayerFloatProperty(layerId, propertyName, value); + } + @Override public void addLayer(@NonNull Layer layer) { if (checkState("addLayer")) { @@ -1681,6 +1687,9 @@ final class NativeMapView implements NativeMap { @Keep private native Layer nativeGetLayer(String layerId); + @Keep + private native boolean nativeSetStyleLayerFloatProperty(String layerId, String propertyName, float value); + @Keep private native void nativeAddLayer(long layerPtr, String before) throws CannotAddLayerException; diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt index 04567baa0..b2b4b24da 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt @@ -144,11 +144,6 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() { private fun setTimeMix(value: Float) { val requestedTimeMix = value.coerceIn(0.0f, 1.0f) - val layer = maplibreMap.style?.getLayer(PARTICLE_LAYER_ID) - if (layer == null) { - Log.i(TAG, "ParticleGPU: event=MIX_REJECTED reason=LAYER_NOT_READY styleEpoch=$styleLoadEpoch") - return - } val rejectReason = when { !styleReady -> "STYLE_LOADING" !enabled -> "DISABLED" @@ -159,8 +154,12 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() { Log.i(TAG, "ParticleGPU: event=MIX_REJECTED reason=$rejectReason styleEpoch=$styleLoadEpoch") return } + Log.i(TAG, "ParticleGPU: event=MIX_PROPERTY_REQUEST value=$requestedTimeMix styleEpoch=$styleLoadEpoch") + if (!maplibreMap.setStyleLayerFloatProperty(PARTICLE_LAYER_ID, "raster-particle-time-mix", requestedTimeMix)) { + Log.i(TAG, "ParticleGPU: event=MIX_REJECTED reason=CORE_LAYER_NOT_FOUND styleEpoch=$styleLoadEpoch") + return + } timeMix = requestedTimeMix - layer.setProperties(PaintPropertyValue("raster-particle-time-mix", timeMix)) status.text = statusText() Log.i(TAG, "ParticleGPU: event=MIX_PROPERTY_ONLY value=$timeMix styleEpoch=$styleLoadEpoch") } diff --git a/粒子开发记录.md b/粒子开发记录.md index 3ce80d4b0..efb9172d2 100644 --- a/粒子开发记录.md +++ b/粒子开发记录.md @@ -248,3 +248,7 @@ ## 2026-09-03 — STEP-043A 源码审查后最小修正 - texture reuse 现消费 wanted revision;MIX reject 不再改变 timeMix;补充 lifecycle diagnostics 与 Style reason。状态仍为 `IMPLEMENTED / WAITING FOR ANDROID VALIDATION`。 + +## 2026-09-03 — STEP-043B Android→Core MIX 属性桥接 + +- 自定义 raster-particle 没有 Android Java Layer peer,`Style.getLayer()` 不能作为 Core layer readiness;新增最小 NativeMapView bridge 走正式 Core `Layer::setProperty`,MIX 仅 bridge 成功后更新状态。