summaryrefslogtreecommitdiff
path: root/fakelocation/src
diff options
context:
space:
mode:
authorLeonard Kugis <leonard@kug.is>2024-01-02 17:53:12 +0100
committerLeonard Kugis <leonard@kug.is>2024-01-02 17:53:12 +0100
commit5db0bdfdf62ae0915b587399a0ff4ce53bca813b (patch)
tree538a18ce0adbf6e600ee77a48e51d8c67649b0c6 /fakelocation/src
parent298dff2a877680e928b37e3a1336dc7d7aa52dfb (diff)
Implemented route mode
Diffstat (limited to 'fakelocation/src')
-rw-r--r--fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/domain/usecases/FakeLocationModule.kt9
-rw-r--r--fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/services/FakeLocationService.kt108
2 files changed, 106 insertions, 11 deletions
diff --git a/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/domain/usecases/FakeLocationModule.kt b/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/domain/usecases/FakeLocationModule.kt
index 89d5628..7424f38 100644
--- a/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/domain/usecases/FakeLocationModule.kt
+++ b/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/domain/usecases/FakeLocationModule.kt
@@ -29,6 +29,7 @@ import android.os.Build
import android.os.SystemClock
import android.util.Log
import foundation.e.advancedprivacy.fakelocation.services.FakeLocationService
+import foundation.e.advancedprivacy.domain.entities.FakeLocationCoordinate
/**
* Implementation of the functionality of fake location.
@@ -86,6 +87,14 @@ class FakeLocationModule(private val context: Context) {
}
}
+ fun routeStart(route: List<FakeLocationCoordinate>, loopEnabled: Boolean) {
+ context.startService(FakeLocationService.buildRouteIntent(context, route, loopEnabled))
+ }
+
+ fun routeStop() {
+ context.stopService(FakeLocationService.buildStopIntent(context))
+ }
+
fun setFakeLocation(altitude: Double, speed: Float, jitter: Float, latitude: Double, longitude: Double) {
context.startService(FakeLocationService.buildFakeLocationIntent(context, altitude, speed, jitter, latitude, longitude))
}
diff --git a/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/services/FakeLocationService.kt b/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/services/FakeLocationService.kt
index 2d85e6c..c388afc 100644
--- a/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/services/FakeLocationService.kt
+++ b/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/services/FakeLocationService.kt
@@ -25,13 +25,18 @@ import android.os.CountDownTimer
import android.os.IBinder
import android.util.Log
import foundation.e.advancedprivacy.fakelocation.domain.usecases.FakeLocationModule
+import foundation.e.advancedprivacy.domain.entities.FakeLocationCoordinate
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import kotlin.math.sqrt
import kotlin.random.Random
class FakeLocationService : Service() {
enum class Actions {
- START_FAKE_LOCATION
+ START_FAKE_LOCATION,
+ START_ROUTE
}
companion object {
@@ -43,6 +48,8 @@ class FakeLocationService : Service() {
private const val PARAM_JITTER = "PARAM_JITTER"
private const val PARAM_LATITUDE = "PARAM_LATITUDE"
private const val PARAM_LONGITUDE = "PARAM_LONGITUDE"
+ private const val PARAM_ROUTE = "PARAM_ROUTE"
+ private const val PARAM_ROUTE_LOOP = "PARAM_ROUTE_LOOP"
fun buildFakeLocationIntent(context: Context, altitude: Double, speed: Float, jitter: Float, latitude: Double, longitude: Double): Intent {
return Intent(context, FakeLocationService::class.java).apply {
@@ -55,12 +62,22 @@ class FakeLocationService : Service() {
}
}
+ fun buildRouteIntent(context: Context, route: List<FakeLocationCoordinate>, loopRoute: Boolean): Intent {
+ return Intent(context, FakeLocationService::class.java).apply {
+ action = Actions.START_ROUTE.name
+ putExtra(PARAM_ROUTE, Gson().toJson(route))
+ putExtra(PARAM_ROUTE_LOOP, loopRoute)
+ }
+ }
+
fun buildStopIntent(context: Context) = Intent(context, FakeLocationService::class.java)
}
private lateinit var fakeLocationModule: FakeLocationModule
- private var countDownTimer: CountDownTimer? = null
+ private var cdtFakeLocation: CountDownTimer? = null
+ private var cdtRoute: CountDownTimer? = null
+ private var routeTime: Float = 0f
private var altitude: Double? = null
private var speed: Float? = null
@@ -68,6 +85,10 @@ class FakeLocationService : Service() {
private var fakeLocation: Pair<Double, Double>? = null
+ private var route: List<FakeLocationCoordinate>? = null
+ private var loopRoute: Boolean = false
+ private var routeReversed: Boolean = false
+
override fun onCreate() {
super.onCreate()
fakeLocationModule = FakeLocationModule(applicationContext)
@@ -84,7 +105,12 @@ class FakeLocationService : Service() {
it.getDoubleExtra(PARAM_LATITUDE, 0.0),
it.getDoubleExtra(PARAM_LONGITUDE, 0.0)
)
- initTimer()
+ initTimerFakeLocation()
+ }
+ Actions.START_ROUTE -> {
+ route = Gson().fromJson(it.getStringExtra(PARAM_ROUTE) ?: "[]", object : TypeToken<List<FakeLocationCoordinate>>() {}.type)
+ loopRoute = it.getBooleanExtra(PARAM_ROUTE_LOOP, false)
+ initTimerRoute()
}
else -> {}
}
@@ -94,13 +120,14 @@ class FakeLocationService : Service() {
}
override fun onDestroy() {
- countDownTimer?.cancel()
+ cdtFakeLocation?.cancel()
+ cdtRoute?.cancel()
super.onDestroy()
}
- private fun initTimer() {
- countDownTimer?.cancel()
- countDownTimer = object : CountDownTimer(PERIOD_UPDATES_SERIE, PERIOD_LOCATION_UPDATE) {
+ private fun initTimerFakeLocation() {
+ cdtFakeLocation?.cancel()
+ cdtFakeLocation = object : CountDownTimer(PERIOD_UPDATES_SERIE, PERIOD_LOCATION_UPDATE) {
override fun onTick(millisUntilFinished: Long) {
var altitude_buf: Double = altitude ?: return
var speed_buf: Float = speed ?: return
@@ -109,11 +136,11 @@ class FakeLocationService : Service() {
if(fakeLocation != null && altitude != null && speed != null && jitter != null) {
try {
fakeLocationModule.setTestProviderLocation(
- altitude_buf + ((Random.nextFloat() * jitter_buf) - (jitter_buf * 0.5f)),
+ (altitude_buf + ((Random.nextFloat() * jitter_buf) - (jitter_buf * 0.5f))).toDouble(),
speed_buf + ((Random.nextFloat() * jitter_buf) - (jitter_buf * 0.5f)),
jitter_buf,
- fakeLocation_buf.first + (((Random.nextFloat() * jitter_buf) - (jitter_buf * 0.5f)) / 111139.0f),
- fakeLocation_buf.second + (((Random.nextFloat() * jitter_buf) - (jitter_buf * 0.5f)) / 111139.0f)
+ (fakeLocation_buf.first + (((Random.nextFloat() * jitter_buf) - (jitter_buf * 0.5f)) / 111139.0f)).toDouble(),
+ (fakeLocation_buf.second + (((Random.nextFloat() * jitter_buf) - (jitter_buf * 0.5f)) / 111139.0f)).toDouble()
)
} catch (e: Exception) {
Log.d("FakeLocationService", "setting fake location", e)
@@ -122,7 +149,66 @@ class FakeLocationService : Service() {
}
override fun onFinish() {
- initTimer()
+ initTimerFakeLocation()
+ }
+ }.start()
+ }
+
+ private fun calculateRouteSegment(route: List<FakeLocationCoordinate>, routeTime: Float): Pair<FakeLocationCoordinate,Pair<Float,Float>>? {
+ if(route.size < 2)
+ return null
+ var prev = route.first()
+ var timeCurrent: Float = 0f
+ do {
+ var route_current = if(routeReversed) route.reversed() else route
+ for(coord in route_current) {
+ var direction = Pair<Float,Float>((coord.latitude - prev.latitude) * 111139.0f, (coord.longitude - prev.longitude) * 111139.0f)
+ if(!(coord.latitude == prev.latitude && coord.longitude == prev.longitude)) {
+ var distance_target = sqrt((direction.first * direction.first) + (direction.second * direction.second))
+ var direction_unit = Pair<Float,Float>(direction.first / distance_target, direction.second / distance_target)
+ var location_meters = Pair<Float,Float>(direction_unit.first * (routeTime - timeCurrent) * prev.speed,
+ direction_unit.second * (routeTime - timeCurrent) * prev.speed)
+ var distance_current = sqrt((location_meters.first * location_meters.first) + (location_meters.second - location_meters.second))
+ var location = Pair<Float,Float>(prev.latitude + (location_meters.first / 111139.0f), prev.longitude + (location_meters.second / 111139.0f))
+ if(distance_current < distance_target)
+ return Pair<FakeLocationCoordinate,Pair<Float,Float>>(prev, location)
+ timeCurrent += distance_target / prev.speed
+ prev = coord
+ }
+ }
+ if(loopRoute)
+ routeReversed = !routeReversed
+ } while(loopRoute)
+ return null
+ }
+
+ private fun initTimerRoute() {
+ cdtRoute?.cancel()
+ routeTime = 0f
+ cdtRoute = object : CountDownTimer(PERIOD_UPDATES_SERIE, PERIOD_LOCATION_UPDATE) {
+ override fun onTick(millisUntilFinished: Long) {
+ var route_buf: List<FakeLocationCoordinate> = route ?: return
+ var coord = calculateRouteSegment(route_buf, routeTime)
+ if(coord == null) {
+ // done with route
+ return
+ }
+ try {
+ fakeLocationModule.setTestProviderLocation(
+ (coord.first.altitude + ((Random.nextFloat() * coord.first.jitter) - (coord.first.jitter * 0.5f))).toDouble(),
+ coord.first.speed + ((Random.nextFloat() * coord.first.jitter) - (coord.first.jitter * 0.5f)),
+ coord.first.jitter,
+ (coord.second.first + (((Random.nextFloat() * coord.first.jitter) - (coord.first.jitter * 0.5f)) / 111139.0f)).toDouble(),
+ (coord.second.second + (((Random.nextFloat() * coord.first.jitter) - (coord.first.jitter * 0.5f)) / 111139.0f)).toDouble()
+ )
+ } catch (e: Exception) {
+ Log.d("FakeLocationService", "setting fake location", e)
+ }
+ routeTime += (PERIOD_LOCATION_UPDATE / 1000f)
+ }
+
+ override fun onFinish() {
+ initTimerRoute()
}
}.start()
}