diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2020-11-20 17:17:42 +0000 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2020-11-20 19:14:04 +0000 |
| commit | 70da5c302698a16cec6fadc694ebf2abc169e6c0 (patch) | |
| tree | 98d44aeb22156b3e34b2e8f05593a81e2bed8fb7 /android/src | |
| parent | 5dfccd389a9c07071ce63c360c341e69a5948627 (diff) | |
| download | mullvadvpn-70da5c302698a16cec6fadc694ebf2abc169e6c0.tar.xz mullvadvpn-70da5c302698a16cec6fadc694ebf2abc169e6c0.zip | |
Use an actor for updating the notification
Ensures that all updates are done in the UI thread.
Diffstat (limited to 'android/src')
| -rw-r--r-- | android/src/main/kotlin/net/mullvad/mullvadvpn/service/ForegroundNotificationManager.kt | 80 |
1 files changed, 59 insertions, 21 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ForegroundNotificationManager.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ForegroundNotificationManager.kt index c402881488..2daf1477ba 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ForegroundNotificationManager.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ForegroundNotificationManager.kt @@ -8,6 +8,11 @@ import android.content.Intent import android.content.IntentFilter import android.os.Build import kotlin.properties.Delegates.observable +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.actor +import kotlinx.coroutines.channels.sendBlocking import net.mullvad.mullvadvpn.model.TunnelState import net.mullvad.mullvadvpn.service.notifications.TunnelStateNotification import net.mullvad.talpid.util.EventNotifier @@ -18,6 +23,15 @@ class ForegroundNotificationManager( val serviceNotifier: EventNotifier<ServiceInstance?>, val keyguardManager: KeyguardManager ) { + private sealed class UpdaterMessage { + class UpdateNotification : UpdaterMessage() + class UpdateAction : UpdaterMessage() + class AcknowledgeStartForegroundService : UpdaterMessage() + class NewTunnelState(val newState: TunnelState) : UpdaterMessage() + } + + private val updater = runUpdater() + private val tunnelStateNotification = TunnelStateNotification(service) private val deviceLockListener = object : BroadcastReceiver() { @@ -36,15 +50,16 @@ class ForegroundNotificationManager( private var tunnelStateEvents by autoSubscribable<TunnelState>(this, TunnelState.Disconnected()) { newState -> - tunnelStateNotification.tunnelState = newState - updateNotification() + updater.sendBlocking(UpdaterMessage.NewTunnelState(newState)) } private var deviceIsUnlocked by observable(!keyguardManager.isDeviceLocked) { _, _, _ -> - updateNotificationAction() + updater.sendBlocking(UpdaterMessage.UpdateAction()) } - private var loggedIn by observable(false) { _, _, _ -> updateNotificationAction() } + private var loggedIn by observable(false) { _, _, _ -> + updater.sendBlocking(UpdaterMessage.UpdateAction()) + } private val tunnelState get() = tunnelStateEvents?.latestEvent ?: TunnelState.Disconnected() @@ -55,7 +70,9 @@ class ForegroundNotificationManager( var onForeground = false private set - var lockedToForeground by observable(false) { _, _, _ -> updateNotification() } + var lockedToForeground by observable(false) { _, _, _ -> + updater.sendBlocking(UpdaterMessage.UpdateNotification()) + } init { serviceNotifier.subscribe(this) { newServiceInstance -> @@ -73,7 +90,7 @@ class ForegroundNotificationManager( ) } - updateNotification() + updater.sendBlocking(UpdaterMessage.UpdateNotification()) } fun onDestroy() { @@ -84,17 +101,40 @@ class ForegroundNotificationManager( service.unregisterReceiver(deviceLockListener) - tunnelStateNotification.visible = false + updater.close() } fun acknowledgeStartForegroundService() { + updater.sendBlocking(UpdaterMessage.AcknowledgeStartForegroundService()) + } + + private fun runUpdater() = GlobalScope.actor<UpdaterMessage>( + Dispatchers.Main, + Channel.UNLIMITED + ) { + for (message in channel) { + when (message) { + is UpdaterMessage.UpdateNotification -> updateNotification() + is UpdaterMessage.UpdateAction -> updateNotificationAction() + is UpdaterMessage.AcknowledgeStartForegroundService -> { + doAcknowledgeStartForegroundService() + } + is UpdaterMessage.NewTunnelState -> { + tunnelStateNotification.tunnelState = message.newState + updateNotification() + } + } + } + + tunnelStateNotification.visible = false + } + + private fun doAcknowledgeStartForegroundService() { // When sending start commands to the service, it is necessary to request the service to be // on the foreground. With such request, when the service is started it must be placed on // the foreground with a call to startForeground before a timeout expires, otherwise Android // kills the app. - synchronized(this) { - showOnForeground() - } + showOnForeground() // Restore the notification to its correct state. updateNotification() @@ -110,19 +150,17 @@ class ForegroundNotificationManager( } private fun updateNotification() { - synchronized(this) { - if (shouldBeOnForeground != onForeground) { - if (shouldBeOnForeground) { - showOnForeground() + if (shouldBeOnForeground != onForeground) { + if (shouldBeOnForeground) { + showOnForeground() + } else { + if (Build.VERSION.SDK_INT >= 24) { + service.stopForeground(Service.STOP_FOREGROUND_DETACH) } else { - if (Build.VERSION.SDK_INT >= 24) { - service.stopForeground(Service.STOP_FOREGROUND_DETACH) - } else { - service.stopForeground(false) - } - - onForeground = false + service.stopForeground(false) } + + onForeground = false } } } |
