VancedMicroG/play-services-location-core/src/main/java/org/microg/gms/location/UnifiedLocationProvider.kt

95 lines
3.4 KiB
Kotlin

package org.microg.gms.location
import android.content.Context
import android.location.Location
import android.util.Log
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.microg.nlp.client.UnifiedLocationClient
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
class UnifiedLocationProvider(context: Context?, changeListener: LocationChangeListener) {
private val client: UnifiedLocationClient
private var connectedMinTime: Long = 0
private var lastLocation: Location? = null
private val connected = AtomicBoolean(false)
private val changeListener: LocationChangeListener
private val requests: MutableList<LocationRequestHelper> = ArrayList()
private val listener: UnifiedLocationClient.LocationListener = object : UnifiedLocationClient.LocationListener {
override fun onLocation(location: Location) {
lastLocation = location
changeListener.onLocationChanged()
}
}
private fun updateLastLocation() {
GlobalScope.launch {
client.getLastLocation()?.let { lastLocation = it }
}
}
fun addRequest(request: LocationRequestHelper) {
Log.d(TAG, "unified network: addRequest $request")
for (i in 0..requests.size) {
if (i >= requests.size) break
val req = requests[i]
if (req.respondsTo(request.pendingIntent) || req.respondsTo(request.listener) || req.respondsTo(request.callback)) {
requests.removeAt(i)
}
}
requests.add(request)
updateConnection()
}
fun removeRequest(request: LocationRequestHelper) {
Log.d(TAG, "unified network: removeRequest $request")
requests.remove(request)
updateConnection()
}
fun getLastLocation(): Location? {
if (lastLocation == null) {
Log.d(TAG, "uh-ok: last location for unified network is null!")
}
return lastLocation
}
@Synchronized
private fun updateConnection() {
if (connected.get() && requests.isEmpty()) {
Log.d(TAG, "unified network: no longer requesting location update")
client.removeLocationUpdates(listener)
connected.set(false)
} else if (!requests.isEmpty()) {
var minTime = Long.MAX_VALUE
val sb = StringBuilder()
var opPackageName: String? = null
for (request in requests) {
if (request.locationRequest.interval < minTime) {
opPackageName = request.packageName
minTime = request.locationRequest.interval
}
if (sb.isNotEmpty()) sb.append(", ")
sb.append("${request.packageName}:${request.locationRequest.interval}ms")
}
client.opPackageName = opPackageName
Log.d(TAG, "unified network: requesting location updates with interval ${minTime}ms ($sb)")
if (!connected.get() || connectedMinTime != minTime) {
client.requestLocationUpdates(listener, minTime)
}
connected.set(true)
connectedMinTime = minTime
}
}
companion object {
const val TAG = "GmsLocProviderU"
}
init {
client = UnifiedLocationClient[context!!]
this.changeListener = changeListener
updateLastLocation()
}
}