Skip to content

Add Burning Man native offline map pack#6330

Draft
RCGV1 wants to merge 16 commits into
meshtastic:mainfrom
RCGV1:codex/burning-man-native-offline-map
Draft

Add Burning Man native offline map pack#6330
RCGV1 wants to merge 16 commits into
meshtastic:mainfrom
RCGV1:codex/burning-man-native-offline-map

Conversation

@RCGV1

@RCGV1 RCGV1 commented Jul 20, 2026

Copy link
Copy Markdown
Member

Summary

Adds the 2026 Burning Man system offline region from current Protomaps OSM-derived PMTiles, with separate native Google Maps and F-Droid/osmdroid renderers.

  • Shared validated app-private z15 PMTiles pack, lifecycle, suppression, and race-safe cleanup.
  • Google and F-Droid use opaque local rendering inside BRC coverage; no online tile fallback is allowed there.
  • Google remote custom tiles resume outside coverage; F-Droid resumes its normal provider outside coverage.
  • highway=pedestrian BRC roads render as visible minor roads; ordinary paths remain filtered.
  • Foreground reconciliation uses only existing authorized fresh last-known location and never prompts or starts location updates.

Root cause

The BRC OSM streets are highway=pedestrian, represented by Protomaps as roads kind=path, kind_detail=pedestrian. The renderer needed an explicit rule for this road type and an actual z15 pack validation path.

Data evidence

Validation

  • Focused Android host/Google/F-Droid tests, Detekt, and both flavor Kotlin compiles.
  • Pixel 7 emulator booted; both variants installed with networking disabled. The archive was not present on that emulator, so no BRC rendering was fabricated.
  • Final independent review verified z15 enforcement, local-pack precedence, no online fallback in coverage, lifecycle/location boundaries, and cleanup races.

Visual evidence

Apple simulator BRC rendering is documented in the companion Apple PR. Android emulator captures are retained locally; GitHub CLI cannot upload binary image attachments, so native PR attachment is pending.

Notes

No dedicated Burning Man map issue exists; design#120 supplies event metadata.

Summary by CodeRabbit

  • New Features
    • Added automatic offline Burning Man map pack installation and management based on location and event timing.
    • Maps now use the offline pack within its coverage area, including support for Google Maps and OpenStreetMap views.
    • Online maps and custom tile sources resume automatically when viewing areas outside the offline pack.
    • Offline map packs are restored, validated, updated, and removed automatically as needed.
  • Bug Fixes
    • Improved handling of invalid, incomplete, outdated, or unavailable offline map data.
  • Tests
    • Added coverage for offline rendering, pack lifecycle management, location boundaries, and map-layer selection.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@RCGV1, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 30 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b48ce7de-a64d-4552-9eff-427eb2a0ba66

📥 Commits

Reviewing files that changed from the base of the PR and between 483a652 and 0955565.

📒 Files selected for processing (15)
  • androidApp/src/fdroid/kotlin/org/meshtastic/app/map/offline/BurningManOsmDroidTileProvider.kt
  • androidApp/src/google/kotlin/org/meshtastic/app/map/GoogleMapTileLayerSelection.kt
  • androidApp/src/google/kotlin/org/meshtastic/app/map/MapView.kt
  • androidApp/src/google/kotlin/org/meshtastic/app/map/MapViewModel.kt
  • androidApp/src/google/kotlin/org/meshtastic/app/map/offline/BurningManGoogleTileProvider.kt
  • androidApp/src/main/kotlin/org/meshtastic/app/map/offline/BurningManPmtilesRenderer.kt
  • androidApp/src/testGoogle/kotlin/org/meshtastic/app/map/offline/BurningManGoogleTileProviderTest.kt
  • feature/map/src/androidHostTest/kotlin/org/meshtastic/feature/map/offline/BurningManPackCoordinatorTest.kt
  • feature/map/src/androidHostTest/kotlin/org/meshtastic/feature/map/offline/BurningManPackRuntimeTest.kt
  • feature/map/src/androidHostTest/kotlin/org/meshtastic/feature/map/offline/ProtomapsRegionDownloaderTest.kt
  • feature/map/src/androidMain/kotlin/org/meshtastic/feature/map/offline/BurningManPackCoordinator.kt
  • feature/map/src/androidMain/kotlin/org/meshtastic/feature/map/offline/BurningManPackRuntime.kt
  • feature/map/src/androidMain/kotlin/org/meshtastic/feature/map/offline/ProtomapsRegionDownloader.kt
  • feature/map/src/commonMain/kotlin/org/meshtastic/feature/map/offline/BurningManPackPolicy.kt
  • feature/map/src/commonTest/kotlin/org/meshtastic/feature/map/offline/BurningManPackPolicyTest.kt
📝 Walkthrough

Walkthrough

Adds automatic Burning Man offline pack management, PMTiles downloading and validation, local vector-tile rendering for Google Maps and OSMdroid, and camera-aware map-layer switching with coverage-based offline precedence.

Changes

Burning Man offline map

Layer / File(s) Summary
Pack policy and PMTiles acquisition
feature/map/src/commonMain/..., feature/map/src/androidMain/.../ProtomapsRegionDownloader.kt, feature/map/src/androidHostTest/.../BurningManPackPolicyTest.kt, feature/map/src/androidHostTest/.../ProtomapsRegionDownloaderTest.kt
Adds time/location-based pack reconciliation and downloads bounded MVT PMTiles archives through validated HTTP range requests.
Pack persistence and reconciliation
feature/map/src/androidMain/.../BurningManPackCoordinator.kt, feature/map/src/androidMain/.../BurningManPackRuntime.kt, feature/map/src/androidHostTest/.../BurningManPackCoordinatorTest.kt, feature/map/src/androidHostTest/.../BurningManPackRuntimeTest.kt
Persists pack metadata, validates restored files, coordinates installation/removal/concurrent reconciliation, and exposes application-scoped selection state.
PMTiles vector tile rendering
androidApp/src/fdroid/.../offline/BurningManOsmDroidTileProvider.kt, androidApp/src/google/.../offline/BurningManGoogleTileProvider.kt, androidApp/src/testFdroid/..., androidApp/src/testGoogle/...
Adds local-only PMTiles providers that decode vector tiles and rasterize themed areas and selected road features for both map backends.
Map selection and lifecycle integration
androidApp/src/main/.../MainActivity.kt, androidApp/src/google/.../MapView.kt, androidApp/src/google/.../MapViewModel.kt, androidApp/src/fdroid/.../MapView.kt, androidApp/src/google/.../GoogleMapTileLayerSelection.kt
Restores and reconciles packs on startup, exposes selection state, and switches offline, custom, and online layers based on camera coverage.
Map-layer selection validation
androidApp/src/testGoogle/.../GoogleMapTileLayerSelectionTest.kt
Tests Burning Man precedence over custom tiles inside pack coverage and custom tile retention outside coverage.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

Pack installation and map rendering

sequenceDiagram
  participant MainActivity
  participant BurningManPackRuntime
  participant BurningManPackCoordinator
  participant ProtomapsRegionDownloader
  participant MapView
  participant BurningManTileProvider

  MainActivity->>BurningManPackRuntime: reconcile current time and location
  BurningManPackRuntime->>BurningManPackCoordinator: reconcile pack state
  BurningManPackCoordinator->>ProtomapsRegionDownloader: download region when policy selects Install
  ProtomapsRegionDownloader-->>BurningManPackCoordinator: validated PMTiles file
  BurningManPackCoordinator-->>MapView: selected pack state
  MapView->>BurningManTileProvider: request covered camera tiles
  BurningManTileProvider-->>MapView: rendered local tiles
Loading
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a native offline Burning Man map pack.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@RCGV1

RCGV1 commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
feature/map/src/androidMain/kotlin/org/meshtastic/feature/map/offline/ProtomapsRegionDownloader.kt (1)

289-295: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoff

Reader loads the entire archive to inspect only the header + metadata.

FileInputStream(file).use { it.readBytes() } pulls the full multi-MB PMTiles pack into memory, yet init only needs the 127-byte header and the metadata slice. Since validatedSelection, install, and download each construct a reader, a z15 pack is fully re-read several times per reconcile. Consider reading just the header and the [metadataOffset, metadataOffset+metadataLength) window (e.g. via RandomAccessFile).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/map/src/androidMain/kotlin/org/meshtastic/feature/map/offline/ProtomapsRegionDownloader.kt`
around lines 289 - 295, Update the reader initialization around parseHeader and
parseMetadata to avoid loading the entire archive: read only the fixed PMTiles
header bytes, parse it, then seek to header.metadataOffset and read
header.metadataLength bytes for metadata. Preserve the existing header and
metadata-range validation, and use bounded file access so repeated
ProtomapsReader construction does not reread the full archive.
androidApp/src/fdroid/kotlin/org/meshtastic/app/map/offline/BurningManOsmDroidTileProvider.kt (1)

149-183: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Extract the duplicated PMTiles/MVT stack into shared src/main. Both providers carry a verbatim copy of LocalPmtiles, the header/directory parsers, WireReader/VarintReader, the decode* vector-tile functions, the geometry types, and the drawAreaLayer/drawRoad/drawLine/fillCircle helpers — only the provider class and rasterize's return type differ. This flavor-independent code (it depends only on android.graphics, not on osmdroid or Google Maps) will drift out of sync. Move it to a shared androidApp/src/main location (internal), leaving each flavor with just its provider wrapper.

  • androidApp/src/fdroid/kotlin/org/meshtastic/app/map/offline/BurningManOsmDroidTileProvider.kt#L149-L183: remove the local parser/decoder block and depend on the shared implementation.
  • androidApp/src/google/kotlin/org/meshtastic/app/map/offline/BurningManGoogleTileProvider.kt#L131-L156: remove the mirrored parser/decoder block and depend on the shared implementation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@androidApp/src/fdroid/kotlin/org/meshtastic/app/map/offline/BurningManOsmDroidTileProvider.kt`
around lines 149 - 183, Extract the duplicated flavor-independent PMTiles/MVT
implementation—including LocalPmtiles, parsers, readers, decode functions,
geometry types, and drawing helpers—into shared internal code under
androidApp/src/main, then update both provider wrappers to use it. Remove the
duplicated implementation from
androidApp/src/fdroid/kotlin/org/meshtastic/app/map/offline/BurningManOsmDroidTileProvider.kt
lines 149-183 and
androidApp/src/google/kotlin/org/meshtastic/app/map/offline/BurningManGoogleTileProvider.kt
lines 131-156; preserve each provider’s platform-specific wrapper and rasterize
return type.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@androidApp/src/google/kotlin/org/meshtastic/app/map/GoogleMapTileLayerSelection.kt`:
- Around line 19-35: Run ./gradlew spotlessApply and apply the resulting
formatting changes without altering behavior: reformat
GoogleMapTileLayerSelection.kt lines 19-35, the dense apply/expression bodies in
BurningManGoogleTileProvider.kt lines 64-69, and the long writeBytes call in
BurningManGoogleTileProviderTest.kt lines 84-85, then ensure spotlessKotlinCheck
passes.

In
`@feature/map/src/androidMain/kotlin/org/meshtastic/feature/map/offline/BurningManPackCoordinator.kt`:
- Around line 54-64: Run ./gradlew spotlessApply to format
BurningManPackCoordinator.kt, including load, install, validatedSelection, and
asManifest bodies. Restore the complete canonical license header in
BurningManPackRuntimeTest.kt. Also apply Spotless to BurningManPackPolicy.kt,
BurningManPackPolicyTest.kt, ProtomapsRegionDownloader.kt,
ProtomapsRegionDownloaderTest.kt, and BurningManPackCoordinatorTest.kt, then
ensure spotlessKotlinCheck passes.

In
`@feature/map/src/androidMain/kotlin/org/meshtastic/feature/map/offline/ProtomapsRegionDownloader.kt`:
- Around line 270-282: Configure explicit connect and read timeouts on the
HttpURLConnection created in fetch before requesting the response or reading its
stream. Use the existing project timeout constants or configuration if
available, and preserve the current range request, response handling, and
disconnect behavior.

---

Nitpick comments:
In
`@androidApp/src/fdroid/kotlin/org/meshtastic/app/map/offline/BurningManOsmDroidTileProvider.kt`:
- Around line 149-183: Extract the duplicated flavor-independent PMTiles/MVT
implementation—including LocalPmtiles, parsers, readers, decode functions,
geometry types, and drawing helpers—into shared internal code under
androidApp/src/main, then update both provider wrappers to use it. Remove the
duplicated implementation from
androidApp/src/fdroid/kotlin/org/meshtastic/app/map/offline/BurningManOsmDroidTileProvider.kt
lines 149-183 and
androidApp/src/google/kotlin/org/meshtastic/app/map/offline/BurningManGoogleTileProvider.kt
lines 131-156; preserve each provider’s platform-specific wrapper and rasterize
return type.

In
`@feature/map/src/androidMain/kotlin/org/meshtastic/feature/map/offline/ProtomapsRegionDownloader.kt`:
- Around line 289-295: Update the reader initialization around parseHeader and
parseMetadata to avoid loading the entire archive: read only the fixed PMTiles
header bytes, parse it, then seek to header.metadataOffset and read
header.metadataLength bytes for metadata. Preserve the existing header and
metadata-range validation, and use bounded file access so repeated
ProtomapsReader construction does not reread the full archive.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a12956b2-cbcf-4e0d-9e31-20a560469bb6

📥 Commits

Reviewing files that changed from the base of the PR and between 91d2f76 and 483a652.

📒 Files selected for processing (18)
  • androidApp/src/fdroid/kotlin/org/meshtastic/app/map/MapView.kt
  • androidApp/src/fdroid/kotlin/org/meshtastic/app/map/offline/BurningManOsmDroidTileProvider.kt
  • androidApp/src/google/kotlin/org/meshtastic/app/map/GoogleMapTileLayerSelection.kt
  • androidApp/src/google/kotlin/org/meshtastic/app/map/MapView.kt
  • androidApp/src/google/kotlin/org/meshtastic/app/map/MapViewModel.kt
  • androidApp/src/google/kotlin/org/meshtastic/app/map/offline/BurningManGoogleTileProvider.kt
  • androidApp/src/main/kotlin/org/meshtastic/app/MainActivity.kt
  • androidApp/src/testFdroid/kotlin/org/meshtastic/app/map/offline/BurningManOsmDroidTileProviderTest.kt
  • androidApp/src/testGoogle/kotlin/org/meshtastic/app/map/GoogleMapTileLayerSelectionTest.kt
  • androidApp/src/testGoogle/kotlin/org/meshtastic/app/map/offline/BurningManGoogleTileProviderTest.kt
  • feature/map/src/androidHostTest/kotlin/org/meshtastic/feature/map/offline/BurningManPackCoordinatorTest.kt
  • feature/map/src/androidHostTest/kotlin/org/meshtastic/feature/map/offline/BurningManPackRuntimeTest.kt
  • feature/map/src/androidHostTest/kotlin/org/meshtastic/feature/map/offline/ProtomapsRegionDownloaderTest.kt
  • feature/map/src/androidMain/kotlin/org/meshtastic/feature/map/offline/BurningManPackCoordinator.kt
  • feature/map/src/androidMain/kotlin/org/meshtastic/feature/map/offline/BurningManPackRuntime.kt
  • feature/map/src/androidMain/kotlin/org/meshtastic/feature/map/offline/ProtomapsRegionDownloader.kt
  • feature/map/src/commonMain/kotlin/org/meshtastic/feature/map/offline/BurningManPackPolicy.kt
  • feature/map/src/commonTest/kotlin/org/meshtastic/feature/map/offline/BurningManPackPolicyTest.kt

@RCGV1

RCGV1 commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@jamesarich

Copy link
Copy Markdown
Collaborator

We can't do this without THOROUGH understanding of licensing.

@jamesarich jamesarich added the do-not-merge DO NOT MERGE THIS label Jul 21, 2026
@RCGV1

RCGV1 commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@jamesarich Its just using OSM tiles. We just need to follow OSM license

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge DO NOT MERGE THIS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants