Compare commits

...

2 commits

Author SHA1 Message Date
f71da0e4ff Update documentation
All checks were successful
/ build-debug (push) Successful in 4m29s
2024-09-29 15:32:46 -04:00
fe1319537a Make foreground tasks block UI reloads 2024-09-29 15:30:49 -04:00
4 changed files with 27 additions and 1 deletions

View file

@ -16,8 +16,10 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.takeWhile
import kotlinx.coroutines.flow.transformWhile import kotlinx.coroutines.flow.transformWhile
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -129,9 +131,13 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker {
/** /**
* Launch a potentially blocking foreground task in this service's lifecycle context. * Launch a potentially blocking foreground task in this service's lifecycle context.
* This function does not block, but returns a Flow that emits ForegroundTaskState * 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. * The task closure is expected to update foregroundTaskState whenever appropriate.
* If a foreground task is already running, this function returns null. * 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( private fun launchForegroundTask(
title: String, title: String,
@ -176,6 +182,9 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker {
// We should be the only task running, so we can subscribe to foregroundTaskState // We should be the only task running, so we can subscribe to foregroundTaskState
// until we encounter ForegroundTaskState.Done. // 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 { return foregroundTaskState.transformWhile {
// Also update our notification when we see an update // Also update our notification when we see an update
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
@ -186,6 +195,14 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker {
}.onCompletion { foregroundTaskState.value = ForegroundTaskState.Idle } }.onCompletion { foregroundTaskState.value = ForegroundTaskState.Idle }
} }
val isForegroundTaskRunning: Boolean
get() = foregroundTaskState.value != ForegroundTaskState.Idle
suspend fun waitForForegroundTask() {
foregroundTaskState.takeWhile { it != ForegroundTaskState.Idle }
.collect()
}
fun launchProfileDownloadTask( fun launchProfileDownloadTask(
slotId: Int, slotId: Int,
portId: Int, portId: Int,

View file

@ -155,6 +155,7 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
lifecycleScope.launch { lifecycleScope.launch {
ensureEuiccChannelManager() ensureEuiccChannelManager()
euiccChannelManagerService.waitForForegroundTask()
if (!this@EuiccManagementFragment::disableSafeguardFlow.isInitialized) { if (!this@EuiccManagementFragment::disableSafeguardFlow.isInitialized) {
disableSafeguardFlow = disableSafeguardFlow =

View file

@ -134,6 +134,8 @@ open class MainActivity : BaseEuiccAccessActivity(), OpenEuiccContextMarker {
loadingProgress.visibility = View.VISIBLE loadingProgress.visibility = View.VISIBLE
viewPager.visibility = View.GONE viewPager.visibility = View.GONE
tabs.visibility = View.GONE tabs.visibility = View.GONE
// Prevent concurrent access with any running foreground task
euiccChannelManagerService.waitForForegroundTask()
val knownChannels = withContext(Dispatchers.IO) { val knownChannels = withContext(Dispatchers.IO) {
euiccChannelManager.enumerateEuiccChannels().onEach { euiccChannelManager.enumerateEuiccChannels().onEach {

View file

@ -160,6 +160,12 @@ class ProfileDownloadFragment : BaseMaterialDialogFragment(),
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
ensureEuiccChannelManager() ensureEuiccChannelManager()
if (euiccChannelManagerService.isForegroundTaskRunning) {
withContext(Dispatchers.Main) {
dismiss()
}
return@launch
}
// Fetch remaining NVRAM // Fetch remaining NVRAM
val str = channel.lpa.euiccInfo2?.freeNvram?.also { val str = channel.lpa.euiccInfo2?.freeNvram?.also {