diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt index d556fb829201288fcb745ae453f6bc8cb84d8e4d..54c2f41509a6404770d42a4d3aad856622cd4570 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt @@ -3,8 +3,10 @@ package de.rki.coronawarnapp.storage import android.content.Context import androidx.core.app.NotificationManagerCompat import androidx.lifecycle.MutableLiveData +import de.rki.coronawarnapp.util.BackgroundPrioritization import de.rki.coronawarnapp.util.ConnectivityHelper -import de.rki.coronawarnapp.util.PowerManagementHelper +import javax.inject.Inject +import javax.inject.Singleton /** * The Settings Repository maps all setting states from different sources to MutableLiveData. @@ -14,9 +16,11 @@ import de.rki.coronawarnapp.util.PowerManagementHelper * * @see LocalData */ -object SettingsRepository { - - private val TAG: String? = SettingsRepository::class.simpleName +@Singleton +class SettingsRepository @Inject constructor( + private val context: Context, + private val backgroundPrioritization: BackgroundPrioritization +) { // public mutable live data val isNotificationsEnabled = MutableLiveData(true) @@ -35,7 +39,7 @@ object SettingsRepository { * * @see LocalData */ - fun refreshNotificationsEnabled(context: Context) { + fun refreshNotificationsEnabled() { isNotificationsEnabled.value = NotificationManagerCompat.from(context).areNotificationsEnabled() } @@ -131,8 +135,7 @@ object SettingsRepository { /** * Refresh the current background priority state. */ - fun refreshBackgroundPriorityEnabled(context: Context) { - isBackgroundPriorityEnabled.value = - PowerManagementHelper.isIgnoringBatteryOptimizations(context) + fun refreshBackgroundPriorityEnabled() { + isBackgroundPriorityEnabled.value = backgroundPrioritization.isBackgroundActivityPrioritized } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/timer/TimerHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/timer/TimerHelper.kt index 6212810fa0b875c2866ac84c76d96e013cdea90e..ac56b4c5df61a79b2d19a485ec7e876674aceb14 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/timer/TimerHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/timer/TimerHelper.kt @@ -4,6 +4,7 @@ import de.rki.coronawarnapp.BuildConfig import de.rki.coronawarnapp.risk.TimeVariables import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.SettingsRepository +import de.rki.coronawarnapp.util.di.AppInjector import org.joda.time.DateTime import org.joda.time.DateTimeZone import org.joda.time.Instant @@ -48,6 +49,10 @@ object TimerHelper { */ private const val INITIAL_TIMER_DELAY = 0L + private val settingsRepository by lazy { + AppInjector.component.settingsRepository + } + /** * Get cooldown time left between last time update button was triggered and current time * @@ -103,7 +108,7 @@ object TimerHelper { } } if (!isManualKeyRetrievalOnTimer.get()) { - SettingsRepository.updateManualKeyRetrievalEnabled(true) + settingsRepository.updateManualKeyRetrievalEnabled(true) } } @@ -120,8 +125,8 @@ object TimerHelper { private fun onManualKeyRetrievalTimerTick() { val timeDifference = getManualKeyRetrievalTimeLeft() val result = timeDifference <= 0 - SettingsRepository.updateManualKeyRetrievalEnabled(result) - SettingsRepository.updateManualKeyRetrievalTime(timeDifference) + settingsRepository.updateManualKeyRetrievalEnabled(result) + settingsRepository.updateManualKeyRetrievalTime(timeDifference) if (result) stopManualKeyRetrievalTimer() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt index 9fbc8cd81d80605c94514cbfb48372ded0b9f52c..bfd78ff91cf4667394687a62dc4df61cb5bdd338 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt @@ -16,13 +16,14 @@ import de.rki.coronawarnapp.http.playbook.BackgroundNoise import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel +import de.rki.coronawarnapp.util.BackgroundPrioritization import de.rki.coronawarnapp.util.ConnectivityHelper import de.rki.coronawarnapp.util.DialogHelper -import de.rki.coronawarnapp.util.ExternalActionHelper -import de.rki.coronawarnapp.util.PowerManagementHelper +import de.rki.coronawarnapp.util.device.PowerManagement import de.rki.coronawarnapp.worker.BackgroundWorkScheduler import kotlinx.coroutines.launch import timber.log.Timber +import javax.inject.Inject /** * This activity holds all the fragments (except onboarding) and also registers a listener for @@ -46,6 +47,12 @@ class MainActivity : AppCompatActivity() { private lateinit var settingsViewModel: SettingsViewModel + @Inject + lateinit var backgroundPrioritization: BackgroundPrioritization + + @Inject + lateinit var powerManagement: PowerManagement + /** * Register connection callback. */ @@ -123,7 +130,7 @@ class MainActivity : AppCompatActivity() { R.string.onboarding_energy_optimized_dialog_button_negative, false, { // go to battery optimization - ExternalActionHelper.disableBatteryOptimizations(this) + powerManagement.disableBatteryOptimizations() }, { // keep battery optimization enabled showManualCheckingRequiredDialog() @@ -132,7 +139,7 @@ class MainActivity : AppCompatActivity() { } private fun checkForEnergyOptimizedEnabled() { - if (!PowerManagementHelper.isIgnoringBatteryOptimizations(this)) { + if (!backgroundPrioritization.isBackgroundActivityPrioritized) { showEnergyOptimizedEnabledForBackground() } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsBackgroundPriorityFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsBackgroundPriorityFragment.kt index b5d465e9fbd0954d9ac49bb405d88c1ccf4239a7..3b3223f2839fd0a943750de601af4655bda18f02 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsBackgroundPriorityFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsBackgroundPriorityFragment.kt @@ -11,7 +11,6 @@ import de.rki.coronawarnapp.databinding.FragmentSettingsBackgroundPriorityBindin import de.rki.coronawarnapp.ui.main.MainActivity import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel -import de.rki.coronawarnapp.util.ExternalActionHelper /** * This is the setting background priority page. Here the user sees the background priority setting status. @@ -54,7 +53,7 @@ class SettingsBackgroundPriorityFragment : Fragment() { super.onResume() binding.settingsBackgroundPriorityContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) // refresh required data - settingsViewModel.refreshBackgroundPriorityEnabled(requireContext()) + settingsViewModel.refreshBackgroundPriorityEnabled() } private fun setButtonOnClickListener() { @@ -66,14 +65,18 @@ class SettingsBackgroundPriorityFragment : Fragment() { it.setOnClickListener { val isPriorityEnabled = settingsViewModel.isBackgroundPriorityEnabled.value == true - if (!isPriorityEnabled) - ExternalActionHelper.disableBatteryOptimizations(requireContext()) + if (!isPriorityEnabled) { + val activity = requireActivity() as MainActivity + activity.powerManagement.disableBatteryOptimizations() + } } } // explanatory card binding.settingsTracingStatusConnection.tracingStatusCardButton.setOnClickListener { - ExternalActionHelper.toBatteryOptimizationSettings(requireContext()) + (requireActivity() as MainActivity).apply { + startActivity(powerManagement.toBatteryOptimizationSettingsIntent) + } } // back navigation diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt index 258db57c53ac5fe4b0c60817f9f36ad815783419..33bc8f9b3217b510e45f33357252ad4a9695926b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt @@ -57,10 +57,10 @@ class SettingsFragment : Fragment() { super.onResume() // refresh required data tracingViewModel.refreshIsTracingEnabled() - settingsViewModel.refreshNotificationsEnabled(requireContext()) + settingsViewModel.refreshNotificationsEnabled() settingsViewModel.refreshNotificationsRiskEnabled() settingsViewModel.refreshNotificationsTestEnabled() - settingsViewModel.refreshBackgroundPriorityEnabled(requireContext()) + settingsViewModel.refreshBackgroundPriorityEnabled() binding.settingsContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsNotificationFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsNotificationFragment.kt index 48445dcc8c8f20b2e7a4045733b53bf9bcbe29ca..3acd7e6d9fa92a9c2a6fea280d8dde90a617d46e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsNotificationFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsNotificationFragment.kt @@ -56,7 +56,7 @@ class SettingsNotificationFragment : Fragment() { super.onResume() binding.settingsNotificationsContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) // refresh required data - settingsViewModel.refreshNotificationsEnabled(requireContext()) + settingsViewModel.refreshNotificationsEnabled() settingsViewModel.refreshNotificationsRiskEnabled() settingsViewModel.refreshNotificationsTestEnabled() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt index 1dc1cbae485776d665b2ee03d07c3d091e90da01..afc6c1abf4581ecf6200b17b8d7fc3318662bbf1 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt @@ -22,7 +22,6 @@ import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel import de.rki.coronawarnapp.util.DialogHelper import de.rki.coronawarnapp.util.ExternalActionHelper import de.rki.coronawarnapp.util.IGNORE_CHANGE_TAG -import de.rki.coronawarnapp.util.PowerManagementHelper import de.rki.coronawarnapp.util.formatter.formatTracingSwitchEnabled import de.rki.coronawarnapp.worker.BackgroundWorkScheduler import kotlinx.coroutines.launch @@ -155,7 +154,8 @@ class SettingsTracingFragment : Fragment(), // activated during onboarding showConsentDialog() // check if background processing is switched off, if it is, show the manual calculation dialog explanation before turning on. - if (!PowerManagementHelper.isIgnoringBatteryOptimizations(requireActivity())) { + val activity = requireActivity() as MainActivity + if (!activity.backgroundPrioritization.isBackgroundActivityPrioritized) { showManualCheckingRequiredDialog() } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt index 486954f1ac74cc6912e24ec6619ba8cf616092c9..fa6bde7ffd0c4200c7799a8d23b45f2dd0321fd8 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt @@ -1,9 +1,9 @@ package de.rki.coronawarnapp.ui.viewmodel -import android.content.Context import androidx.lifecycle.LiveData import androidx.lifecycle.ViewModel import de.rki.coronawarnapp.storage.SettingsRepository +import de.rki.coronawarnapp.util.di.AppInjector /** * ViewModel for everything settings related. @@ -12,23 +12,24 @@ import de.rki.coronawarnapp.storage.SettingsRepository */ class SettingsViewModel : ViewModel() { - val isNotificationsEnabled: LiveData<Boolean> = SettingsRepository.isNotificationsEnabled + private val settingsRepository by lazy { + AppInjector.component.settingsRepository + } + + val isNotificationsEnabled: LiveData<Boolean> = settingsRepository.isNotificationsEnabled val isNotificationsRiskEnabled: LiveData<Boolean> = - SettingsRepository.isNotificationsRiskEnabled + settingsRepository.isNotificationsRiskEnabled val isNotificationsTestEnabled: LiveData<Boolean> = - SettingsRepository.isNotificationsTestEnabled - val isConnectionEnabled: LiveData<Boolean> = - SettingsRepository.isConnectionEnabled - val isBluetoothEnabled: LiveData<Boolean> = - SettingsRepository.isBluetoothEnabled - val isLocationEnabled: LiveData<Boolean> = - SettingsRepository.isLocationEnabled + settingsRepository.isNotificationsTestEnabled + val isConnectionEnabled: LiveData<Boolean> = settingsRepository.isConnectionEnabled + val isBluetoothEnabled: LiveData<Boolean> = settingsRepository.isBluetoothEnabled + val isLocationEnabled: LiveData<Boolean> = settingsRepository.isLocationEnabled // Will impact UI if background activity is not permitted, persistent storing is not necessary - val isBackgroundJobEnabled: LiveData<Boolean> = SettingsRepository.isBackgroundJobEnabled + val isBackgroundJobEnabled: LiveData<Boolean> = settingsRepository.isBackgroundJobEnabled val isBackgroundPriorityEnabled: LiveData<Boolean> = - SettingsRepository.isBackgroundPriorityEnabled + settingsRepository.isBackgroundPriorityEnabled /** * Is manual key retrieval enabled @@ -37,14 +38,14 @@ class SettingsViewModel : ViewModel() { * @see SettingsRepository.isManualKeyRetrievalEnabled */ val isManualKeyRetrievalEnabled: LiveData<Boolean> = - SettingsRepository.isManualKeyRetrievalEnabled + settingsRepository.isManualKeyRetrievalEnabled /** * Manual update button timer value * * @see SettingsRepository.manualKeyRetrievalTime */ - val manualKeyRetrievalTime: LiveData<Long> = SettingsRepository.manualKeyRetrievalTime + val manualKeyRetrievalTime: LiveData<Long> = settingsRepository.manualKeyRetrievalTime /** * Refresher and toggles for settings @@ -56,32 +57,32 @@ class SettingsViewModel : ViewModel() { * - Connectivity * - Background activity * - * @see SettingsRepository + * @see settingsRepository */ - fun refreshNotificationsEnabled(context: Context) { - SettingsRepository.refreshNotificationsEnabled(context) + fun refreshNotificationsEnabled() { + settingsRepository.refreshNotificationsEnabled() } /** * Refresh & toggle risk notifications */ fun refreshNotificationsRiskEnabled() { - SettingsRepository.refreshNotificationsRiskEnabled() + settingsRepository.refreshNotificationsRiskEnabled() } fun toggleNotificationsRiskEnabled() { - SettingsRepository.toggleNotificationsRiskEnabled() + settingsRepository.toggleNotificationsRiskEnabled() } /** * Refresh & toggle test notifications */ fun refreshNotificationsTestEnabled() { - SettingsRepository.refreshNotificationsTestEnabled() + settingsRepository.refreshNotificationsTestEnabled() } fun toggleNotificationsTestEnabled() { - SettingsRepository.toggleNotificationsTestEnabled() + settingsRepository.toggleNotificationsTestEnabled() } /** @@ -90,7 +91,7 @@ class SettingsViewModel : ViewModel() { * @param value */ fun updateConnectionEnabled(value: Boolean) { - SettingsRepository.updateConnectionEnabled(value) + settingsRepository.updateConnectionEnabled(value) } /** @@ -99,7 +100,7 @@ class SettingsViewModel : ViewModel() { * @param value */ fun updateBluetoothEnabled(value: Boolean) { - SettingsRepository.updateBluetoothEnabled(value) + settingsRepository.updateBluetoothEnabled(value) } /** @@ -108,7 +109,7 @@ class SettingsViewModel : ViewModel() { * @param value */ fun updateLocationEnabled(value: Boolean) { - SettingsRepository.updateLocationEnabled(value) + settingsRepository.updateLocationEnabled(value) } /** @@ -117,7 +118,7 @@ class SettingsViewModel : ViewModel() { * @param value */ fun updateBackgroundJobEnabled(value: Boolean) { - SettingsRepository.updateBackgroundJobEnabled(value) + settingsRepository.updateBackgroundJobEnabled(value) } /** @@ -126,10 +127,10 @@ class SettingsViewModel : ViewModel() { * @param value */ fun updateManualKeyRetrievalEnabled(value: Boolean) { - SettingsRepository.updateManualKeyRetrievalEnabled(value) + settingsRepository.updateManualKeyRetrievalEnabled(value) } - fun refreshBackgroundPriorityEnabled(context: Context) { - SettingsRepository.refreshBackgroundPriorityEnabled(context) + fun refreshBackgroundPriorityEnabled() { + settingsRepository.refreshBackgroundPriorityEnabled() } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/BackgroundPrioritization.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/BackgroundPrioritization.kt new file mode 100644 index 0000000000000000000000000000000000000000..75934dc836964e21806d40754e6cc3600e1b4c40 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/BackgroundPrioritization.kt @@ -0,0 +1,6 @@ +package de.rki.coronawarnapp.util + +interface BackgroundPrioritization { + + val isBackgroundActivityPrioritized: Boolean +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt index 7771bd45d1d11cf11d1535bb352036c5d7c64b05..079c5f2a46e0bb0149ae5d20b85979a39e58b0ea 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt @@ -15,6 +15,7 @@ import android.os.Build import androidx.core.location.LocationManagerCompat import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.reporting.report +import de.rki.coronawarnapp.util.di.AppInjector import timber.log.Timber /** @@ -23,6 +24,10 @@ import timber.log.Timber object ConnectivityHelper { private val TAG: String? = ConnectivityHelper::class.simpleName + private val backgroundPrioritization by lazy { + AppInjector.component.connectivityHelperInjection.backgroundPrioritization + } + /** * Register bluetooth state change listener. * @@ -81,30 +86,30 @@ object ConnectivityHelper { * */ fun registerLocationStatusCallback(context: Context, callback: LocationCallback) { - val receiver = object : BroadcastReceiver() { - var isGpsEnabled: Boolean = false - var isNetworkEnabled: Boolean = false + val receiver = object : BroadcastReceiver() { + var isGpsEnabled: Boolean = false + var isNetworkEnabled: Boolean = false - override fun onReceive(context: Context, intent: Intent) { - intent.action?.let { act -> - if (act.matches("android.location.PROVIDERS_CHANGED".toRegex())) { - val locationManager = - context.getSystemService(Context.LOCATION_SERVICE) as LocationManager - isGpsEnabled = - locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) - isNetworkEnabled = - locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) + override fun onReceive(context: Context, intent: Intent) { + intent.action?.let { act -> + if (act.matches("android.location.PROVIDERS_CHANGED".toRegex())) { + val locationManager = + context.getSystemService(Context.LOCATION_SERVICE) as LocationManager + isGpsEnabled = + locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) + isNetworkEnabled = + locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) - if (isGpsEnabled || isNetworkEnabled) { - callback.onLocationAvailable() - Timber.d("Location enabled") - } else { - callback.onLocationUnavailable() - Timber.d("Location disabled") - } + if (isGpsEnabled || isNetworkEnabled) { + callback.onLocationAvailable() + Timber.d("Location enabled") + } else { + callback.onLocationUnavailable() + Timber.d("Location disabled") } } } + } } callback.recevier = receiver context.registerReceiver( @@ -200,7 +205,7 @@ object ConnectivityHelper { } /** - * Background jobs are enabled only if the battery optimization is enabled and + * Background jobs are enabled only if the background activity prioritization is enabled and * the background activity is not restricted * * @param context the context @@ -210,7 +215,7 @@ object ConnectivityHelper { * @see isBackgroundRestricted */ fun autoModeEnabled(context: Context): Boolean { - return !isBackgroundRestricted(context) || PowerManagementHelper.isIgnoringBatteryOptimizations(context) + return !isBackgroundRestricted(context) || backgroundPrioritization.isBackgroundActivityPrioritized } /** @@ -290,6 +295,7 @@ object ConnectivityHelper { */ abstract fun onLocationUnavailable() } + /** * Abstract network state change callback. * diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelperInjection.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelperInjection.kt new file mode 100644 index 0000000000000000000000000000000000000000..e7f7b9f58a3137d6f3ac40d1a61a7815e9ece671 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelperInjection.kt @@ -0,0 +1,8 @@ +package de.rki.coronawarnapp.util + +import javax.inject.Inject + +// TODO Wrapper that can be removed once **[ConnectivityHelper]** is no longer a singleton +data class ConnectivityHelperInjection @Inject constructor( + val backgroundPrioritization: BackgroundPrioritization +) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DefaultBackgroundPrioritization.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DefaultBackgroundPrioritization.kt new file mode 100644 index 0000000000000000000000000000000000000000..7cfd0d07b2c5fbbc01e76b1002709c5bc06b92ca --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DefaultBackgroundPrioritization.kt @@ -0,0 +1,12 @@ +package de.rki.coronawarnapp.util + +import de.rki.coronawarnapp.util.device.PowerManagement +import javax.inject.Inject + +class DefaultBackgroundPrioritization @Inject constructor( + private val powerManagement: PowerManagement +) : BackgroundPrioritization { + + override val isBackgroundActivityPrioritized + get() = powerManagement.isIgnoringBatteryOptimizations +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ExternalActionHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ExternalActionHelper.kt index 0883265034c19739c9fbf29f92d0ef99ebaa3827..5a2e9b6c046ba37283f8469c43a9aa1130a1c568 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ExternalActionHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ExternalActionHelper.kt @@ -156,35 +156,6 @@ object ExternalActionHelper { } } - fun disableBatteryOptimizations(context: Context) { - try { - val intent = Intent( - Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, - Uri.parse("package:" + context.packageName) - ) - context.startActivity(intent) - } catch (exception: Exception) { - // catch generic exception on settings navigation - // most likely due to device / rom specific intent issue - ExternalActionException(exception).report( - ExceptionCategory.UI - ) - } - } - - fun toBatteryOptimizationSettings(context: Context) { - try { - val intent = Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS) - context.startActivity(intent) - } catch (exception: Exception) { - // catch generic exception on settings navigation - // most likely due to device / rom specific intent issue - ExternalActionException(exception).report( - ExceptionCategory.UI - ) - } - } - fun toBatterySaverSettings(context: Context) { try { val intent = Intent(Settings.ACTION_BATTERY_SAVER_SETTINGS) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/PowerManagementHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/PowerManagementHelper.kt deleted file mode 100644 index a7c14291470c03b346044d284241a384ffb06099..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/PowerManagementHelper.kt +++ /dev/null @@ -1,14 +0,0 @@ -package de.rki.coronawarnapp.util - -import android.content.Context -import android.os.PowerManager - -object PowerManagementHelper { - /** - * Checks if app is excluded from battery optimizations - */ - fun isIgnoringBatteryOptimizations(context: Context): Boolean { - val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager - return powerManager.isIgnoringBatteryOptimizations(context.packageName) - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/UtilModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/UtilModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..79bc71b5d57157184b444befa641bd3b8ca559be --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/UtilModule.kt @@ -0,0 +1,23 @@ +package de.rki.coronawarnapp.util + +import dagger.Binds +import dagger.Module +import de.rki.coronawarnapp.util.device.DefaultPowerManagement +import de.rki.coronawarnapp.util.device.PowerManagement +import javax.inject.Singleton + +@Module +abstract class UtilModule { + + @Binds + @Singleton + abstract fun bindPowerManagement( + powerManagement: DefaultPowerManagement + ): PowerManagement + + @Binds + @Singleton + abstract fun bindBackgroundPrioritization( + backgroundPrioritization: DefaultBackgroundPrioritization + ): BackgroundPrioritization +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/device/DefaultPowerManagement.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/device/DefaultPowerManagement.kt new file mode 100644 index 0000000000000000000000000000000000000000..140b1e0e9d6804cc15a261441c8bad652ee980e3 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/device/DefaultPowerManagement.kt @@ -0,0 +1,43 @@ +package de.rki.coronawarnapp.util.device + +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.os.PowerManager +import android.provider.Settings +import de.rki.coronawarnapp.exception.ExceptionCategory +import de.rki.coronawarnapp.exception.ExternalActionException +import de.rki.coronawarnapp.exception.reporting.report +import javax.inject.Inject + +class DefaultPowerManagement @Inject constructor( + private val context: Context +) : PowerManagement { + + private val powerManager by lazy { + context.getSystemService(Context.POWER_SERVICE) as PowerManager + } + + override val isIgnoringBatteryOptimizations + get() = powerManager.isIgnoringBatteryOptimizations(context.packageName) + + override val toBatteryOptimizationSettingsIntent = + Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS) + + override fun disableBatteryOptimizations() { + try { + context.startActivity( + Intent( + Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, + Uri.parse("package:${context.packageName}") + ) + ) + } catch (exception: Exception) { + // catch generic exception on settings navigation + // most likely due to device / rom specific intent issue + ExternalActionException(exception).report( + ExceptionCategory.UI + ) + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/device/PowerManagement.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/device/PowerManagement.kt new file mode 100644 index 0000000000000000000000000000000000000000..1e92d27413aadefc031a42d06b47f8724db8cda4 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/device/PowerManagement.kt @@ -0,0 +1,15 @@ +package de.rki.coronawarnapp.util.device + +import android.content.Intent + +interface PowerManagement { + + /** + * Checks if app is excluded from battery optimizations + */ + val isIgnoringBatteryOptimizations: Boolean + + val toBatteryOptimizationSettingsIntent: Intent + + fun disableBatteryOptimizations() +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/AndroidModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/AndroidModule.kt index eb695f2f55046e01330eaeac796ccbe7a54afe36..15b4f6a3962f4e95b126bf2eb92a07ff3b3a263d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/AndroidModule.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/AndroidModule.kt @@ -4,11 +4,16 @@ import android.app.Application import android.content.Context import dagger.Module import dagger.Provides +import de.rki.coronawarnapp.CoronaWarnApplication import javax.inject.Singleton @Module class AndroidModule { + @Provides + @Singleton + fun application(app: CoronaWarnApplication): Application = app + @Provides @Singleton fun context(app: Application): Context = app.applicationContext diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt index 691b28bd77cf966da95fd440e6085b5713c475ac..b175c93c80857bd680b6732bc1943e9b23731da7 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt @@ -8,10 +8,13 @@ import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.receiver.ReceiverBinder import de.rki.coronawarnapp.risk.RiskModule import de.rki.coronawarnapp.service.ServiceBinder +import de.rki.coronawarnapp.storage.SettingsRepository import de.rki.coronawarnapp.transaction.RetrieveDiagnosisInjectionHelper import de.rki.coronawarnapp.transaction.RiskLevelInjectionHelper import de.rki.coronawarnapp.transaction.SubmitDiagnosisInjectionHelper import de.rki.coronawarnapp.ui.ActivityBinder +import de.rki.coronawarnapp.util.ConnectivityHelperInjection +import de.rki.coronawarnapp.util.UtilModule import de.rki.coronawarnapp.util.device.DeviceModule import javax.inject.Singleton @@ -23,16 +26,22 @@ import javax.inject.Singleton ReceiverBinder::class, ServiceBinder::class, ActivityBinder::class, - DeviceModule::class, - RiskModule::class + RiskModule::class, + UtilModule::class, + DeviceModule::class ] ) interface ApplicationComponent : AndroidInjector<CoronaWarnApplication> { + // TODO Remove once Singletons are gone val transRetrieveKeysInjection: RetrieveDiagnosisInjectionHelper val transRiskLevelInjection: RiskLevelInjectionHelper val transSubmitDiagnosisInjection: SubmitDiagnosisInjectionHelper + val connectivityHelperInjection: ConnectivityHelperInjection + + val settingsRepository: SettingsRepository + @Component.Factory interface Factory { fun create(@BindsInstance app: CoronaWarnApplication): ApplicationComponent diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/ExternalActionHelperTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/ExternalActionHelperTest.kt index 2ed5436204ef831e009df21951b2f55ed0a1b42a..0ca6efe8ca0da64c57dfd852a2253cd8427774ee 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/ExternalActionHelperTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/ExternalActionHelperTest.kt @@ -79,21 +79,6 @@ class ExternalActionHelperTest { verify(exactly = 1) { fragment.startActivity(any()) } } - @Test - fun disableBatteryOptimizations() { - every { context.packageName } returns "package_name" - every { context.startActivity(any()) } just Runs - ExternalActionHelper.disableBatteryOptimizations(context) - verify(exactly = 1) { context.startActivity(any()) } - } - - @Test - fun toBatteryOptimizationSettings() { - every { context.startActivity(any()) } just Runs - ExternalActionHelper.toBatteryOptimizationSettings(context) - verify(exactly = 1) { context.startActivity(any()) } - } - @After fun cleanUp() { unmockkAll()