Skip to content

Commit a079c9a

Browse files
author
Tommy Webb
committed
Skip known-unreasonable network location updates
If we have a GPS location of a given accuracy, and our proposed network location is more than twice as far away as the GPS accuracy, this is considered unreasonable. Stop sending that network location. As part of this, also keep track of lower-accuracy GPS locations. Change-Id: I1893c63c2d716a5e41011cbf39f069491e6b5da6
1 parent 3fcc78a commit a079c9a

File tree

1 file changed

+35
-9
lines changed

1 file changed

+35
-9
lines changed

play-services-location/core/provider/src/main/kotlin/org/microg/gms/location/network/NetworkLocationService.kt

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class NetworkLocationService : LifecycleService(), WifiDetailsCallback, CellDeta
7878
@GuardedBy("gpsLocationBuffer")
7979
private val gpsLocationBuffer = LinkedList<Location>()
8080

81+
@GuardedBy("lowAccuracyGpsLocationBuffer")
82+
private val lowAccuracyGpsLocationBuffer = LinkedList<Location>()
83+
8184
private var currentLocalMovingWifi: WifiDetails? = null
8285
private var lastLocalMovingWifiLocationCandidate: Location? = null
8386

@@ -391,7 +394,22 @@ class NetworkLocationService : LifecycleService(), WifiDetailsCallback, CellDeta
391394
elapsedRealtimeNanos = (old.elapsedRealtimeNanos.toDouble() * (1.0-pct) + new.elapsedRealtimeNanos.toDouble() * pct).toLong()
392395
}
393396
}
397+
fun Location.isUnreasonableComparedTo(other: Location): Boolean {
398+
val distance = distanceTo(other)
399+
if (distance > 2 * other.accuracy) {
400+
Log.d(TAG, "Unreasonable location ${this.provider} vs ${other.provider} (accuracy ${other.accuracy}): distance $distance")
401+
return true
402+
}
403+
return false
404+
}
405+
fun Location.reasonableOrNull(): Location? {
406+
val gpsLocation = getGpsLocation(elapsedMillis, includeLowAccuracy = true) ?: return this
407+
if (isUnreasonableComparedTo(gpsLocation)) return null
408+
return this
409+
}
394410
val location = synchronized(locationLock) {
411+
lastCellLocation = lastCellLocation?.reasonableOrNull()
412+
lastWifiLocation = lastWifiLocation?.reasonableOrNull()
395413
if (lastCellLocation == null && lastWifiLocation == null) return
396414
when {
397415
// Only non-null
@@ -401,7 +419,7 @@ class NetworkLocationService : LifecycleService(), WifiDetailsCallback, CellDeta
401419
lastCellLocation!!.elapsedMillis > lastWifiLocation!!.elapsedMillis + LOCATION_TIME_CLIFF_END_MS -> lastCellLocation
402420
lastWifiLocation!!.elapsedMillis > lastCellLocation!!.elapsedMillis + LOCATION_TIME_CLIFF_START_MS -> lastWifiLocation
403421
// Wifi out of cell range with higher precision
404-
lastCellLocation!!.precision > lastWifiLocation!!.precision && lastWifiLocation!!.distanceTo(lastCellLocation!!) > 2 * lastCellLocation!!.accuracy -> lastCellLocation
422+
lastCellLocation!!.precision > lastWifiLocation!!.precision && lastWifiLocation!!.isUnreasonableComparedTo(lastCellLocation!!) -> lastCellLocation
405423
// Consider cliff start
406424
lastCellLocation!!.elapsedMillis > lastWifiLocation!!.elapsedMillis + LOCATION_TIME_CLIFF_START_MS -> cliffLocations(lastWifiLocation, lastCellLocation)
407425
else -> lastWifiLocation
@@ -429,7 +447,9 @@ class NetworkLocationService : LifecycleService(), WifiDetailsCallback, CellDeta
429447
}
430448

431449
private fun onNewGpsLocation(location: Location) {
432-
if (location.accuracy > GPS_PASSIVE_MIN_ACCURACY) return
450+
if (location.accuracy > GPS_PASSIVE_MIN_ACCURACY_LOW) return
451+
// gpsLocationBuffer field is shadowed by the low accuracy buffer if inaccurate enough.
452+
val gpsLocationBuffer = if (location.accuracy > GPS_PASSIVE_MIN_ACCURACY) lowAccuracyGpsLocationBuffer else this.gpsLocationBuffer
433453
synchronized(gpsLocationBuffer) {
434454
if (gpsLocationBuffer.isNotEmpty() && gpsLocationBuffer.last.elapsedMillis < SystemClock.elapsedRealtime() - GPS_BUFFER_SIZE * GPS_PASSIVE_INTERVAL) {
435455
gpsLocationBuffer.clear()
@@ -440,16 +460,20 @@ class NetworkLocationService : LifecycleService(), WifiDetailsCallback, CellDeta
440460
}
441461
}
442462

443-
private fun getGpsLocation(elapsedMillis: Long): Location? {
463+
private fun getGpsLocation(elapsedMillis: Long, includeLowAccuracy: Boolean = false): Location? {
444464
if (elapsedMillis + GPS_BUFFER_SIZE * GPS_PASSIVE_INTERVAL < SystemClock.elapsedRealtime()) return null
445-
synchronized(gpsLocationBuffer) {
446-
if (gpsLocationBuffer.isEmpty()) return null
447-
for (location in gpsLocationBuffer.descendingIterator()) {
448-
if (location.elapsedMillis in (elapsedMillis - GPS_PASSIVE_INTERVAL)..(elapsedMillis + GPS_PASSIVE_INTERVAL)) return location
449-
if (location.elapsedMillis < elapsedMillis) return null
465+
fun getGpsLocationFromBuffer(gpsLocationBuffer: LinkedList<Location>): Location? {
466+
// gpsLocationBuffer field is shadowed by the argument provided.
467+
synchronized(gpsLocationBuffer) {
468+
if (gpsLocationBuffer.isEmpty()) return null
469+
for (location in gpsLocationBuffer.descendingIterator()) {
470+
if (location.elapsedMillis in (elapsedMillis - GPS_PASSIVE_INTERVAL)..(elapsedMillis + GPS_PASSIVE_INTERVAL)) return location
471+
if (location.elapsedMillis < elapsedMillis) return null
472+
}
450473
}
474+
return null
451475
}
452-
return null
476+
return getGpsLocationFromBuffer(gpsLocationBuffer) ?: if (includeLowAccuracy) getGpsLocationFromBuffer(lowAccuracyGpsLocationBuffer) else null
453477
}
454478

455479
override fun dump(fd: FileDescriptor?, writer: PrintWriter, args: Array<out String>?) {
@@ -463,6 +487,7 @@ class NetworkLocationService : LifecycleService(), WifiDetailsCallback, CellDeta
463487
writer.println("Ichnaea settings: endpoint=${settings.ichneaeEndpoint} contribute=${settings.ichnaeaContribute}")
464488
writer.println("Wifi scan cache size=${wifiScanCache.size()} hits=${wifiScanCache.hitCount()} miss=${wifiScanCache.missCount()} puts=${wifiScanCache.putCount()} evicts=${wifiScanCache.evictionCount()}")
465489
writer.println("GPS location buffer size=${gpsLocationBuffer.size} first=${gpsLocationBuffer.firstOrNull()?.elapsedMillis?.formatRealtime()} last=${gpsLocationBuffer.lastOrNull()?.elapsedMillis?.formatRealtime()}")
490+
writer.println("Low-accuracy GPS location buffer size=${lowAccuracyGpsLocationBuffer.size} first=${lowAccuracyGpsLocationBuffer.firstOrNull()?.elapsedMillis?.formatRealtime()} last=${lowAccuracyGpsLocationBuffer.lastOrNull()?.elapsedMillis?.formatRealtime()}")
466491
cache.dump(writer)
467492
synchronized(activeRequests) {
468493
if (activeRequests.isNotEmpty()) {
@@ -478,6 +503,7 @@ class NetworkLocationService : LifecycleService(), WifiDetailsCallback, CellDeta
478503
const val GPS_BUFFER_SIZE = 60
479504
const val GPS_PASSIVE_INTERVAL = 1000L
480505
const val GPS_PASSIVE_MIN_ACCURACY = 25f
506+
const val GPS_PASSIVE_MIN_ACCURACY_LOW = 10000f // 10 kilometers
481507
const val LOCATION_TIME_CLIFF_START_MS = 30000L
482508
const val LOCATION_TIME_CLIFF_END_MS = 60000L
483509
const val DEBOUNCE_DELAY_MS = 5000L

0 commit comments

Comments
 (0)