summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2021-05-03 19:07:01 +0000
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2021-05-14 20:39:01 +0000
commita1076abac6cb43941f01e16dbe0156c6eacd0361 (patch)
tree8af552c089136d8a6c18acdf0783bbfc620ba3ff /android
parenta486e2286ab6685e4e0e6d676587b629fa738404 (diff)
downloadmullvadvpn-a1076abac6cb43941f01e16dbe0156c6eacd0361.tar.xz
mullvadvpn-a1076abac6cb43941f01e16dbe0156c6eacd0361.zip
Create `HandlerFlow` helper type
A handler message loop that can be used as a `Flow`.
Diffstat (limited to 'android')
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/HandlerFlow.kt45
1 files changed, 45 insertions, 0 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/HandlerFlow.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/HandlerFlow.kt
new file mode 100644
index 0000000000..943c55eeff
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/HandlerFlow.kt
@@ -0,0 +1,45 @@
+package net.mullvad.mullvadvpn.ipc
+
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import android.util.Log
+import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.InternalCoroutinesApi
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.ClosedSendChannelException
+import kotlinx.coroutines.channels.sendBlocking
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.FlowCollector
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.consumeAsFlow
+import kotlinx.coroutines.flow.onCompletion
+
+class HandlerFlow<T>(
+ looper: Looper,
+ private val extractor: (Message) -> T
+) : Handler(looper), Flow<T> {
+ private val channel = Channel<T>(Channel.UNLIMITED)
+ private val flow = channel.consumeAsFlow().onCompletion {
+ removeCallbacksAndMessages(null)
+ }
+
+ @InternalCoroutinesApi
+ override suspend fun collect(collector: FlowCollector<T>) = flow.collect(collector)
+
+ override fun handleMessage(message: Message) {
+ val extractedData = extractor(message)
+
+ try {
+ channel.sendBlocking(extractedData)
+ } catch (exception: Exception) {
+ when (exception) {
+ is ClosedSendChannelException, is CancellationException -> {
+ Log.w("mullvad", "Received a message after HandlerFlow was closed", exception)
+ removeCallbacksAndMessages(null)
+ }
+ else -> throw exception
+ }
+ }
+ }
+}