From 360f01069cead50ee53425cbe297a5e4da861910 Mon Sep 17 00:00:00 2001 From: jacquarg Date: Thu, 27 Feb 2025 14:18:54 +0100 Subject: [PATCH 1/4] fix: Sentry IllegalArgumentException: Navigation action/destination cannot be found --- .../extensions/NavControllerExtensions.kt | 34 +++++++++++++++++++ .../features/dashboard/DashboardFragment.kt | 3 +- .../features/trackers/TrackersFragment.kt | 3 +- .../trackers/TrackersPeriodFragment.kt | 3 +- 4 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/foundation/e/advancedprivacy/common/extensions/NavControllerExtensions.kt diff --git a/app/src/main/java/foundation/e/advancedprivacy/common/extensions/NavControllerExtensions.kt b/app/src/main/java/foundation/e/advancedprivacy/common/extensions/NavControllerExtensions.kt new file mode 100644 index 00000000..4af519db --- /dev/null +++ b/app/src/main/java/foundation/e/advancedprivacy/common/extensions/NavControllerExtensions.kt @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2025 MURENA SAS + * + * 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 . + */ + +package foundation.e.advancedprivacy.common.extensions + +import android.os.Bundle +import androidx.navigation.NavController +import androidx.navigation.NavDirections + +fun NavController.safeNavigate(direction: NavDirections) { + currentDestination?.getAction(direction.actionId)?.run { + navigate(direction.actionId) + } +} + +fun NavController.safeNavigateWithArgs(direction: NavDirections, bundle: Bundle?) { + currentDestination?.getAction(direction.actionId)?.run { + navigate(direction.actionId, bundle) + } +} diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt index 099d8fbb..dec15104 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt @@ -32,6 +32,7 @@ import com.google.android.material.tabs.TabLayoutMediator import foundation.e.advancedprivacy.R import foundation.e.advancedprivacy.common.BigNumberFormatter import foundation.e.advancedprivacy.common.NavToolbarFragment +import foundation.e.advancedprivacy.common.extensions.safeNavigate import foundation.e.advancedprivacy.databinding.FragmentDashboardBinding import foundation.e.advancedprivacy.domain.entities.FeatureMode import foundation.e.advancedprivacy.domain.entities.FeatureState @@ -171,7 +172,7 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) { viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.navigate.collect(findNavController()::navigate) + viewModel.navigate.collect(findNavController()::safeNavigate) } } diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt index 5f55b1a8..ba65d818 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt @@ -39,6 +39,7 @@ import com.google.android.material.tabs.TabLayoutMediator import foundation.e.advancedprivacy.R import foundation.e.advancedprivacy.common.NavToolbarFragment import foundation.e.advancedprivacy.common.extensions.findViewHolderForAdapterPosition +import foundation.e.advancedprivacy.common.extensions.safeNavigate import foundation.e.advancedprivacy.common.extensions.updatePagerHeightForChild import foundation.e.advancedprivacy.databinding.FragmentTrackersBinding import kotlinx.coroutines.flow.SharedFlow @@ -100,7 +101,7 @@ class TrackersFragment : NavToolbarFragment(R.layout.fragment_trackers) { lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.navigate.collect(findNavController()::navigate) + viewModel.navigate.collect(findNavController()::safeNavigate) } } } diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodFragment.kt index 91f53394..771c31d6 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodFragment.kt @@ -33,6 +33,7 @@ import androidx.viewpager2.widget.ViewPager2 import com.google.android.material.tabs.TabLayoutMediator import foundation.e.advancedprivacy.R import foundation.e.advancedprivacy.common.extensions.findViewHolderForAdapterPosition +import foundation.e.advancedprivacy.common.extensions.safeNavigate import foundation.e.advancedprivacy.common.extensions.updatePagerHeightForChild import foundation.e.advancedprivacy.databinding.TrackersPeriodFragmentBinding import foundation.e.advancedprivacy.features.trackers.TrackersPeriodViewModel.SingleEvent @@ -147,7 +148,7 @@ class TrackersPeriodFragment : Fragment(R.layout.trackers_period_fragment) { lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.navigate.collect(findNavController()::navigate) + viewModel.navigate.collect(findNavController()::safeNavigate) } } -- GitLab From d08cc61ad54fd99ab892e499bdc85d93e2e3b23d Mon Sep 17 00:00:00 2001 From: jacquarg Date: Thu, 27 Feb 2025 14:50:48 +0100 Subject: [PATCH 2/4] fix: Sentry, don't send error log for connectivity issue while updateing tracker list. --- .../domain/usecases/UpdateTrackerListUseCase.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt index 2645e60d..c9572a6d 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt @@ -20,6 +20,11 @@ package foundation.e.advancedprivacy.trackers.domain.usecases import foundation.e.advancedprivacy.data.repositories.ETrackersApi import foundation.e.advancedprivacy.data.repositories.RemoteTrackersListRepository import foundation.e.advancedprivacy.trackers.data.TrackersRepository +import java.net.ConnectException +import java.net.SocketException +import java.net.SocketTimeoutException +import java.net.UnknownHostException +import javax.net.ssl.SSLHandshakeException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import timber.log.Timber @@ -39,6 +44,16 @@ class UpdateTrackerListUseCase( try { remoteTrackersListRepository.saveData(trackersRepository.eTrackerFile, api.trackers()) trackersRepository.initTrackersFile() + } catch (e: UnknownHostException) { + Timber.d(e, "While updating trackers, is internet reachable ?") + } catch (e: SocketTimeoutException) { + Timber.d(e, "While updating trackers, is internet reachable ?") + } catch (e: SSLHandshakeException) { + Timber.d(e, "While updating trackers, is internet reachable ?") + } catch (e: SocketException) { + Timber.d(e, "While updating trackers, is internet reachable ?") + } catch (e: ConnectException) { + Timber.d(e, "While updating trackers, is internet reachable ?") } catch (e: Exception) { Timber.e(e, "While updating trackers") } -- GitLab From 179c5802f61154e3a01e381bc7b5ea26fb86d848 Mon Sep 17 00:00:00 2001 From: jacquarg Date: Fri, 28 Feb 2025 11:30:43 +0100 Subject: [PATCH 3/4] fix: Sentry issue, handle locked Legacy VPN while activating ipScrambling --- .../permissions/IPermissionsPrivacyModule.kt | 3 ++ .../java/android/internal/net/VpnConfig.java | 26 +++++++++++++++ .../PermissionsPrivacyModuleImpl.kt | 5 +++ .../PermissionsPrivacyModuleImpl.kt | 4 +++ .../service/VpnSupervisorUseCaseEos.kt | 33 ++++++++++++++++--- 5 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 permissionseos/libs/hidden-apis-stub/src/main/java/android/internal/net/VpnConfig.java diff --git a/core/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/IPermissionsPrivacyModule.kt b/core/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/IPermissionsPrivacyModule.kt index 599cb376..731d3cc4 100644 --- a/core/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/IPermissionsPrivacyModule.kt +++ b/core/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/IPermissionsPrivacyModule.kt @@ -122,6 +122,9 @@ interface IPermissionsPrivacyModule { */ fun getAlwaysOnVpnPackage(): String? + /** Returns the dummy package name used by Android to highlight legacy VPN */ + fun getLegacyVpnDummyPackage(): String + /** * Allows users to block notifications sent through this channel, if this channel belongs to * a package that is signed with the system signature. diff --git a/permissionseos/libs/hidden-apis-stub/src/main/java/android/internal/net/VpnConfig.java b/permissionseos/libs/hidden-apis-stub/src/main/java/android/internal/net/VpnConfig.java new file mode 100644 index 00000000..134b1e90 --- /dev/null +++ b/permissionseos/libs/hidden-apis-stub/src/main/java/android/internal/net/VpnConfig.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2025 MURENA SAS + * + * 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 . + */ + +package android.internal.net; + +// Stub based on: +// https://gitlab.e.foundation/e/os/android_frameworks_base/-/blob/[VERSION]/core/java/com/android/internal/net/VpnConfig.java +public class VpnConfig { + + // Availability checked from SDK29 to SDK 35 + public static final String LEGACY_VPN = "[Legacy VPN]"; +} diff --git a/permissionseos/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModuleImpl.kt b/permissionseos/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModuleImpl.kt index 4c96a02a..06ea40b3 100644 --- a/permissionseos/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModuleImpl.kt +++ b/permissionseos/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModuleImpl.kt @@ -28,6 +28,7 @@ import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.content.pm.UserInfo import android.graphics.drawable.Drawable +import android.internal.net.VpnConfig import android.net.IConnectivityManager import android.net.VpnManager import android.net.VpnManager.TYPE_VPN_SERVICE @@ -203,6 +204,10 @@ class PermissionsPrivacyModuleImpl(context: Context) : PermissionsPrivacyModuleB } } + override fun getLegacyVpnDummyPackage(): String { + return VpnConfig.LEGACY_VPN + } + @TargetApi(29) private fun getAlwaysOnVpnPackageSDK29(): String? { val service: IConnectivityManager = IConnectivityManager.Stub.asInterface( diff --git a/permissionsstandalone/src/main/java/foundation/e/advancedprivacy/permissions/externalinterfaces/PermissionsPrivacyModuleImpl.kt b/permissionsstandalone/src/main/java/foundation/e/advancedprivacy/permissions/externalinterfaces/PermissionsPrivacyModuleImpl.kt index 142e34ea..7ae8e813 100644 --- a/permissionsstandalone/src/main/java/foundation/e/advancedprivacy/permissions/externalinterfaces/PermissionsPrivacyModuleImpl.kt +++ b/permissionsstandalone/src/main/java/foundation/e/advancedprivacy/permissions/externalinterfaces/PermissionsPrivacyModuleImpl.kt @@ -56,5 +56,9 @@ class PermissionsPrivacyModuleImpl(context: Context) : PermissionsPrivacyModuleB return null } + override fun getLegacyVpnDummyPackage(): String { + return "[Legacy VPN]" + } + override fun setBlockable(notificationChannel: NotificationChannel) {} } diff --git a/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/VpnSupervisorUseCaseEos.kt b/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/VpnSupervisorUseCaseEos.kt index afbf90fa..510c0499 100644 --- a/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/VpnSupervisorUseCaseEos.kt +++ b/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/VpnSupervisorUseCaseEos.kt @@ -22,6 +22,7 @@ import foundation.e.advancedprivacy.domain.entities.FeatureState import foundation.e.advancedprivacy.domain.entities.MainFeatures import foundation.e.advancedprivacy.domain.entities.MainFeatures.IpScrambling import foundation.e.advancedprivacy.domain.entities.MainFeatures.TrackersControl +import foundation.e.advancedprivacy.domain.entities.ProfileType import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository import foundation.e.advancedprivacy.domain.usecases.VpnSupervisorUseCase import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule @@ -32,6 +33,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch +import timber.log.Timber class VpnSupervisorUseCaseEos( private val localStateRepository: LocalStateRepository, @@ -82,12 +84,35 @@ class VpnSupervisorUseCaseEos( permissionsPrivacyModule.setVpnPackageAuthorization(appDesc.packageName) val alwaysOnVpnPackage = permissionsPrivacyModule.getAlwaysOnVpnPackage() if (alwaysOnVpnPackage != null) { - localStateRepository.emitOtherVpnRunning( - permissionsPrivacyModule.getApplicationDescription( + val vpnApp = if (alwaysOnVpnPackage == permissionsPrivacyModule.getLegacyVpnDummyPackage()) { + ApplicationDescription( packageName = alwaysOnVpnPackage, - withIcon = false + uid = -1, + profileId = -1, + profileType = ProfileType.MAIN, + label = "PTP, L2TP/IPSec or IPSec", + icon = null ) - ) + } else { + try { + permissionsPrivacyModule.getApplicationDescription( + packageName = alwaysOnVpnPackage, + withIcon = false + ) + } catch (e: Exception) { + Timber.e(e, "Can't getApplicationDescription for package: $alwaysOnVpnPackage") + ApplicationDescription( + packageName = alwaysOnVpnPackage, + uid = -1, + profileId = -1, + profileType = ProfileType.MAIN, + label = null, + icon = null + ) + } + } + + localStateRepository.emitOtherVpnRunning(vpnApp) localStateRepository.toggleIpScrambling(enabled = false) return } -- GitLab From 72dc71731512c21d1d46796bf67e5798da7a0b73 Mon Sep 17 00:00:00 2001 From: jacquarg Date: Mon, 3 Mar 2025 12:35:17 +0100 Subject: [PATCH 4/4] fix: hide internet unreachablerror, MR review fixes. --- .../domain/usecases/UpdateTrackerListUseCase.kt | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt index c9572a6d..711e7a03 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt @@ -20,11 +20,7 @@ package foundation.e.advancedprivacy.trackers.domain.usecases import foundation.e.advancedprivacy.data.repositories.ETrackersApi import foundation.e.advancedprivacy.data.repositories.RemoteTrackersListRepository import foundation.e.advancedprivacy.trackers.data.TrackersRepository -import java.net.ConnectException -import java.net.SocketException -import java.net.SocketTimeoutException -import java.net.UnknownHostException -import javax.net.ssl.SSLHandshakeException +import java.io.IOException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import timber.log.Timber @@ -44,15 +40,7 @@ class UpdateTrackerListUseCase( try { remoteTrackersListRepository.saveData(trackersRepository.eTrackerFile, api.trackers()) trackersRepository.initTrackersFile() - } catch (e: UnknownHostException) { - Timber.d(e, "While updating trackers, is internet reachable ?") - } catch (e: SocketTimeoutException) { - Timber.d(e, "While updating trackers, is internet reachable ?") - } catch (e: SSLHandshakeException) { - Timber.d(e, "While updating trackers, is internet reachable ?") - } catch (e: SocketException) { - Timber.d(e, "While updating trackers, is internet reachable ?") - } catch (e: ConnectException) { + } catch (e: IOException) { Timber.d(e, "While updating trackers, is internet reachable ?") } catch (e: Exception) { Timber.e(e, "While updating trackers") -- GitLab