diff options
Diffstat (limited to 'app/src/main/java')
3 files changed, 134 insertions, 19 deletions
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt index d94f71c..fe9359a 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt @@ -54,10 +54,13 @@ class FakeLocationFeature( data class ErrorEvent(val error: String) : SingleEvent() } - sealed class Action { + sealed class Action() { data class UpdateLocationAction(val latLng: LatLng) : Action() - object UseRealLocationAction : Action() - data class UseRandomLocationAction(val cities: Array<String>) : Action() { + data class UseRealLocationAction(val locationApiDelegate: LocationApiDelegate) : Action() + data class UseRandomLocationAction( + val locationApiDelegate: LocationApiDelegate, + val cities: Array<String> + ) : Action() { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false @@ -74,8 +77,12 @@ class FakeLocationFeature( } } - object UseSpecificLocationAction : Action() - data class SetFakeLocationAction(val latitude: Double, val longitude: Double) : Action() + data class UseSpecificLocationAction(val locationApiDelegate: LocationApiDelegate) : Action() + data class SetFakeLocationAction( + val locationApiDelegate: LocationApiDelegate, + val latitude: Double, + val longitude: Double + ) : Action() } sealed class Effect { @@ -139,7 +146,7 @@ class FakeLocationFeature( action.latitude, action.longitude ) - // TODO: Call fake location api with specific coordinates here. + action.locationApiDelegate.setFakeLocation(action.latitude, action.longitude) val success = DummyDataSource.setLocationMode( LocationMode.CUSTOM_LOCATION, location @@ -156,7 +163,7 @@ class FakeLocationFeature( } is Action.UseRandomLocationAction -> { val randomCity = CityDataSource.getRandomCity(action.cities) - // TODO: Call fake location api with random location here. + action.locationApiDelegate.setFakeLocation(randomCity.latitude, randomCity.longitude) val success = DummyDataSource.setLocationMode( LocationMode.RANDOM_LOCATION, randomCity.toRandomLocation() @@ -171,8 +178,8 @@ class FakeLocationFeature( ) } } - Action.UseRealLocationAction -> { - // TODO: Call turn off fake location api here. + is Action.UseRealLocationAction -> { + action.locationApiDelegate.startRealLocation() val success = DummyDataSource.setLocationMode(LocationMode.REAL_LOCATION) if (success) { flowOf( @@ -184,7 +191,7 @@ class FakeLocationFeature( ) } } - Action.UseSpecificLocationAction -> { + is Action.UseSpecificLocationAction -> { flowOf(Effect.SpecificLocationSelectedEffect) } } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt index 96bebb7..c11a7ea 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt @@ -21,6 +21,7 @@ import android.annotation.SuppressLint import android.content.Context import android.os.Bundle import android.os.Looper +import android.os.Process import android.text.Editable import android.util.Log import android.view.Gravity @@ -57,12 +58,17 @@ import com.mapbox.mapboxsdk.maps.Style import foundation.e.flowmvi.MVIView import foundation.e.privacycentralapp.R import foundation.e.privacycentralapp.dummy.LocationMode +import foundation.e.privacymodules.location.FakeLocation +import foundation.e.privacymodules.location.IFakeLocation +import foundation.e.privacymodules.permissions.PermissionsPrivacyModule +import foundation.e.privacymodules.permissions.data.ApplicationDescription import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch +import java.lang.Exception class FakeLocationFragment : Fragment(R.layout.fragment_fake_location), @@ -129,6 +135,23 @@ class FakeLocationFragment : private const val TAG = "FakeLocationFragment" private const val DEFAULT_INTERVAL_IN_MILLISECONDS = 1000L private const val DEFAULT_MAX_WAIT_TIME = DEFAULT_INTERVAL_IN_MILLISECONDS * 5 + private const val DROPPED_MARKER_LAYER_ID = "DROPPED_MARKER_LAYER_ID" + } + + private val fakeLocationModule: IFakeLocation by lazy { FakeLocation(this.requireContext()) } + private val permissionsModule by lazy { PermissionsPrivacyModule(this.requireContext()) } + + private val appDesc by lazy { + ApplicationDescription( + packageName = this.requireContext().packageName, + uid = Process.myUid(), + label = getString(R.string.app_name), + icon = null + ) + } + + private val locationApiDelegate by lazy { + LocationApiDelegate(fakeLocationModule, permissionsModule, appDesc) } override fun onCreate(savedInstanceState: Bundle?) { @@ -146,6 +169,7 @@ class FakeLocationFragment : } is FakeLocationFeature.SingleEvent.SpecificLocationSavedEvent -> { // Hide camera hover marker when custom location is picked from map. + displayToast("Specific location selected") hoveringMarker?.visibility = View.GONE isCameraMoved = false } @@ -161,6 +185,7 @@ class FakeLocationFragment : } } } + locationApiDelegate.startRealLocation() } override fun onAttach(context: Context) { @@ -256,31 +281,33 @@ class FakeLocationFragment : } } - private fun saveSpecificLocation(latitude: Double, longitude: Double) { - viewModel.submitAction( - FakeLocationFeature.Action.SetFakeLocationAction(latitude, longitude) - ) - } - private fun toggleLocationType(radioButton: View?) { if (radioButton is RadioButton) { val checked = radioButton.isChecked when (radioButton.id) { R.id.radio_use_real_location -> if (checked) { - viewModel.submitAction(FakeLocationFeature.Action.UseRealLocationAction) + viewModel.submitAction( + FakeLocationFeature.Action.UseRealLocationAction( + locationApiDelegate + ) + ) } R.id.radio_use_random_location -> if (checked) { viewModel.submitAction( FakeLocationFeature.Action.UseRandomLocationAction( - resources.getStringArray(R.array.cities) + locationApiDelegate, resources.getStringArray(R.array.cities) ) ) } R.id.radio_use_specific_location -> if (checked) { - viewModel.submitAction(FakeLocationFeature.Action.UseSpecificLocationAction) + viewModel.submitAction( + FakeLocationFeature.Action.UseSpecificLocationAction( + locationApiDelegate + ) + ) } } } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/LocationApiDelegate.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/LocationApiDelegate.kt new file mode 100644 index 0000000..dd2e5c1 --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/LocationApiDelegate.kt @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package foundation.e.privacycentralapp.features.location + +import android.app.AppOpsManager +import android.util.Log +import foundation.e.privacymodules.location.IFakeLocation +import foundation.e.privacymodules.permissions.PermissionsPrivacyModule +import foundation.e.privacymodules.permissions.data.AppOpModes +import foundation.e.privacymodules.permissions.data.ApplicationDescription +import java.lang.Exception + +class LocationApiDelegate( + private val fakeLocationModule: IFakeLocation, + private val permissionsModule: PermissionsPrivacyModule, + private val appDesc: ApplicationDescription +) { + + private val TAG = LocationApiDelegate::class.simpleName + + fun setFakeLocation(latitude: Double, longitude: Double) { + if (permissionsModule.getAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION) != AppOpModes.ALLOWED) { + permissionsModule.setAppOpMode( + appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, + AppOpModes.ALLOWED + ) + } + try { + fakeLocationModule.startFakeLocation() + } catch (e: Exception) { + Log.e(TAG, "Can't startFakeLocation", e) + } + fakeLocationModule.setFakeLocation(latitude, longitude) + } + + fun stopFakeLocation() { + try { + permissionsModule.setAppOpMode( + appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, + AppOpModes.IGNORED + ) + permissionsModule.setAppOpMode( + appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, + AppOpModes.IGNORED + ) + fakeLocationModule.stopFakeLocation() + } catch (e: Exception) { + Log.e(TAG, "Can't stop FakeLocation", e) + } + } + fun startRealLocation() { + stopFakeLocation() + try { + permissionsModule.setAppOpMode( + appDesc, AppOpsManager.OPSTR_COARSE_LOCATION, + AppOpModes.ALLOWED + ) + permissionsModule.setAppOpMode( + appDesc, AppOpsManager.OPSTR_FINE_LOCATION, + AppOpModes.ALLOWED + ) + } catch (e: Exception) { + Log.e(TAG, "Can't start RealLocation", e) + } + } +} |