Repository navigation
Android Auto map freezes when app is backgrounded on Samsung Android 16 (Mapbox v11) #2716
Description
Environment
- Android OS version: Android 16
- Devices affected: Galaxy S25 Ultra (and multiple new Samsung models)
- Maps SDK Version: 11.20.1
- Mapbox Android Auto Extension: 11.20.1
- Android Car App Library: 1.7.0
- Working devices: Pixel (Android 16) and Samsung (Android <16)
Observed behavior and steps to reproduce
I am observing an issue where the Mapbox map rendered in Android Auto stops updating when the mobile app is backgrounded on specific Samsung devices running Android 16.
The issue does not occur on:
Google Pixel devices running Android 16
Samsung devices running lower Android versions
This suggests a device/vendor-specific behavior affecting Mapbox rendering or camera updates when the app is backgrounded.
Steps to reproduce:
- Launch the app on a Samsung device (Android 16)
- Connect to Android Auto (Desktop Head Unit or real car)
- Render a Mapbox map using MapboxCarMap
- Enable location puck + follow camera (viewport follow puck)
- Start moving (real or simulated location)
- Background the mobile app (home button or switch apps)
- Observe Android Auto screen
Expected behavior
- Location puck continues updating
- Camera continues following location
- Map continues rendering smoothly
Notes / preliminary analysis
Additional Notes / Hypothesis:
The issue appears to be related to Samsung’s background performance policies on Android 16
It seems that animation or rendering loops are being suspended when the app is not in foreground
Mapbox camera updates using animation or viewport transitions may be affected
Notably:
Using setCamera() (non-animated) appears to still work in some cases
Animated transitions (viewport / easeTo) and puck movement appear to stop completely
Additional links and references
This log appears exactly when the app is backgrounded:
Choreographer: CoreRune.SYSPERF_ACTIVE_APP_BBA_ENABLE : stop animation in background states
Minimal Repro
A minimal app was created with:
Mapbox Compose on phone
Mapbox Android Auto extension
Viewport follow-puck camera
The issue is reproducible consistently on Samsung Android 16.
Main Activity:
class MainActivity : ComponentActivity() {
private var hasLocationPermission by mutableStateOf(false)
private val requestLocationPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
hasLocationPermission = granted
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
hasLocationPermission = ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
if (!hasLocationPermission) {
requestLocationPermission.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
setContent {
val mapViewportState = rememberMapViewportState()
MainMapScreen(
hasLocationPermission = hasLocationPermission,
mapViewportState = mapViewportState
)
}
}
}
@Composable
private fun MainMapScreen(
hasLocationPermission: Boolean,
mapViewportState: MapViewportState
) {
MapboxMap(
modifier = Modifier.fillMaxSize(),
mapViewportState = mapViewportState,
style = {
MapboxStandardStyle()
},
scaleBar = {
ScaleBar(Modifier.padding(top = 60.dp))
},
logo = {
Logo(Modifier.padding(bottom = 40.dp))
},
attribution = {
Attribution(Modifier.padding(bottom = 40.dp))
}
) {
MapEffect(hasLocationPermission) { mapView ->
val locationPlugin = mapView.location
if (hasLocationPermission) {
locationPlugin.updateSettings {
enabled = true
puckBearingEnabled = true
puckBearing = PuckBearing.HEADING
locationPuck = createDefault2DPuck(withBearing = true)
}
}
}
}
LaunchedEffect(hasLocationPermission) {
if (hasLocationPermission) {
mapViewportState.transitionToFollowPuckState(
FollowPuckViewportStateOptions.Builder()
.zoom(16.0)
.pitch(0.0)
.build()
)
} else {
mapViewportState.setCameraOptions {
zoom(2.0)
center(Point.fromLngLat(-98.0, 39.5))
pitch(0.0)
bearing(0.0)
}
}
}
}
Android auto related code:
class MyCarAppService : CarAppService() {
override fun createHostValidator(): HostValidator {
return HostValidator.ALLOW_ALL_HOSTS_VALIDATOR
}
override fun onCreateSession(): Session = MyCarSession()
}
class MyCarSession : Session() {
private val mapboxCarMap = mapboxMapInstaller()
.onCreated(TestLandingScreenCameraController())
.install { carContext ->
// Callback is triggered when the Session calls onCreate. This allows you to specify
// custom MapInitOptions.
MapInitOptions(carContext)
}
override fun onCreateScreen(intent: android.content.Intent): Screen {
return MyCarScreen(carContext)
}
}
class MyCarScreen(carContext: CarContext) : Screen(carContext) {
override fun onGetTemplate(): Template {
val temp = NavigationTemplate.Builder()
val actionStrip = ActionStrip.Builder()
actionStrip.addAction(Action.PAN)
temp.setActionStrip(actionStrip.build())
return temp.build()
}
}
class TestLandingScreenCameraController : MapboxCarMapObserver {
private var mapBoxMap : MapboxMap? = null
private var mapSurface: MapSurface? = null
override fun onAttached(mapboxCarMapSurface: MapboxCarMapSurface) {
val mapboxMap = mapboxCarMapSurface.mapSurface.getMapboxMap()
val mapSurface = mapboxCarMapSurface.mapSurface
this.mapBoxMap = mapboxMap
this.mapSurface = mapSurface
mapboxMap.loadStyleUri(Style.MAPBOX_STREETS) {
mapSurface.location.updateSettings {
enabled = true
pulsingEnabled = true
}
}
val followPuckState = mapSurface.viewport.makeFollowPuckViewportState(
FollowPuckViewportStateOptions.Builder()
.zoom(16.0)
.build()
)
mapSurface.viewport.transitionTo(followPuckState)
}
override fun onDetached(mapboxCarMapSurface: MapboxCarMapSurface) {
}
}
Activity
magnussp commentedon May 13, 2026
I have observed exactly the same on my AA implementation. And old Samsung Galaxy S10 with Android version12 works fine with the app in background.
On a Samsung Galaxy S22 with Android16 then the user puck and camera movement stops a few seconds after the app is put in background.
raga70 commentedon May 16, 2026
https://github.com/mapbox/mapbox-maps-android/tree/main/extension-androidauto#xiaomi-animations
https://docs.mapbox.com/android/maps/api/10.9.1/mapbox-maps-android/com.mapbox.maps.threading/-animation-thread-controller/
i am also having issues with the background thread freezing on other devices , it`s a bit hit or miss and for Samsung device with android 16 it appears to be better with the background thread on
magnussp commentedon May 18, 2026
Thanks @raga70 this seem to have solved it for the Samsung phones we use for testing.
aliQMIC commentedon May 31, 2026
Thank you! it fixed it for me as well. Since mapbox says to only use background thread when necessary, is there a way in the code to detect that this issue has occurred ? @magnussp @raga70
raga70 commentedon May 31, 2026
@aliQMIC Here is what is actually going on:
The background thread flag is not a real fix, it is a trade-off. Enabling it unconditionally for everyone will stop the freeze on Samsung One UI 8+ / Android 16, but it will reintroduce the exact same freeze on the majority of other devices.
The root cause is how each manufacturer's AOSP fork implements its Background Process Optimization. When the app is backgrounded, the BPO suspends a thread, but which thread it suspends is vendor dependent (some vendors don't put anything to sleep):
Keep in mind that Battery optimization settings for the app do absolutely noting for BPO .
Most devices suspend the background thread, so keeping rendering on the main thread is what works.
Samsung on Android 16 suspends the main thread instead and lets the background thread keep running.
That is why flipping the flag fixes one group and breaks the other. You are not detecting a bug condition so much as choosing which thread the OS is willing to keep alive on a given device.
Because of that, I would not try to detect the issue after it occurs. By the time the puck has stopped updating, you are already in the bad state and there is no clean signal to react to.
the easiest path for you would be:
I personally detect if user is using a Samsung on A16 and show them a warning and telling them to flip the setting in my app`s settings if they have issues
I did the stupid thing of putting all my 15k users on background thread and discovered that a lot of people not on Samsung started crying that their map animation freezes
one thing I am not certain for is if Xiaomi is still putting the main thread to sleep .
Keep in mind the background thread path has a magnitude of additional downsides, which is why Mapbox tells you to only use it when necessary. It is not free, and as noted above it recreates the same problem it solves on the wrong device set, so gating it behind the vendor and SDK check matters.
I have also implemented a bunch of other safe guards , which pretty much don't really help like:
AND I REPEAT WHATEVER YOU DO, DO NOT ENABLE BACKGROUND THREAD FOR EVERYONE YOU WILL BE IN A VARY STICKY SITUATION
Ranafugaz commentedon Jun 2, 2026
I tested the workaround on my Mapbox Android Auto implementation and it seems to work for me as well.
My previous workaround was keeping the app alive with an overlay window from a background service, because on Samsung devices the Android Auto map froze when the phone app was backgrounded.
After applying
AnimationThreadController.useBackgroundThread()only for Samsung devices running Android 16 / API 36+, the map keeps updating correctly in Android Auto without needing the overlay workaround.I gated it like this:
kyle-young commentedon Jul 15, 2026
For others finding this issue, I'm not using Mapbox but ran into a similar problem.
My findings and workaround:
The suspension is edge-triggered: it engages when the app transitions to the background (for example, when the screen locks) and disengages when the device wakes. After that, animations continue running even if the screen turns off again, because no new background transition occurs. As a result, recovery only requires a single brief screen wake, or "bump."
I developed a watchdog that runs only while a car session has an active renderer. It periodically posts a canary animation-frame callback on the main thread's Choreographer. If the canary doesn't fire, animation callbacks are considered suspended, and the watchdog briefly wakes the phone screen to restore them. Screen bumps are rate-limited and are skipped while the screen is already interactive, since waking the device cannot help in that state.
g4rb4g3 commentedon Aug 24, 2026
I had the exact same issue on some Samsung Android 16 devices (S23 Ultra, S25), from what I found you must not release the virtual display in
onSurfaceDestroyedbut rather keep a reference and release it whenonSurfaceAvailableis invoked again and the new virtual display is shown (or when AA shuts down).Check this for details: Iternio-Planning-AB/react-native-auto-play#107