All communication (commit messages, pull request messages, documentation, and code comments) is human written and not authored by AI
I take full responsibility of all changes submitted in this pull request
### Description
WIP before cleaning up for the comaps repo
### Submitter checklist
- [x] All code changes and commit messages conform to the appropriate [style guide](https://codeberg.org/comaps/comaps/src/branch/main/docs/CONTRIBUTING.md#code-contributions)
- [x] I have signed off all my commits with the [Developers Certificate of Origin](https://codeberg.org/comaps/Governance/src/branch/main/DCO.md)
- [x] All communication (commit messages, pull request messages, documentation, and code comments) is human written and not authored by AI
- [x] I take full responsibility of all changes submitted in this pull request
Solves crashes observed in the simulator while testing CarPlay
It was possible get a NaN matrix that lead to tripping the
m2::Rect min<=max assert in rect2d.hpp
Generated with help of Opus 4.8
Signed-off-by: eisa01 <eisa01@gmail.com>
Rapid switching during CarPlay simulator testing tripped an assert here with invalid m2::RectD
Add guards to not call degenerate viewports
Generated with the help of Claude Opus 4.8
Signed-off-by: eisa01 <eisa01@gmail.com>
When the phone application became active on unlock, we asked for location before the protected data was available leading to a false kCLErrorDenied.
Only ask for it if it is actually restricted, and add observer to know when to ask
Debugged with Claude Opus 4.8 and device logs from the latest Testflight
Signed-off-by: eisa01 <eisa01@gmail.com>
Rework the iOS location keepalive policy around CarPlay scene ownership. Track recording and active unfinished navigation now keep location running independent of which phone or CarPlay app is foreground, while CarPlay/dashboard map hosting remains the only non-navigation CarPlay reason to keep location alive. Map-host transitions now refresh the background location policy immediately so stale host state cannot either drain battery after disconnect/dehost or leave CarPlay without location until the phone app is opened.
Keep protected-data recovery registered for the lifetime of MWMLocationManager. Stopping location now removes only the transient orientation and battery observers, leaving UIApplicationProtectedDataDidBecomeAvailable in place so unlock recovery still works after a previous stop.
Improve CarPlay activation behavior. Re-entering the CarPlay app or dashboard resumes location when the centralized policy allows it and recenters into follow mode. The initial car session can promote follow into the car heading mode, but user panning or manual position controls disable only that automatic heading-mode promotion, not future recentering on re-entry.
Harden dashboard and scene edge cases. The dashboard map now rejects non-finite, zero-size, or invalid-scale viewports before calling into the framework, matching the main CarPlay guard. Scene cold-start URL handling now routes file URLs through the normal import path while preserving deferred deep-link startup handling for non-file URLs.
Fix CarPlay navigation audio button state. The mute/unmute button now reflects MWMTextToSpeech.tts().active rather than only the persisted global TTS availability flag, and CarPlay observes TTS status changes while active so navigation audio buttons stay in sync when state changes from elsewhere.
Validation: xcrun swiftc -parse on the CarPlay Swift files passed, and git diff --check passed. A full xcodebuild was attempted earlier but the local Xcode installation is missing the Metal toolchain, so it failed before compiling app code.
Guarantee the disconnect teardown runs. The two-second CarPlay teardown grace period is now wrapped in a named UIApplication background task, so iOS cannot suspend the process before the deferred destroy() stops location after a disconnect. Field logs from the 2026年07月10日 drive showed the process being reclaimed inside the grace window, which left the location keepalive armed with a stale CarPlay map host. The expiration handler tears down synchronously on the main thread and always ends the task.
Defer early car-screen map operations until the surface is ready. The base template north-up rotation, the default car zoom, and the automatic follow/heading engagement now wait until the shared map view is attached to a car window and its graphics context is initialized. This gates the cold-start calls that previously ran against drape's default 640x480 ScreenBase and produced paired "Bad scale factor = -4.375 / -2.5" errors on every CarPlay cold start (and would assert in Debug builds). Both car map controllers report viewport readiness after the centralized Objective-C++ viewport validation, which replaces the duplicated Swift-side guards. Re-entry recenters requested while a host switch had reset viewport readiness are remembered and replayed once the viewport becomes ready, and automatic recentering is skipped while the CarPlay panning interface is visible.
Make dashboard shortcut routing safe. Shortcut buttons capture the validated bookmark object instead of re-resolving a possibly deleted bookmark ID, the dashboard scene observes bookmark and category deletion for its whole connection lifetime and refreshes its buttons, and the pending dashboard route is tracked as the exact CPTrip instance so only its own route callback can auto-start navigation. Pending state is cleared on success, failure, cancellation, phone handoff, route completion, and teardown.
Harden location recovery around the first unlock. A new background location session is deferred while protected data is unavailable, without interrupting an already-running session, and protected-data availability now retries Core Location when the app is active or the background keepalive policy requires it. This covers a logically-started manager whose Core Location start failed before unlock, which the plain started setter could not retry.
Cleanups: remove the dead reapplyBackgroundLocationPolicy API, the unused requiresFollowMode parameter, and the stale TTS button wrapper; simplify refreshBackgroundLocationPolicy; add an explicit MapMode::Walking case so switching to walking mode no longer logs as unrecognized; add a ScreenBase auto-perspective threshold-transition regression test.
Implemented with GPT 5.6 Sol and Claude Fable 5 from reviews of commit 71f01122b4, the 2026年07月10日 field logs, and jetsam reports.
Validation: xcrun swiftc -parse on the touched Swift files, plutil -lint, git diff --check, the focused ScreenBase_AutoPerspectiveThresholdTransition unit test, and an unsigned generic-iOS Debug build.
🤖 Generated with [Claude Code](https://claude.ai/code)
Signed-off-by: eisa01 <eisa01@gmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
switchScreenToPhone() invalidated the theme before updating the map host. The theme switch posts a map-style update that starts a route recache on the render threads, and the visual-scale change that follows forces a GPU context destroy/recreate, which killed that recache mid-flight on every CarPlay disconnect: the frontend renderer wiped the route GPU buffers while the backend was still building them, and the main thread sat blocked in SetRenderingDisabled for ~110ms waiting for the busy render thread. The pipeline self-heals (the scale change's own VisualScaleChanged recovery re-adds the subroutes), so the route line was never permanently lost, but every disconnect wasted a full backend route build and delayed the context reset.
Running updateMapHost() first lets the context reset happen against an idle message queue, and the theme's recache lands cleanly afterwards. The connect path (setup()) already applied the scale before the theme and needs no change. Verified in the iOS Simulator with a scale-2 CarPlay display: the disconnect destroy now follows the scale change within 30ms with no orphaned recache, and every host switch ends with an accepted route flush.
This also disproves the earlier claim that a CarPlay visual-scale switch permanently drops the rendered route line: FrontendRenderer::UpdateAll ends with UpdateContextDependentResources(), which re-uploads all subroutes after every context reset triggered by DrapeEngine::UpdateVisualScale.
Diagnosed with Claude Fable 5 from instrumented simulator runs on 2026年07月10日.
Validation: xcrun swiftc -parse on CarPlayService.swift, git diff --check, and three instrumented simulator runs (same-scale and scale-2 CarPlay displays) confirming the recache pipeline completes on every host switch.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: eisa01 <eisa01@gmail.com>
Log the five stages of the context-dependent route resource cycle: RouteRenderer::ClearContextDependentResources (the GPU-side wipe on context destroy), FrontendRenderer::UpdateAll and UpdateContextDependentResources (the recovery that re-adds subroutes after a style or visual-scale change), the backend's AddSubroute build, and the frontend's FlushSubroute accept/discard decision with both recache ids.
These logs made the CarPlay disconnect recache race visible (in-flight recaches killed by the visual-scale context reset, always rescued by the following cycle) and confirm the route line recovery path runs after every context reset. They fire only on context resets and route recaches, so they are quiet during normal rendering.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: eisa01 <eisa01@gmail.com>
TextureManager::OnVisualScaleChanged used to destroy the StipplePenTexture
object and allocate a new one. Render states of already generated geometry
hold non-owning references to that object, and FrontendRenderer::UpdateAll
only marks the existing render groups as pending deletion - they keep being
rendered until the re-read tiles replace them. Any of those groups with a
dashed/dotted line pattern then dereferenced the freed texture in
dp::ApplyState, crashing the frontend render thread (EXC_BAD_ACCESS at
render_state.cpp:290, TestFlight crash points BmEkWSV1i2dCo4HaRN-hDS and
DmaJDYelACYWaY0hpcANZg). The Vulkan-only deferred cleanup did not help
because it defers only the hardware texture, not the Texture object itself.
On iOS the visual scale changes exactly on CarPlay connect/disconnect and
phone handoff, which is why the crash rate spiked with the CarPlay dashboard
builds, but the bug affects every platform and predates that work.
The stipple texture is now invalidated in place, following the same pattern
as SymbolsTexture::Invalidate on map style switch: DynamicTexture gains an
Invalidate method that destroys the hardware texture (still deferring its
destruction on Vulkan), resets the initialization flag so the texture is
lazily recreated at the new size on the next UpdateState, and rebinds a
fresh indexer. Pending-deletion groups briefly sample the new texture with
old UVs - a transient visual artifact instead of a use-after-free.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: eisa01 <eisa01@gmail.com>
Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
eisa01/comaps!24
Loading...
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "carplay-dashboard-support"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?