From c8d88ec3364218802bc48257b7766ad8f19a6e45 Mon Sep 17 00:00:00 2001
From: Guillaume Jacquart <guillaume.jacquart@hoodbrains.com>
Date: Wed, 17 Aug 2022 08:49:03 +0000
Subject: 2-Simplify sources modules tree

---
 .../e/privacycentralapp/DependencyContainer.kt     |  5 ++--
 .../domain/usecases/FakeLocationStateUseCase.kt    | 33 +++++++++++-----------
 .../features/location/FakeLocationFragment.kt      | 23 +++++++++++++--
 .../features/location/FakeLocationViewModel.kt     | 16 ++++++++---
 4 files changed, 51 insertions(+), 26 deletions(-)

(limited to 'app/src/main/java/foundation/e')

diff --git a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
index 6be3724..a44a00a 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
@@ -40,16 +40,15 @@ import foundation.e.privacycentralapp.features.location.FakeLocationViewModel
 import foundation.e.privacycentralapp.features.trackers.TrackersViewModel
 import foundation.e.privacycentralapp.features.trackers.apptrackers.AppTrackersFragment
 import foundation.e.privacycentralapp.features.trackers.apptrackers.AppTrackersViewModel
+import foundation.e.privacymodules.fakelocation.FakeLocationModule
 import foundation.e.privacymodules.ipscrambler.IpScramblerModule
 import foundation.e.privacymodules.ipscramblermodule.IIpScramblerModule
-import foundation.e.privacymodules.location.FakeLocationModule
 import foundation.e.privacymodules.location.IFakeLocationModule
 import foundation.e.privacymodules.permissions.PermissionsPrivacyModule
 import foundation.e.privacymodules.permissions.data.ApplicationDescription
 import foundation.e.privacymodules.trackers.api.BlockTrackersPrivacyModule
 import foundation.e.privacymodules.trackers.api.TrackTrackersPrivacyModule
 import kotlinx.coroutines.DelicateCoroutinesApi
-import kotlinx.coroutines.FlowPreview
 import kotlinx.coroutines.GlobalScope
 
 /**
@@ -61,7 +60,7 @@ class DependencyContainer(val app: Application) {
     val context: Context by lazy { app.applicationContext }
 
     // Drivers
-    private val fakeLocationModule: IFakeLocationModule by lazy { FakeLocationModule(app.applicationContext) }
+    private val fakeLocationModule: FakeLocationModule by lazy { FakeLocationModule(app.applicationContext) }
     private val permissionsModule by lazy { PermissionsPrivacyModule(app.applicationContext) }
     private val ipScramblerModule: IIpScramblerModule by lazy { IpScramblerModule(app.applicationContext) }
 
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt
index aa4276d..f7b5439 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt
@@ -28,7 +28,7 @@ import android.util.Log
 import foundation.e.privacycentralapp.data.repositories.LocalStateRepository
 import foundation.e.privacycentralapp.domain.entities.LocationMode
 import foundation.e.privacycentralapp.dummy.CityDataSource
-import foundation.e.privacymodules.location.IFakeLocationModule
+import foundation.e.privacymodules.fakelocation.FakeLocationModule
 import foundation.e.privacymodules.permissions.PermissionsPrivacyModule
 import foundation.e.privacymodules.permissions.data.AppOpModes
 import foundation.e.privacymodules.permissions.data.ApplicationDescription
@@ -39,7 +39,7 @@ import kotlinx.coroutines.launch
 import kotlin.random.Random
 
 class FakeLocationStateUseCase(
-    private val fakeLocationModule: IFakeLocationModule,
+    private val fakeLocationModule: FakeLocationModule,
     private val permissionsModule: PermissionsPrivacyModule,
     private val localStateRepository: LocalStateRepository,
     private val citiesRepository: CityDataSource,
@@ -61,23 +61,15 @@ class FakeLocationStateUseCase(
     private val locationManager: LocationManager
         get() = appContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
 
-    private fun acquireLocationPermission() {
-        if (appContext.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
-            permissionsModule.toggleDangerousPermission(
-                appDesc,
-                android.Manifest.permission.ACCESS_FINE_LOCATION,
-                true
-            )
-        }
+    private fun hasAcquireLocationPermission(): Boolean {
+        return (appContext.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
+            || permissionsModule.toggleDangerousPermission(appDesc, android.Manifest.permission.ACCESS_FINE_LOCATION, true)
     }
 
     private fun applySettings(isQuickPrivacyEnabled: Boolean, fakeLocation: Pair<Float, Float>?, isSpecificLocation: Boolean = false) {
         _configuredLocationMode.value = computeLocationMode(fakeLocation, isSpecificLocation)
 
-        if (isQuickPrivacyEnabled && fakeLocation != null) {
-            if (permissionsModule.getAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION) != AppOpModes.ALLOWED) {
-                permissionsModule.setAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpModes.ALLOWED)
-            }
+        if (isQuickPrivacyEnabled && fakeLocation != null && hasAcquireMockLocationPermission()) {
             fakeLocationModule.startFakeLocation()
             fakeLocationModule.setFakeLocation(fakeLocation.first.toDouble(), fakeLocation.second.toDouble())
             localStateRepository.locationMode.value = configuredLocationMode.value.first
@@ -87,6 +79,11 @@ class FakeLocationStateUseCase(
         }
     }
 
+    private fun hasAcquireMockLocationPermission(): Boolean {
+        return (permissionsModule.getAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION) == AppOpModes.ALLOWED)
+            || permissionsModule.setAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpModes.ALLOWED)
+    }
+
     fun setSpecificLocation(latitude: Float, longitude: Float) {
         if (!localStateRepository.isQuickPrivacyEnabled) {
             localStateRepository.setShowQuickPrivacyDisabledMessage(true)
@@ -161,8 +158,11 @@ class FakeLocationStateUseCase(
         }
     }
 
-    fun startListeningLocation() {
-        requestLocationUpdates(localListener)
+    fun startListeningLocation(): Boolean {
+        return if (hasAcquireLocationPermission()) {
+            requestLocationUpdates(localListener)
+            true
+        } else false
     }
 
     fun stopListeningLocation() {
@@ -170,7 +170,6 @@ class FakeLocationStateUseCase(
     }
 
     fun requestLocationUpdates(listener: LocationListener) {
-        acquireLocationPermission()
         try {
             locationManager.requestLocationUpdates(
                 LocationManager.NETWORK_PROVIDER, // TODO: tight this with fakelocation module.
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 2b858e9..d98cb5d 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
@@ -17,6 +17,7 @@
 
 package foundation.e.privacycentralapp.features.location
 
+import android.Manifest
 import android.annotation.SuppressLint
 import android.content.Context
 import android.location.Location
@@ -24,6 +25,7 @@ import android.os.Bundle
 import android.text.Editable
 import android.view.View
 import android.widget.Toast
+import androidx.activity.result.contract.ActivityResultContracts
 import androidx.annotation.NonNull
 import androidx.core.view.isVisible
 import androidx.core.widget.addTextChangedListener
@@ -81,6 +83,16 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
 
     private var inputJob: Job? = null
 
+    private val locationPermissionRequest = registerForActivityResult(
+        ActivityResultContracts.RequestMultiplePermissions()
+    ) { permissions ->
+        if (permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false)
+            || permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false)
+        ) {
+            viewModel.submitAction(Action.StartListeningLocation)
+        } // TODO: else.
+    }
+
     companion object {
         private const val DEBOUNCE_PERIOD = 1000L
     }
@@ -147,6 +159,13 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
                         is FakeLocationViewModel.SingleEvent.LocationUpdatedEvent -> {
                             updateLocation(event.location, event.mode)
                         }
+                        is FakeLocationViewModel.SingleEvent.RequestLocationPermission -> {
+                            // TODO for standalone: rationale dialog
+                            locationPermissionRequest.launch(arrayOf(
+                                Manifest.permission.ACCESS_FINE_LOCATION,
+                                Manifest.permission.ACCESS_COARSE_LOCATION
+                            ))
+                        }
                     }
                 }
             }
@@ -326,13 +345,13 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
 
     override fun onResume() {
         super.onResume()
-        viewModel.submitAction(Action.EnterScreen)
+        viewModel.submitAction(Action.StartListeningLocation)
         binding.mapView.onResume()
     }
 
     override fun onPause() {
         super.onPause()
-        viewModel.submitAction(Action.LeaveScreen)
+        viewModel.submitAction(Action.StopListeningLocation)
         binding.mapView.onPause()
     }
 
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt
index af20a72..afba3d0 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt
@@ -86,8 +86,8 @@ class FakeLocationViewModel(
 
     fun submitAction(action: Action) = viewModelScope.launch {
         when (action) {
-            is Action.EnterScreen -> fakeLocationStateUseCase.startListeningLocation()
-            is Action.LeaveScreen -> fakeLocationStateUseCase.stopListeningLocation()
+            is Action.StartListeningLocation -> actionStartListeningLocation()
+            is Action.StopListeningLocation -> fakeLocationStateUseCase.stopListeningLocation()
             is Action.SetSpecificLocationAction -> setSpecificLocation(action)
             is Action.UseRandomLocationAction -> fakeLocationStateUseCase.setRandomLocation()
             is Action.UseRealLocationAction ->
@@ -97,18 +97,26 @@ class FakeLocationViewModel(
         }
     }
 
+    private suspend fun actionStartListeningLocation() {
+        val started = fakeLocationStateUseCase.startListeningLocation()
+        if (!started) {
+            _singleEvents.emit(SingleEvent.RequestLocationPermission)
+        }
+    }
+
     private suspend fun setSpecificLocation(action: Action.SetSpecificLocationAction) {
         specificLocationInputFlow.emit(action)
     }
 
     sealed class SingleEvent {
         data class LocationUpdatedEvent(val mode: LocationMode, val location: Location?) : SingleEvent()
+        object RequestLocationPermission: SingleEvent()
         data class ErrorEvent(val error: String) : SingleEvent()
     }
 
     sealed class Action {
-        object EnterScreen : Action()
-        object LeaveScreen : Action()
+        object StartListeningLocation : Action()
+        object StopListeningLocation : Action()
         object UseRealLocationAction : Action()
         object UseRandomLocationAction : Action()
         data class SetSpecificLocationAction(
-- 
cgit v1.2.1