[Bug]: LocationPuck leaks one fused-location provider (thread + native memory) per MapView destroy on Android
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 2.9k
- Forks
- 947
- Avg merge
- 6d 37m
- Merged PRs (30d)
- 1
Description
Mapbox Version
11.20.1 (default)
React Native Version
0.81.5
Platform
Android
@rnmapbox/maps version
10.3.1
Standalone component to reproduce
import React, { useEffect, useState } from 'react';
import { MapView, Camera, LocationPuck } from '@rnmapbox/maps';
const REMOUNT_INTERVAL_MS = 3000;
function BugReportExample() {
const [mapVisible, setMapVisible] = useState(true);
// Simulates navigating to and from a screen containing a map:
// each cycle mounts a fresh MapView + LocationPuck, then unmounts it.
useEffect(() => {
const interval = setInterval(() => {
setMapVisible((visible) => !visible);
}, REMOUNT_INTERVAL_MS);
return () => clearInterval(interval);
}, []);
if (!mapVisible) {
return null;
}
return (
<MapView style={{ flex: 1 }}>
<Camera centerCoordinate={[-74.00597, 40.71427]} zoomLevel={14} />
<LocationPuck />
</MapView>
);
}
Location permission must be granted (the puck's location provider is only created once permissions allow it). While the component remounts, count the Play Services fused-location handler threads:
PID=$(adb shell pidof <your.package>)
adb shell "for t in /proc/$PID/task/*/comm; do cat \$t; done" | grep -c fusedLocation
Observed behavior and steps to reproduce
Every mount/unmount cycle of a MapView containing a LocationPuck permanently leaks one FusedLocationProviderClient (visible as a fusedLocationCl… handler thread) plus its native allocations.
Measured in a production app (Expo SDK 54, new architecture, release build, no expo-dev-client), repeatedly opening and backing out of a screen containing a map — exactly 10 navigation cycles per measurement window, thread census + dumpsys meminfo between windows:
| Baseline (1 live map) | After 10 open/back cycles | After 20 | |
|---|---|---|---|
fusedLocationCl… threads |
3 | 13 | 23 (+1 per mount) |
MapboxRenderThread |
1 | 1 | 1 (map teardown itself is clean) |
Control: removing only <LocationPuck /> from the same screen and repeating the identical 30-cycle protocol keeps the fused-location thread count constant at 1 and removes the linear component of native-heap growth. The render thread and Java heap are clean in both configurations — the leak is specific to the puck's location provider.
Device: Samsung SM-P613, Android 14 (API 34), Google Play Services 26.19.34.
Expected behavior
Destroying a MapView (or unmounting the LocationPuck) releases the location component's provider: the fused-location client count stays constant across mount/unmount cycles, matching the (correct) behavior of MapboxRenderThread.
Notes / preliminary analysis
The leak is Android-specific in our testing and isolates cleanly to LocationPuck: the identical navigation protocol with the puck removed (and nothing else changed) keeps the fused-location client count constant.
Additional links and references
- The same measurement methodology (thread census +
dumpsys meminfoacross fixed navigation-cycle windows) applied to another map engine, for comparison of failure signatures: expo/expo#41648
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the remount cycle with MapView and LocationPuck after granting location permission, then run the provided adb fusedLocation thread census and dumpsys meminfo measurements. Trace the Android LocationPuck location-provider lifecycle across MapView destruction and unmounting. Done means repeated cycles no longer increase fused-location threads or native memory, while the render thread remains clean.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, javascript, kotlin, react-native
- Domain
- mobile, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100