From 912f2be4d3559f058fea2de46c78f4af551b1c6c Mon Sep 17 00:00:00 2001
From: Matthias Urhahn <matthias.urhahn@sap.com>
Date: Wed, 25 Nov 2020 11:51:00 +0100
Subject: [PATCH] Change the polling based flows. (#1707)

callbackflow wasn't a good fit and this should be a simpler solution.
May fix some class cast exception on MediaTek chipsets.

Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com>
---
 .../modules/tracing/DefaultTracingStatus.kt   | 28 +++++++------
 .../util/BackgroundModeStatus.kt              | 42 +++++++++----------
 2 files changed, 36 insertions(+), 34 deletions(-)

diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt
index c2319109f..d8ef3330e 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt
@@ -5,16 +5,16 @@ import de.rki.coronawarnapp.exception.ExceptionCategory
 import de.rki.coronawarnapp.exception.reporting.report
 import de.rki.coronawarnapp.util.coroutine.AppScope
 import de.rki.coronawarnapp.util.flow.shareLatest
+import kotlinx.coroutines.CancellationException
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.cancel
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.catch
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.flow.onCompletion
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.isActive
 import timber.log.Timber
 import javax.inject.Inject
 import javax.inject.Singleton
@@ -28,24 +28,26 @@ class DefaultTracingStatus @Inject constructor(
     @AppScope val scope: CoroutineScope
 ) : TracingStatus {
 
-    override val isTracingEnabled: Flow<Boolean> = callbackFlow<Boolean> {
+    override val isTracingEnabled: Flow<Boolean> = flow {
         while (true) {
             try {
-                send(pollIsEnabled())
-            } catch (e: Exception) {
-                Timber.w(e, "ENF isEnabled failed.")
-                send(false)
-                e.report(ExceptionCategory.EXPOSURENOTIFICATION, TAG, null)
-                cancel("ENF isEnabled failed", e)
+                emit(pollIsEnabled())
+                delay(POLLING_DELAY_MS)
+            } catch (e: CancellationException) {
+                Timber.d("isBackgroundRestricted was cancelled")
+                break
             }
-            if (!isActive) break
-            delay(POLLING_DELAY_MS)
         }
     }
         .distinctUntilChanged()
         .onStart { Timber.v("isTracingEnabled FLOW start") }
         .onEach { Timber.v("isTracingEnabled FLOW emission: %b", it) }
-        .onCompletion { Timber.v("isTracingEnabled FLOW completed.") }
+        .onCompletion { if (it == null) Timber.v("isTracingEnabled FLOW completed.") }
+        .catch {
+            Timber.w(it, "ENF isEnabled failed.")
+            it.report(ExceptionCategory.EXPOSURENOTIFICATION, TAG, null)
+            emit(false)
+        }
         .shareLatest(
             tag = TAG,
             scope = scope
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/BackgroundModeStatus.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/BackgroundModeStatus.kt
index 2e26c1991..838637192 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/BackgroundModeStatus.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/BackgroundModeStatus.kt
@@ -4,13 +4,13 @@ import android.content.Context
 import de.rki.coronawarnapp.util.coroutine.AppScope
 import de.rki.coronawarnapp.util.di.AppContext
 import de.rki.coronawarnapp.util.flow.shareLatest
+import kotlinx.coroutines.CancellationException
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.cancel
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.callbackFlow
 import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.isActive
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.onCompletion
 import timber.log.Timber
 import javax.inject.Inject
 import javax.inject.Singleton
@@ -21,41 +21,41 @@ class BackgroundModeStatus @Inject constructor(
     @AppScope private val appScope: CoroutineScope
 ) {
 
-    val isBackgroundRestricted: Flow<Boolean?> = callbackFlow<Boolean> {
+    val isBackgroundRestricted: Flow<Boolean> = flow {
         while (true) {
             try {
-                send(pollIsBackgroundRestricted())
-            } catch (e: Exception) {
-                Timber.w(e, "isBackgroundRestricted failed.")
-                cancel("isBackgroundRestricted failed", e)
+                emit(pollIsBackgroundRestricted())
+                delay(POLLING_DELAY_MS)
+            } catch (e: CancellationException) {
+                Timber.d("isBackgroundRestricted was cancelled")
+                break
             }
-
-            if (!isActive) break
-
-            delay(POLLING_DELAY_MS)
         }
     }
         .distinctUntilChanged()
+        .onCompletion {
+            if (it != null) Timber.w(it, "isBackgroundRestricted failed.")
+        }
         .shareLatest(
             tag = "isBackgroundRestricted",
             scope = appScope
         )
 
-    val isAutoModeEnabled: Flow<Boolean> = callbackFlow<Boolean> {
+    val isAutoModeEnabled: Flow<Boolean> = flow {
         while (true) {
             try {
-                send(pollIsAutoMode())
-            } catch (e: Exception) {
-                Timber.w(e, "autoModeEnabled failed.")
-                cancel("autoModeEnabled failed", e)
+                emit(pollIsAutoMode())
+                delay(POLLING_DELAY_MS)
+            } catch (e: CancellationException) {
+                Timber.d("isAutoModeEnabled was cancelled")
+                break
             }
-
-            if (!isActive) break
-
-            delay(POLLING_DELAY_MS)
         }
     }
         .distinctUntilChanged()
+        .onCompletion {
+            if (it != null) Timber.w(it, "autoModeEnabled failed.")
+        }
         .shareLatest(
             tag = "autoModeEnabled",
             scope = appScope
-- 
GitLab