Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5ed2165 authored by Ellen Poe's avatar Ellen Poe
Browse files

fix: prefer GPS over fused rather than the opposite

parent 794ce684
Loading
Loading
Loading
Loading
Loading
+29 −63
Original line number Diff line number Diff line
@@ -56,8 +56,8 @@ class LocationRepository @Inject constructor(
        private const val LOCATION_REQUEST_TIMEOUT_MS = 5000L // 5 seconds
        private const val CONTINUOUS_LOCATION_UPDATE_INTERVAL_MS = 5000L // 5 seconds
        private const val CONTINUOUS_LOCATION_UPDATE_DISTANCE_M = 5f // 5 meters
        private const val FUSED_PROVIDER_TIMEOUT_MS =
            5000L // 5 seconds - discard GPS if fused hasn't updated
        private const val GPS_PROVIDER_TIMEOUT_MS =
            10_000L // 10 seconds - discard fused locations if fused has updated within this timeout
    }

    // Location caching with thread safety
@@ -76,8 +76,8 @@ class LocationRepository @Inject constructor(
    private var gpsLocationListener: LocationListener? = null
    private var fusedLocationListener: LocationListener? = null

    // Track last fused provider update time
    private var lastFusedLocationTime: Long = 0L
    // Track last GPS update time
    private var lastGpsLocationTime: Long = 0L

    /**
     * Gets the current location, either from cache or by requesting a fresh one.
@@ -142,8 +142,8 @@ class LocationRepository @Inject constructor(
     * This should be called from the UI when the map is ready.
     *
     * Subscribes to both GPS and fused providers to handle unreliable fused location
     * on some microG devices. GPS updates are discarded unless fused hasn't provided
     * a location for 5 seconds.
     * on some microG devices. Fused updates are discarded unless GPS hasn't provided
     * a location for 10 seconds.
     */
    @SuppressLint("MissingPermission")
    fun startContinuousLocationUpdates(context: Context) {
@@ -165,7 +165,23 @@ class LocationRepository @Inject constructor(
                fusedLocationListener = object : LocationListener {
                    override fun onLocationChanged(location: Location) {
                        Log.d("LocationRepository", "Fused location update received")
                        lastFusedLocationTime = System.currentTimeMillis()
                        val currentTime = System.currentTimeMillis()
                        val timeSinceLastGps = currentTime - lastGpsLocationTime

                        // Discard this position update if the GPS is providing updates.
                        if (timeSinceLastGps <= GPS_PROVIDER_TIMEOUT_MS) {
                            Log.d(
                                "LocationRepository",
                                "Discarding fused update (GPS active: ${timeSinceLastGps}ms ago)"
                            )
                            return
                        }

                        // Only use GPS if fused hasn't updated in 10 seconds
                        Log.d(
                            "LocationRepository",
                            "Using Fused location (GPS timeout: ${timeSinceLastGps}ms)"
                        )

                        // Always use fused provider updates
                        _locationFlow.value = location
@@ -211,27 +227,15 @@ class LocationRepository @Inject constructor(
            if (availableProviders.contains(LocationManager.GPS_PROVIDER)) {
                gpsLocationListener = object : LocationListener {
                    override fun onLocationChanged(location: Location) {
                        val currentTime = System.currentTimeMillis()
                        val timeSinceLastFused = currentTime - lastFusedLocationTime
                        lastGpsLocationTime = System.currentTimeMillis()

                        // Only use GPS if fused hasn't updated in 5 seconds
                        if (timeSinceLastFused >= FUSED_PROVIDER_TIMEOUT_MS) {
                            Log.d(
                                "LocationRepository",
                                "Using GPS location (fused timeout: ${timeSinceLastFused}ms)"
                            )
                        _locationFlow.value = location
                        orientationRepository.setDeclination(location)

                        synchronized(locationLock) {
                            lastRequestedLocation = location
                        }
                        } else {
                            Log.d(
                                "LocationRepository",
                                "Discarding GPS update (fused active: ${timeSinceLastFused}ms ago)"
                            )
                        }

                    }

                    override fun onProviderDisabled(provider: String) {
@@ -272,44 +276,6 @@ class LocationRepository @Inject constructor(
        }
    }

    /**
     * Stops location updates and orientation tracking.
     */
    fun stopLocationUpdates(context: Context) {
        // Stop orientation tracking
        orientationRepository.stop()
        Log.d("LocationRepository", "Orientation sensor stopped")

        val locationManager = try {
            getLocationManager(context)
        } catch (_: Exception) {
            null
        }

        // Remove GPS listener
        gpsLocationListener?.let { listener ->
            try {
                locationManager?.removeUpdates(listener)
            } catch (_: Exception) {
                // Ignore exceptions during cleanup
            }
            gpsLocationListener = null
        }

        // Remove fused listener
        fusedLocationListener?.let { listener ->
            try {
                locationManager?.removeUpdates(listener)
            } catch (_: Exception) {
                // Ignore exceptions during cleanup
            }
            fusedLocationListener = null
        }

        // Reset fused location timestamp
        lastFusedLocationTime = 0L
    }

    /**
     * Checks if a location is recent (less than LOCATION_REQUEST_INTERVAL_MS old).
     */