diff options
11 files changed, 71 insertions, 34 deletions
@@ -105,6 +105,9 @@ PrivacyCentral needs to be installed as system app and whitelisting in order to ```bash adb push privapp-permissions-foundation.e.privacycentralapp.xml /system/etc/permissions/ ``` + +1. Allow the fake location service to run in background. Add <allow-in-power-save package="foundation.e.privacycetrallapp.e" /> in the file /system/etc/permissions/platform.xml . + 1. Reboot the device ```shell adb reboot diff --git a/app/build.gradle b/app/build.gradle index 5de3ca4..4c5b353 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -45,10 +45,10 @@ android { applicationIdSuffix '.e' dimension 'os' } - google { - applicationIdSuffix '.google' - dimension 'os' - } +// google { +// applicationIdSuffix '.google' +// dimension 'os' +// } } buildTypes { @@ -102,7 +102,7 @@ dependencies { implementation 'foundation.e:privacymodule.api:0.4.1' - implementation 'foundation.e:privacymodule.e-29:0.3.2' + implementation 'foundation.e:privacymodule.e-29:0.4.1' implementation 'foundation.e:privacymodule.tor:0.1.1' implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' diff --git a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt index 5bd7c08..27d6ac4 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt @@ -80,7 +80,7 @@ class DependencyContainer constructor(val app: Application) { GetQuickPrivacyStateUseCase(localStateRepository) } private val ipScramblingStateUseCase by lazy { - IpScramblingStateUseCase(ipScramblerModule, localStateRepository, GlobalScope) + IpScramblingStateUseCase(ipScramblerModule, permissionsModule, appDesc, localStateRepository, GlobalScope) } private val appListUseCase = AppListUseCase(permissionsModule, GlobalScope) diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/AppListUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/AppListUseCase.kt index 4d0ece2..57168c5 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/AppListUseCase.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/AppListUseCase.kt @@ -31,12 +31,44 @@ class AppListUseCase( ) { private val _appsUsingInternet = MutableStateFlow<List<ApplicationDescription>>(emptyList()) + private val _installedAppsUsingInternet = MutableStateFlow<List<ApplicationDescription>>(emptyList()) init { corouteineScope.launch { _appsUsingInternet.value = getAppsUsingInternetList() } } + fun getInstalledAppsUsingInternet(): Flow<List<ApplicationDescription>> { + corouteineScope.launch { + _installedAppsUsingInternet.value = getInstalledAppsUsingInternetList() + } + return _installedAppsUsingInternet + } + + private fun getInstalledAppsUsingInternetList(): List<ApplicationDescription> { + return permissionsModule.getInstalledApplications() + .filter { + permissionsModule.getPermissions(it.packageName) + .contains(Manifest.permission.INTERNET) + }.map { + it.icon = permissionsModule.getApplicationIcon(it.packageName) + it + }.sortedWith(object : Comparator<ApplicationDescription> { + override fun compare( + p0: ApplicationDescription?, + p1: ApplicationDescription? + ): Int { + return if (p0?.icon != null && p1?.icon != null) { + p0.label.toString().compareTo(p1.label.toString()) + } else if (p0?.icon == null) { + 1 + } else { + -1 + } + } + }) + } + fun getAppsUsingInternet(): Flow<List<ApplicationDescription>> { corouteineScope.launch { _appsUsingInternet.value = getAppsUsingInternetList() @@ -45,7 +77,7 @@ class AppListUseCase( } private fun getAppsUsingInternetList(): List<ApplicationDescription> { - return permissionsModule.getInstalledApplications() + return permissionsModule.getAllApplications() .filter { permissionsModule.getPermissions(it.packageName) .contains(Manifest.permission.INTERNET) 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 7f288e0..5850dc4 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 @@ -22,6 +22,7 @@ import android.content.Context import android.location.Location import android.location.LocationListener import android.location.LocationManager +import android.os.Bundle import android.util.Log import foundation.e.privacycentralapp.data.repositories.LocalStateRepository import foundation.e.privacycentralapp.domain.entities.LocationMode @@ -125,8 +126,6 @@ class FakeLocationStateUseCase( applySettings(true, null) } - private var listener: LocationListener? = null - val currentLocation = MutableStateFlow<Location?>(null) private var localListener = object : LocationListener { @@ -137,6 +136,9 @@ class FakeLocationStateUseCase( currentLocation.value = location } + // Deprecated since API 29, never called. + override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {} + override fun onProviderEnabled(provider: String?) { Log.e("DebugLoc", "ProvuderEnabled: $provider") reset(provider) diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt index f8badcf..3caab63 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt @@ -17,11 +17,12 @@ package foundation.e.privacycentralapp.domain.usecases -import android.content.Intent import android.util.Log import foundation.e.privacycentralapp.data.repositories.LocalStateRepository import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode import foundation.e.privacymodules.ipscramblermodule.IIpScramblerModule +import foundation.e.privacymodules.permissions.IPermissionsPrivacyModule +import foundation.e.privacymodules.permissions.data.ApplicationDescription import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.SharingStarted @@ -33,6 +34,8 @@ import kotlinx.coroutines.launch class IpScramblingStateUseCase( private val ipScramblerModule: IIpScramblerModule, + private val permissionsPrivacyModule: IPermissionsPrivacyModule, + private val appDesc: ApplicationDescription, private val localStateRepository: LocalStateRepository, coroutineScope: CoroutineScope ) { @@ -70,23 +73,22 @@ class IpScramblingStateUseCase( } } - fun toggle(hideIp: Boolean): Intent? { - if (!localStateRepository.isQuickPrivacyEnabled) return null + fun toggle(hideIp: Boolean) { + if (!localStateRepository.isQuickPrivacyEnabled) return localStateRepository.isIpScramblingEnabled = hideIp - return applySettings(true, hideIp) + applySettings(true, hideIp) } - private fun applySettings(isQuickPrivacyEnabled: Boolean, isIpScramblingEnabled: Boolean): Intent? { + private fun applySettings(isQuickPrivacyEnabled: Boolean, isIpScramblingEnabled: Boolean) { when { isQuickPrivacyEnabled && isIpScramblingEnabled -> when (internetPrivacyMode.value) { InternetPrivacyMode.REAL_IP, InternetPrivacyMode.REAL_IP_LOADING -> { val intent = ipScramblerModule.prepareAndroidVpn() if (intent != null) { - return intent - } else { - ipScramblerModule.start() + permissionsPrivacyModule.setVpnPackageAuthorization(appDesc.packageName) } + ipScramblerModule.start() } else -> { Log.d("testQPFlow", "Not starting tor, already in started state") @@ -100,7 +102,6 @@ class IpScramblingStateUseCase( } } } - return null } private fun map(status: IIpScramblerModule.Status): InternetPrivacyMode { diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt index e0eb12c..a9482db 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt @@ -137,7 +137,7 @@ class InternetPrivacyFeature( action is Action.LoadInternetModeAction -> merge( getQuickPrivacyStateUseCase.quickPrivacyEnabledFlow.map { Effect.QuickPrivacyUpdatedEffect(it) }, ipScramblingStateUseCase.internetPrivacyMode.map { Effect.ModeUpdatedEffect(it) }.shareIn(scope = coroutineScope, started = SharingStarted.Lazily, replay = 0), - flowOf(Effect.ModeUpdatedEffect(InternetPrivacyMode.REAL_IP)), + // flowOf(Effect.ModeUpdatedEffect(InternetPrivacyMode.REAL_IP)), appListUseCase.getAppsUsingInternet().map { apps -> if (ipScramblerModule.appList.isEmpty()) { ipScramblerModule.appList = @@ -189,11 +189,8 @@ class InternetPrivacyFeature( InternetPrivacyMode.REAL_IP_LOADING ) -> { if (getQuickPrivacyStateUseCase.isQuickPrivacyEnabled) { - ipScramblingStateUseCase.toggle(hideIp = true)?.let { - flowOf(Effect.ShowAndroidVpnDisclaimerEffect(it)) - } ?: run { - flowOf(Effect.ModeUpdatedEffect(InternetPrivacyMode.HIDE_IP_LOADING)) - } + ipScramblingStateUseCase.toggle(hideIp = true) + flowOf(Effect.ModeUpdatedEffect(InternetPrivacyMode.HIDE_IP_LOADING)) } else { flowOf(Effect.QuickPrivacyDisabledWarningEffect) } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt index e7a9480..135b563 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt @@ -101,13 +101,15 @@ class InternetPrivacyFragment : } } - binding.radioUseRealIp.container.setOnClickListener { + binding.radioUseRealIp.radiobutton.setOnClickListener { viewModel.submitAction(InternetPrivacyFeature.Action.UseRealIPAction) } - binding.radioUseHiddenIp.container.setOnClickListener { + binding.radioUseHiddenIp.radiobutton.setOnClickListener { viewModel.submitAction(InternetPrivacyFeature.Action.UseHiddenIPAction) } + + binding.executePendingBindings() } override fun getTitle(): String = getString(R.string.ipscrambling_title) @@ -144,7 +146,7 @@ class InternetPrivacyFragment : } setOnItemSelectedListener(object : AdapterView.OnItemSelectedListener { - override fun onItemSelected(parentView: AdapterView<*>, selectedItemView: View, position: Int, id: Long) { + override fun onItemSelected(parentView: AdapterView<*>, selectedItemView: View?, position: Int, id: Long) { viewModel.submitAction(InternetPrivacyFeature.Action.SelectLocationAction(position)) } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFeature.kt index 5d20e7c..81edea8 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFeature.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFeature.kt @@ -152,7 +152,7 @@ class TrackersFeature( ) ) }, - appListUseCase.getAppsUsingInternet().map { apps -> + appListUseCase.getInstalledAppsUsingInternet().map { apps -> Effect.AvailableAppsListEffect(apps) } ) diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt index 1c3144d..f0b0aef 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt @@ -75,9 +75,9 @@ class AppTrackersFragment : } } lifecycleScope.launchWhenStarted { - viewModel.submitAction( - Action.InitAction(requireArguments().getString(PARAM_PACKAGE_NAME)) - ) + requireArguments().getString(PARAM_PACKAGE_NAME)?.let { + viewModel.submitAction(Action.InitAction(it)) + } } } @@ -86,7 +86,7 @@ class AppTrackersFragment : .show() } - override fun getTitle(): String = requireArguments().getString(PARAM_LABEL) + override fun getTitle(): String = requireArguments().getString(PARAM_LABEL) ?: "" override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/build.gradle b/build.gradle index e1df856..842ad40 100644 --- a/build.gradle +++ b/build.gradle @@ -4,9 +4,9 @@ import foundation.e.privacycentral.buildsrc.ReleaseType // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext.buildConfig = [ - 'compileSdk': 30, + 'compileSdk': 29, 'minSdk' : 26, - 'targetSdk' : 30, + 'targetSdk' : 29, 'version' : [ 'major': 1, 'minor': 0, |