From fe1319537ace15ab2f323e7fce951c155eeffe73 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sun, 29 Sep 2024 15:30:49 -0400 Subject: [PATCH 1/2] Make foreground tasks block UI reloads --- .../openeuicc/service/EuiccChannelManagerService.kt | 10 ++++++++++ .../im/angry/openeuicc/ui/EuiccManagementFragment.kt | 1 + .../main/java/im/angry/openeuicc/ui/MainActivity.kt | 2 ++ .../im/angry/openeuicc/ui/ProfileDownloadFragment.kt | 6 ++++++ 4 files changed, 19 insertions(+) diff --git a/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt b/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt index c9a252a..97a7841 100644 --- a/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt +++ b/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt @@ -16,8 +16,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.onCompletion +import kotlinx.coroutines.flow.takeWhile import kotlinx.coroutines.flow.transformWhile import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -186,6 +188,14 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker { }.onCompletion { foregroundTaskState.value = ForegroundTaskState.Idle } } + val isForegroundTaskRunning: Boolean + get() = foregroundTaskState.value != ForegroundTaskState.Idle + + suspend fun waitForForegroundTask() { + foregroundTaskState.takeWhile { it != ForegroundTaskState.Idle } + .collect() + } + fun launchProfileDownloadTask( slotId: Int, portId: Int, diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt index fc2aa5c..14d958d 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt @@ -155,6 +155,7 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener, lifecycleScope.launch { ensureEuiccChannelManager() + euiccChannelManagerService.waitForForegroundTask() if (!this@EuiccManagementFragment::disableSafeguardFlow.isInitialized) { disableSafeguardFlow = diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/MainActivity.kt b/app-common/src/main/java/im/angry/openeuicc/ui/MainActivity.kt index 1307513..17c99ff 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/MainActivity.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/MainActivity.kt @@ -134,6 +134,8 @@ open class MainActivity : BaseEuiccAccessActivity(), OpenEuiccContextMarker { loadingProgress.visibility = View.VISIBLE viewPager.visibility = View.GONE tabs.visibility = View.GONE + // Prevent concurrent access with any running foreground task + euiccChannelManagerService.waitForForegroundTask() val knownChannels = withContext(Dispatchers.IO) { euiccChannelManager.enumerateEuiccChannels().onEach { diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/ProfileDownloadFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/ProfileDownloadFragment.kt index 99ac003..35825bf 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/ProfileDownloadFragment.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/ProfileDownloadFragment.kt @@ -160,6 +160,12 @@ class ProfileDownloadFragment : BaseMaterialDialogFragment(), lifecycleScope.launch(Dispatchers.IO) { ensureEuiccChannelManager() + if (euiccChannelManagerService.isForegroundTaskRunning) { + withContext(Dispatchers.Main) { + dismiss() + } + return@launch + } // Fetch remaining NVRAM val str = channel.lpa.euiccInfo2?.freeNvram?.also { From f71da0e4ffefbc74d6b75a843885acb74109b0a4 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sun, 29 Sep 2024 15:32:46 -0400 Subject: [PATCH 2/2] Update documentation --- .../openeuicc/service/EuiccChannelManagerService.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt b/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt index 97a7841..f177f1a 100644 --- a/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt +++ b/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt @@ -131,9 +131,13 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker { /** * Launch a potentially blocking foreground task in this service's lifecycle context. * This function does not block, but returns a Flow that emits ForegroundTaskState - * updates associated with this task. + * updates associated with this task. The last update the returned flow will emit is + * always ForegroundTaskState.Done. + * * The task closure is expected to update foregroundTaskState whenever appropriate. * If a foreground task is already running, this function returns null. + * + * The function will set the state back to Idle once it sees ForegroundTaskState.Done. */ private fun launchForegroundTask( title: String, @@ -178,6 +182,9 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker { // We should be the only task running, so we can subscribe to foregroundTaskState // until we encounter ForegroundTaskState.Done. + // Then, we complete the returned flow, but we also set the state back to Idle. + // The state update back to Idle won't show up in the returned stream, because + // it has been completed by that point. return foregroundTaskState.transformWhile { // Also update our notification when we see an update withContext(Dispatchers.Main) {