From 3f896faca90a3f93f3297cc17eef2f571a83e0b9 Mon Sep 17 00:00:00 2001
From: Matthias Urhahn <matthias.urhahn@sap.com>
Date: Fri, 21 May 2021 16:07:57 +0200
Subject: [PATCH] Reduce config check timeout for the update checker
 (EXPOSUREAPP-6101) (#3245)

* Reduce config check timeout for the update checker by 50% to reduce app blocking on launch due to bad internet or firewalls.

* LINT

Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com>
---
 .../rki/coronawarnapp/update/UpdateChecker.kt | 12 +++---
 .../coronawarnapp/update/UpdateCheckerTest.kt | 38 +++++++++++++++++++
 2 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/update/UpdateChecker.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/update/UpdateChecker.kt
index dd664afae..417619858 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/update/UpdateChecker.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/update/UpdateChecker.kt
@@ -8,6 +8,7 @@ import de.rki.coronawarnapp.appconfig.AppConfigProvider
 import de.rki.coronawarnapp.appconfig.CWAConfig
 import de.rki.coronawarnapp.appconfig.internal.ApplicationConfigurationCorruptException
 import de.rki.coronawarnapp.environment.BuildConfigWrap
+import kotlinx.coroutines.withTimeout
 import timber.log.Timber
 import javax.inject.Inject
 
@@ -29,13 +30,15 @@ class UpdateChecker @Inject constructor(
         )
 
         Result(isUpdateNeeded = true, updateIntent = createUpdateAction())
-    } catch (exception: Exception) {
-        Timber.tag(TAG).e("Exception caught:%s", exception.localizedMessage)
+    } catch (e: Exception) {
+        Timber.tag(TAG).e(e, "Update check failed, network connection?")
         Result(isUpdateNeeded = false)
     }
 
     private suspend fun isUpdateNeeded(): Boolean {
-        val cwaAppConfig: CWAConfig = appConfigProvider.getAppConfig()
+        val cwaAppConfig: CWAConfig = withTimeout(UPDATE_CHECK_TIMEOUT) {
+            appConfigProvider.getAppConfig()
+        }
 
         val minVersionFromServer = cwaAppConfig.minVersionCode
 
@@ -43,7 +46,6 @@ class UpdateChecker @Inject constructor(
 
         Timber.tag(TAG).d("minVersionFromServer:%s", minVersionFromServer)
         Timber.tag(TAG).d("Current app version:%s", currentVersion)
-
         val needsImmediateUpdate = VersionComparator.isVersionOlder(
             currentVersion,
             minVersionFromServer
@@ -67,7 +69,7 @@ class UpdateChecker @Inject constructor(
 
     companion object {
         private const val TAG: String = "UpdateChecker"
-
+        private const val UPDATE_CHECK_TIMEOUT = 5_000L
         private const val STORE_PREFIX = "https://play.google.com/store/apps/details?id="
         private const val COM_ANDROID_VENDING = "com.android.vending"
     }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/update/UpdateCheckerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/update/UpdateCheckerTest.kt
index 6ae3f903d..cd58fb66a 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/update/UpdateCheckerTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/update/UpdateCheckerTest.kt
@@ -12,7 +12,9 @@ import io.mockk.coVerifySequence
 import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import io.mockk.mockkObject
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.test.runBlockingTest
+import okio.IOException
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
@@ -89,4 +91,40 @@ class UpdateCheckerTest : BaseTest() {
             appConfigProvider.getAppConfig()
         }
     }
+
+    @Test
+    fun `timeout after 5 seconds`() = runBlockingTest {
+        every { configData.minVersionCode } returns 10
+        every { BuildConfigWrap.VERSION_CODE } returns 9
+
+        coEvery { appConfigProvider.getAppConfig() } coAnswers {
+            delay(4_000)
+            configData
+        }
+
+        createInstance().checkForUpdate().apply {
+            isUpdateNeeded shouldBe true
+            updateIntent shouldNotBe null
+        }
+
+        coEvery { appConfigProvider.getAppConfig() } coAnswers {
+            delay(6_000)
+            throw IOException()
+        }
+
+        createInstance().checkForUpdate().apply {
+            isUpdateNeeded shouldBe false
+            updateIntent shouldBe null
+        }
+
+        coEvery { appConfigProvider.getAppConfig() } coAnswers {
+            delay(6_000)
+            configData
+        }
+
+        createInstance().checkForUpdate().apply {
+            isUpdateNeeded shouldBe false
+            updateIntent shouldBe null
+        }
+    }
 }
-- 
GitLab