summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/data/repositories/LocalStateRepository.kt27
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt29
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt41
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationState.kt4
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationViewModel.kt34
-rw-r--r--app/src/main/res/layout/fragment_fake_location.xml103
-rw-r--r--app/src/main/res/values/strings.xml4
7 files changed, 229 insertions, 13 deletions
diff --git a/app/src/main/java/foundation/e/advancedprivacy/data/repositories/LocalStateRepository.kt b/app/src/main/java/foundation/e/advancedprivacy/data/repositories/LocalStateRepository.kt
index 2afd6ee..fd309a6 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/data/repositories/LocalStateRepository.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/data/repositories/LocalStateRepository.kt
@@ -35,6 +35,9 @@ class LocalStateRepositoryImpl(context: Context) : LocalStateRepository {
private const val SHARED_PREFS_FILE = "localState"
private const val KEY_BLOCK_TRACKERS = "blockTrackers"
private const val KEY_IP_SCRAMBLING = "ipScrambling"
+ private const val KEY_FAKE_ALTITUDE = "fakeAltitude"
+ private const val KEY_FAKE_SPEED = "fakeSpeed"
+ private const val KEY_FAKE_JITTER = "fakeJitter"
private const val KEY_FAKE_LOCATION = "fakeLocation"
private const val KEY_FAKE_LATITUDE = "fakeLatitude"
private const val KEY_FAKE_LONGITUDE = "fakeLongitude"
@@ -66,6 +69,30 @@ class LocalStateRepositoryImpl(context: Context) : LocalStateRepository {
_fakeLocationEnabled.update { enabled }
}
+ override var fakeAltitude: Float
+ get() = sharedPref.getFloat(KEY_FAKE_ALTITUDE, 3.0f)
+ set(value) {
+ sharedPref.edit()
+ .putFloat(KEY_FAKE_ALTITUDE, value)
+ .apply()
+ }
+
+ override var fakeSpeed: Float
+ get() = sharedPref.getFloat(KEY_FAKE_SPEED, 1.0f)
+ set(value) {
+ sharedPref.edit()
+ .putFloat(KEY_FAKE_SPEED, value)
+ .apply()
+ }
+
+ override var fakeJitter: Float
+ get() = sharedPref.getFloat(KEY_FAKE_JITTER, 3.0f)
+ set(value) {
+ sharedPref.edit()
+ .putFloat(KEY_FAKE_JITTER, value)
+ .apply()
+ }
+
override var fakeLocation: Pair<Float, Float>
get() = Pair(
// Initial default value is Quezon City
diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt
index 282116e..8cf5f43 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt
@@ -32,6 +32,7 @@ import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository
import foundation.e.advancedprivacy.dummy.CityDataSource
import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule
import foundation.e.advancedprivacy.fakelocation.domain.usecases.FakeLocationModule
+import foundation.e.advancedprivacy.features.location.FakeLocationState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -49,11 +50,11 @@ class FakeLocationStateUseCase(
private val appContext: Context,
coroutineScope: CoroutineScope
) {
- private val _configuredLocationMode = MutableStateFlow<Triple<LocationMode, Float?, Float?>>(
- Triple(LocationMode.REAL_LOCATION, null, null)
+ private val _configuredLocationMode = MutableStateFlow<FakeLocationState>(
+ FakeLocationState(LocationMode.REAL_LOCATION, null, null, null, null, false, null, null, false)
)
- val configuredLocationMode: StateFlow<Triple<LocationMode, Float?, Float?>> = _configuredLocationMode
+ val configuredLocationMode: StateFlow<FakeLocationState> = _configuredLocationMode
init {
coroutineScope.launch {
@@ -76,8 +77,8 @@ class FakeLocationStateUseCase(
if (isEnabled && hasAcquireMockLocationPermission()) {
fakeLocationModule.startFakeLocation()
- fakeLocationModule.setFakeLocation(fakeLocation.first.toDouble(), fakeLocation.second.toDouble())
- localStateRepository.locationMode.value = configuredLocationMode.value.first
+ fakeLocationModule.setFakeLocation(localStateRepository.fakeAltitude.toDouble(), localStateRepository.fakeSpeed, localStateRepository.fakeJitter, fakeLocation.first.toDouble(), fakeLocation.second.toDouble())
+ localStateRepository.locationMode.value = configuredLocationMode.value.mode
} else {
fakeLocationModule.stopFakeLocation()
localStateRepository.locationMode.value = LocationMode.REAL_LOCATION
@@ -89,6 +90,12 @@ class FakeLocationStateUseCase(
permissionsModule.setAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpModes.ALLOWED)
}
+ fun setFakeLocationParameters(altitude: Float, speed: Float, jitter: Float) {
+ localStateRepository.fakeAltitude = altitude
+ localStateRepository.fakeSpeed = speed
+ localStateRepository.fakeJitter = jitter
+ }
+
fun setSpecificLocation(latitude: Float, longitude: Float) {
setFakeLocation(latitude to longitude, true)
}
@@ -115,16 +122,22 @@ class FakeLocationStateUseCase(
isFakeLocationEnabled: Boolean,
fakeLocation: Pair<Float, Float>,
isSpecificLocation: Boolean = false,
- ): Triple<LocationMode, Float?, Float?> {
- return Triple(
+ ): FakeLocationState {
+ return FakeLocationState(
when {
!isFakeLocationEnabled -> LocationMode.REAL_LOCATION
(fakeLocation in citiesRepository.citiesLocationsList && !isSpecificLocation) ->
LocationMode.RANDOM_LOCATION
else -> LocationMode.SPECIFIC_LOCATION
},
+ null,
+ null,
+ null,
+ null,
+ false,
fakeLocation.first,
- fakeLocation.second
+ fakeLocation.second,
+ false
)
}
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt
index 1c629c2..2b054ab 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt
@@ -244,6 +244,31 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
}
}
+ private fun updateMockLocationParameters() {
+ viewModel.submitAction(
+ Action.UpdateMockLocationParameters(
+ binding.altitude.text.toString().toFloat(),
+ binding.speed.text.toString().toFloat(),
+ binding.jitter.text.toString().toFloat(),
+ )
+ )
+ }
+
+ @Suppress("UNUSED_PARAMETER")
+ private fun onAltitudeTextChanged(editable: Editable?) {
+ updateMockLocationParameters()
+ }
+
+ @Suppress("UNUSED_PARAMETER")
+ private fun onSpeedTextChanged(editable: Editable?) {
+ updateMockLocationParameters()
+ }
+
+ @Suppress("UNUSED_PARAMETER")
+ private fun onJitterTextChanged(editable: Editable?) {
+ updateMockLocationParameters()
+ }
+
@Suppress("UNUSED_PARAMETER")
private fun onLatTextChanged(editable: Editable?) {
if (!binding.edittextLatitude.isFocused ||
@@ -291,6 +316,9 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
}
}
+ binding.altitude.addTextChangedListener(afterTextChanged = ::onAltitudeTextChanged)
+ binding.speed.addTextChangedListener(afterTextChanged = ::onSpeedTextChanged)
+ binding.jitter.addTextChangedListener(afterTextChanged = ::onJitterTextChanged)
binding.edittextLatitude.addTextChangedListener(afterTextChanged = ::onLatTextChanged)
binding.edittextLongitude.addTextChangedListener(afterTextChanged = ::onLonTextChanged)
binding.edittextLatitude.onFocusChangeListener = latLonOnFocusChangeListener
@@ -307,6 +335,19 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
binding.mapView.isEnabled = (state.mode == LocationMode.SPECIFIC_LOCATION)
+ binding.altitude.isEnabled = state.mode == LocationMode.SPECIFIC_LOCATION
+ binding.speed.isEnabled = state.mode == LocationMode.SPECIFIC_LOCATION
+ binding.jitter.isEnabled = state.mode == LocationMode.SPECIFIC_LOCATION
+
+ if(!binding.altitude.isFocused)
+ binding.altitude.setText(state.altitude?.toString())
+
+ if(!binding.speed.isFocused)
+ binding.speed.setText(state.speed?.toString())
+
+ if(!binding.jitter.isFocused)
+ binding.jitter.setText(state.jitter?.toString())
+
if (state.mode == LocationMode.REAL_LOCATION) {
binding.centeredMarker.isVisible = false
} else {
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationState.kt b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationState.kt
index baa672b..12ebecf 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationState.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationState.kt
@@ -23,6 +23,10 @@ import foundation.e.advancedprivacy.domain.entities.LocationMode
data class FakeLocationState(
val mode: LocationMode = LocationMode.REAL_LOCATION,
val currentLocation: Location? = null,
+ val altitude: Float? = null,
+ val speed: Float? = null,
+ val jitter: Float? = null,
+ val joystick: Boolean = false,
val specificLatitude: Float? = null,
val specificLongitude: Float? = null,
val forceRefresh: Boolean = false,
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationViewModel.kt b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationViewModel.kt
index deca4c1..29bfbfa 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationViewModel.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationViewModel.kt
@@ -52,24 +52,32 @@ class FakeLocationViewModel(
val singleEvents = _singleEvents.asSharedFlow()
private val specificLocationInputFlow = MutableSharedFlow<Action.SetSpecificLocationAction>()
+ private val mockLocationParametersInputFlow = MutableSharedFlow<Action.UpdateMockLocationParameters>()
@OptIn(FlowPreview::class)
suspend fun doOnStartedState() = withContext(Dispatchers.Main) {
launch {
merge(
- fakeLocationStateUseCase.configuredLocationMode.map { (mode, lat, lon) ->
+ fakeLocationStateUseCase.configuredLocationMode.map { ss ->
_state.update { s ->
s.copy(
- mode = mode,
- specificLatitude = lat,
- specificLongitude = lon
+ mode = ss.mode,
+ altitude = ss.altitude,
+ speed = ss.speed,
+ jitter = ss.jitter,
+ specificLatitude = ss.specificLatitude,
+ specificLongitude = ss.specificLongitude
)
}
},
specificLocationInputFlow
.debounce(SET_SPECIFIC_LOCATION_DELAY).map { action ->
fakeLocationStateUseCase.setSpecificLocation(action.latitude, action.longitude)
- }
+ },
+ mockLocationParametersInputFlow
+ .debounce(SET_SPECIFIC_LOCATION_DELAY).map { action ->
+ fakeLocationStateUseCase.setFakeLocationParameters(action.altitude, action.speed, action.jitter)
+ },
).collect {}
}
}
@@ -82,6 +90,8 @@ class FakeLocationViewModel(
is Action.UseRandomLocationAction -> fakeLocationStateUseCase.setRandomLocation()
is Action.UseRealLocationAction ->
fakeLocationStateUseCase.stopFakeLocation()
+ is Action.UpdateMockLocationParameters -> updateMockLocationParameters(action)
+ is Action.UseJoystick -> enableJoystick()
}
}
@@ -96,6 +106,14 @@ class FakeLocationViewModel(
specificLocationInputFlow.emit(action)
}
+ private suspend fun updateMockLocationParameters(action: Action.UpdateMockLocationParameters) {
+ mockLocationParametersInputFlow.emit(action)
+ }
+
+ private suspend fun enableJoystick() {
+
+ }
+
sealed class SingleEvent {
object RequestLocationPermission : SingleEvent()
data class ErrorEvent(val error: String) : SingleEvent()
@@ -106,6 +124,12 @@ class FakeLocationViewModel(
object StopListeningLocation : Action()
object UseRealLocationAction : Action()
object UseRandomLocationAction : Action()
+ object UseJoystick : Action()
+ data class UpdateMockLocationParameters(
+ val altitude: Float,
+ val speed: Float,
+ val jitter: Float
+ ) : Action()
data class SetSpecificLocationAction(
val latitude: Float,
val longitude: Float
diff --git a/app/src/main/res/layout/fragment_fake_location.xml b/app/src/main/res/layout/fragment_fake_location.xml
index 5da95e1..47ed7da 100644
--- a/app/src/main/res/layout/fragment_fake_location.xml
+++ b/app/src/main/res/layout/fragment_fake_location.xml
@@ -83,6 +83,109 @@
/>
</RadioGroup>
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:padding="16dp"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ tools:context=".main.MainActivity"
+ >
+
+ <TextView
+ android:id="@+id/fake_location_info_altitude"
+ android:layout_gravity="center_horizontal"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:text="@string/location_altitude"
+ android:lineSpacingExtra="5sp"
+ />
+
+ <EditText
+ android:id="@+id/altitude"
+ android:inputType="numberDecimal"
+ android:layout_width="wrap_content"
+ android:layout_height="24dp"
+ />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:padding="16dp"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ tools:context=".main.MainActivity"
+ >
+
+ <TextView
+ android:id="@+id/fake_location_info_speed"
+ android:layout_gravity="center_horizontal"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:text="@string/location_speed"
+ android:lineSpacingExtra="5sp"
+ />
+
+ <EditText
+ android:id="@+id/speed"
+ android:inputType="numberDecimal"
+ android:layout_width="wrap_content"
+ android:layout_height="24dp"
+ />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:padding="16dp"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ tools:context=".main.MainActivity"
+ >
+
+ <TextView
+ android:id="@+id/fake_location_info_jitter"
+ android:layout_gravity="center_horizontal"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:text="@string/location_jitter"
+ android:lineSpacingExtra="5sp"
+ />
+
+ <EditText
+ android:id="@+id/jitter"
+ android:inputType="numberDecimal"
+ android:layout_width="wrap_content"
+ android:layout_height="24dp"
+ />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:padding="16dp"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ tools:context=".main.MainActivity"
+ >
+
+ <TextView
+ android:id="@+id/fake_location_info_joystick"
+ android:layout_gravity="center_horizontal"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:text="@string/location_joystick"
+ android:lineSpacingExtra="5sp"
+ />
+
+ <Switch
+ android:id="@+id/joystick_enable"
+ android:layout_width="wrap_content"
+ android:layout_height="24dp"
+ android:checked="true"
+ />
+
+ </LinearLayout>
<FrameLayout
android:layout_marginTop="16dp"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index aa33837..416a0d2 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -82,6 +82,10 @@
<!-- Location -->
<string name="location_title" weblate_ctx="location-1">Manage my location</string>
<string name="location_info" weblate_ctx="location-1">Your location can reveal a lot about yourself or your activities.\n\nManage my location enables you to use a fake location instead of your real position. This way, your real location isn\'t shared with applications that might be snooping too much.</string>
+ <string name="location_altitude">Altitude [m]</string>
+ <string name="location_speed">Speed [km/h]</string>
+ <string name="location_jitter">Jitter [m]</string>
+ <string name="location_joystick">Enable joystick</string>
<string name="location_use_real_location" weblate_ctx="location-1">Use my real location</string>
<string name="location_use_random_location" weblate_ctx="location-1">Use a random plausible location</string>
<string name="location_use_specific_location" weblate_ctx="location-1">Use a specific location</string>