UnifiedNlp/service/src/main/kotlin/org/microg/nlp/service/UnifiedLocationServiceInsta...

113 lines
4.5 KiB
Kotlin

/*
* SPDX-FileCopyrightText: 2019, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.nlp.service
import android.app.ActivityManager
import android.content.Context
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.location.Location
import android.os.Binder.getCallingPid
import android.os.Binder.getCallingUid
import android.os.Bundle
import android.os.RemoteException
import android.util.Log
import androidx.lifecycle.lifecycleScope
import org.microg.nlp.client.UnifiedLocationClient.Companion.KEY_FORCE_NEXT_UPDATE
import org.microg.nlp.client.UnifiedLocationClient.Companion.KEY_OP_PACKAGE_NAME
import org.microg.nlp.client.UnifiedLocationClient.Companion.PERMISSION_SERVICE_ADMIN
import java.io.PrintWriter
@Deprecated("Use LocationService or GeocodeService")
class UnifiedLocationServiceInstance(private val root: UnifiedLocationServiceRoot) : UnifiedLocationService.Default() {
private var callback: LocationCallback? = null
private var interval: Long = 0
private var singleUpdatePending = false
val callingPackage = root.context.getCallingPackage()
private var opPackage: String? = null
private val debugPackageString: String?
get() {
if (opPackage == callingPackage || opPackage == null) return callingPackage
return "$callingPackage for $opPackage"
}
private fun Context.getCallingPackage(): String? {
val manager = getSystemService(Context.ACTIVITY_SERVICE) as? ActivityManager
val callingPid = getCallingPid()
if (manager != null && callingPid > 0) {
manager.runningAppProcesses.find { it.pid == callingPid }?.pkgList?.singleOrNull()?.let { return it }
}
return packageManager.getPackagesForUid(getCallingUid())?.singleOrNull()
}
fun reportLocation(location: Location) {
try {
if (callback != null) {
callback!!.onLocationUpdate(location)
}
if (singleUpdatePending) {
singleUpdatePending = false
root.updateLocationInterval()
}
} catch (e: RemoteException) {
root.onDisconnected(this)
}
}
fun getInterval(): Long {
// TODO: Do not report interval if client should no longer receive
return if (singleUpdatePending) UnifiedLocationServiceRoot.MIN_LOCATION_INTERVAL else interval
}
override fun registerLocationCallback(callback: LocationCallback, options: Bundle) {
if (root.context.checkCallingPermission(PERMISSION_SERVICE_ADMIN) == PERMISSION_GRANTED && options.containsKey(KEY_OP_PACKAGE_NAME)) {
opPackage = options.getString(KEY_OP_PACKAGE_NAME)
}
Log.d(TAG, "registerLocationCallback[$callingPackage]")
this.callback = callback
}
override fun setUpdateInterval(interval: Long, options: Bundle) {
if (root.context.checkCallingPermission(PERMISSION_SERVICE_ADMIN) == PERMISSION_GRANTED && options.containsKey(KEY_OP_PACKAGE_NAME)) {
opPackage = options.getString(KEY_OP_PACKAGE_NAME)
}
Log.d(TAG, "setUpdateInterval[$debugPackageString] interval: $interval")
this.interval = interval
root.updateLocationInterval()
}
override fun requestSingleUpdate(options: Bundle) {
if (root.context.checkCallingPermission(PERMISSION_SERVICE_ADMIN) == PERMISSION_GRANTED && options.containsKey(KEY_OP_PACKAGE_NAME)) {
opPackage = options.getString(KEY_OP_PACKAGE_NAME)
}
val lastLocation = root.lastReportedLocation
if (lastLocation == null || lastLocation.time < System.currentTimeMillis() - UnifiedLocationServiceRoot.MAX_LOCATION_AGE || options.getBoolean(KEY_FORCE_NEXT_UPDATE, false)) {
Log.d(TAG, "requestSingleUpdate[$debugPackageString] requesting new location")
singleUpdatePending = true
root.lifecycleScope.launchWhenStarted {
root.locationFuser.update()
root.updateLocationInterval()
}
} else if (callback != null) {
Log.d(TAG, "requestSingleUpdate[$debugPackageString] using last location ")
try {
this.callback!!.onLocationUpdate(lastLocation)
} catch (e: RemoteException) {
root.onDisconnected(this)
throw e
}
}
}
fun dump(writer: PrintWriter?) {
writer?.println("$debugPackageString: interval $interval, single $singleUpdatePending")
}
companion object {
private val TAG = "ULocService"
}
}