Skip to content

docs backend evidence maps MAP 16

AlexandreZanata edited this page Oct 26, 2026 · 1 revision

MAP-16 — Compose lifecycle and privacy-controlled map host

Current assessment: 2026-10-25 remediation supersedes earlier integration/acceptance claims. Historical evidence below is retained.

Status: LOCAL_DONE / INTEGRATION_PENDING Validation: PASS (JVM view model + real-phone Compose host + real native engine lifecycle) Integration: INTEGRATION_PENDING

Tested tree: codex/map-ev-implementation at 6106b4d9 plus the MAP-16 closure changes. Date: 2026-10-25. No map tab or marker UI was added.

Behavior frozen

  • One MapEngine per process via Hilt singleton (MapEngineModule + MapEngineHolder); Compose hosts share it and never create a second native core. The native SDK type never leaks into app/domain/data layers.
  • MapHost wraps the native surface in Compose AndroidView only after readiness; newMapView before readiness throws, and a bare Context without an AndroidX lifecycle owner is rejected by MapViewHelper.
  • The host creates the map without starting location. A location permission is requested only on explicit recenter tap. Denied, approximate, denied-forever, GPS-off and no-fix states never block browsing, search or manual viewport use; they annotate recenter (no-permission, gps-off, no-fix) with visible text.
  • No Play Services dependency and no background/continuous GPS for simple browsing. release() stops location polling; disposal is idempotent and late readiness/permission callbacks cannot revive a discarded host.
  • MapViewModel (Hilt) owns readiness, permission flags, GPS state, explicit recenter and camera persistence. It cancels stale search/route work on dispose and stores only center/zoom in SharedPreferencesMapCameraStore (no private route/favorite data).
  • MapHost observes ON_RESUME (permission + GPS refresh) and ON_STOP (camera save). Camera restores after recreation; the surface is recreated without a second native initialization.
  • Recenter is a 48 dp target with an explicit content description.

Implementation

  • maps/engine/.../MapEngineModule.kt: Hilt singleton + process holder.
  • maps/engine/.../MapHost.kt: product Hilt host + testable explicit-engine overload, permission/GPS UI states, readiness-gated AndroidView.
  • maps/engine/.../MapViewModel.kt: @HiltViewModel state machine with gpsEnabled/recenterError, disposal and camera persistence.
  • maps/engine/.../MapCameraStore.kt: shared-preferences center/zoom store.
  • MapEngine/ComapsMapEngine: currentCenter() and explicit recenter().
  • maps/engine/build.gradle.kts: Hilt + navigation-compose; optional module remains gated by -PcomapsSdkDir.

Verification executed

JVM (:maps:engine:testDebugUnitTest, 25 cases: 3 + 7 + 9 + 6):

  • saved camera restored and applied once;
  • no permission never triggers recenter;
  • approximate permission permits an explicit recenter;
  • host stop persists the current center without changing zoom;
  • dispose cancels search/route work and rejects late callbacks;
  • gps-off blocks recenter but keeps browsing;
  • no-fix surfaces explicit error without moving camera;
  • denied-forever never triggers recenter;
  • camera restores after recreation;
  • singleton holder returns one engine per process.

Real phone instrumentation through adb (2311DRK48G, Android 16 / API 36):

./gradlew :maps:engine:connectedDebugAndroidTest \
  -PcomapsSdkDir=/data/dev/artifacts/abastevo-map-engine/d2ec37881ede4e22 \
  -Pandroid.testInstrumentationRunnerArguments.class=com.anpfuel.maps.engine.MapHostInstrumentedTest
# Starting 2 tests on 2311DRK48G - 16
# Finished 2 tests on 2311DRK48G - 16
# BUILD SUCCESSFUL

./gradlew :maps:engine:connectedDebugAndroidTest \
  -PcomapsSdkDir=/data/dev/artifacts/abastevo-map-engine/d2ec37881ede4e22 \
  -Pandroid.testInstrumentationRunnerArguments.class=com.anpfuel.maps.engine.MapHostRealEngineInstrumentedTest
# Starting 1 tests on 2311DRK48G - 16
# Finished 1 tests on 2311DRK48G - 16
# BUILD SUCCESSFUL
  • Fake-host tests prove the surface waits for readiness and creates the map without calling recenter/location on entry.
  • Real-engine test proves on-device native init, readiness-gated surface, lifecycle-owner rejection, recenter-without-fix fail-closed, viewport/center round-trip and idempotent release/re-init. Rendering with map data stays in MAP-14; this proves the host contract with the real core.

Fix 2026-10-25 — production Hilt/Compose init path (review defect 1)

  • B-BR-MAP-HOST-INIT-01: the production MapScreen/MapHost path owns exactly one native initialization of the injected singleton engine, on the application context (never a retained Activity), gating the AndroidView on readiness. Synchronous init failure surfaces initError with a 48 dp retry; a blank screen is never the terminal state.
  • BUC-MAP-HOST-INIT-01: GIVEN the MAP route with Hilt VMs and the real engine, WHEN opened, THEN ensureInitialized runs once and the surface appears; GIVEN a failed init, WHEN retrying, THEN one more init runs and the surface appears; GIVEN tab return, rotation or recreation, THEN the same engine serves the surface with no repeated native init and stale callbacks are dropped.

MapViewModel.ensureInitialized/retryInit is the single owner (per-VM guard

  • application context + error state). MapHostContent drives it from a single LaunchedEffect(vm) for both the Hilt and explicit-engine overloads; the engine?.initialize direct call is gone. User-visible init strings are parameters (recenterDescription, initErrorMessage, retryLabel) so the app passes localized resources; remaining hardcoded host strings are owned by the MAP-18/20 language pass.

Verification (2311DRK48G, API 36):

./gradlew :maps:engine:testDebugUnitTest \
  -PcomapsSdkDir=/data/dev/artifacts/abastevo-map-engine/d2ec37881ede4e22
# MapInitTest 3/3 PASS (app-context init, failure+retry, late-callback drop)

./gradlew :maps:engine:connectedDebugAndroidTest \
  -PcomapsSdkDir=/data/dev/artifacts/abastevo-map-engine/d2ec37881ede4e22 \
  -Pandroid.testInstrumentationRunnerArguments.class=com.anpfuel.maps.engine.MapHostInstrumentedTest
# 4/4 PASS (readiness gate, no location on entry, init error + retry UI)

./gradlew :app:connectedDebugAndroidTest \
  -Pandroid.testInstrumentationRunnerArguments.class=com.anpfuel.app.ui.map.MapRouteInstrumentedTest
# 1/1 PASS — real MainActivity + real nav + Hilt + real engine, no
# mapContent override, no manual initialize/onEngineReady: open → surface,
# other tab → back → surface, landscape → portrait → recreate, same
# MapEngineHolder instance, isInitialized() true throughout.

The pre-existing fake-host tests are preserved for their scope; the new route test owns the production path.

Limits

  • No map tab, quick sheet, marker cluster or source selector (MAP-17/18).
  • No runtime permission grant/denial dialog test; those states are covered by view-model tests and the launcher code is compiled. GPS-off is read from LocationManager on resume; a device-level toggle test remains manual.
  • ENGINE_GATE remains the MAP-14 receipt; this is a local host checkpoint, not a release/integration acceptance.

Engine checkpoint integration correction — 2026-10-24

MAP-14_ENGINE_GATE adds a failing-then-passing instrumented asynchronous-init case: MapHost creates no native surface before readiness. Disposal is idempotent, releases the adapter and rejects late readiness/permission callbacks. MapViewHelper forwards the complete SDK lifecycle and pauses before buffer teardown. Actual native probe recreation is recorded separately from the controlled Compose tests. Native package-layout, first-fix/recenter, error states and the real navigation screen remain the retained MAP-15/MAP-17 integration work; this record does not accept fake GPS or a production map tab.

Native storage and live camera completion — 2026-10-25

B-BR-MAP-NATIVE-SYNC-01: publication reconnects the initialized SDK to the verified map storage and re-registers regional maps on the main thread. BUC-MAP-NATIVE-SYNC-01: returning from Downloads shows the newly activated map without seeding files through adb or restarting the process. B-BR-MAP-CAMERA-02: native pan AND zoom update viewport discovery; host stop persists the current native center and zoom, including zoom-only gestures. Validation results are recorded after the scoped regression/device checks.

Fuel prices wiki

Source: AlexandreZanata/brazil-fuel-prices @ bbd96568180563ced975b96f8f89f7a3c242522e

Clone this wiki locally