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 9957f30..f868717 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 @@ -11,6 +11,7 @@ import androidx.core.app.NotificationManagerCompat import androidx.lifecycle.LifecycleService import androidx.lifecycle.lifecycleScope import im.angry.openeuicc.common.R +import im.angry.openeuicc.core.EuiccChannel import im.angry.openeuicc.core.EuiccChannelManager import im.angry.openeuicc.util.* import kotlinx.coroutines.Dispatchers @@ -446,30 +447,30 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker { iccid: String, enable: Boolean, // Enable or disable the profile indicated in iccid reconnectTimeoutMillis: Long = 0 // 0 = do not wait for reconnect - ): ForegroundTaskSubscriberFlow = + ) = launchForegroundTask( getString(R.string.task_profile_switch), getString(R.string.task_profile_switch_failure), R.drawable.ic_task_switch ) { - euiccChannelManager.beginTrackedOperation(slotId, portId) { - val (res, refreshed) = euiccChannelManager.withEuiccChannel( - slotId, - portId - ) { channel -> - if (!channel.lpa.switchProfile(iccid, enable, refresh = true)) { - // Sometimes, we *can* enable or disable the profile, but we cannot - // send the refresh command to the modem because the profile somehow - // makes the modem "busy". In this case, we can still switch by setting - // refresh to false, but then the switch cannot take effect until the - // user resets the modem manually by toggling airplane mode or rebooting. - Pair(channel.lpa.switchProfile(iccid, enable, refresh = false), false) - } else { - Pair(true, true) - } - } + suspend fun onSwitch(channel: EuiccChannel): Pair { + val refresh = preferenceRepository.refreshAfterSwitchFlow.first() + val response = channel.lpa.switchProfile(iccid, enable, refresh) + if (response || !refresh) return Pair(response, refresh) + // refresh failed, but refresh was requested + // Sometimes, we *can* enable or disable the profile, but we cannot + // send the refresh command to the modem because the profile somehow + // makes the modem "busy". In this case, we can still switch by setting + // refresh to false, but then the switch cannot take effect until the + // user resets the modem manually by toggling airplane mode or rebooting. + return Pair(channel.lpa.switchProfile(iccid, enable, refresh = false), false) + } - if (!res) { + euiccChannelManager.beginTrackedOperation(slotId, portId) { + val (response, refreshed) = + euiccChannelManager.withEuiccChannel(slotId, portId, ::onSwitch) + + if (!response) { throw RuntimeException("Could not switch profile") } diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt index b085286..d137e90 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt @@ -78,6 +78,9 @@ open class SettingsFragment: PreferenceFragmentCompat() { requirePreference("pref_developer_ignore_tls_certificate") .bindBooleanFlow(preferenceRepository.ignoreTLSCertificateFlow) + requirePreference("pref_developer_refresh_after_switch") + .bindBooleanFlow(preferenceRepository.refreshAfterSwitchFlow) + requirePreference("pref_developer_euicc_memory_reset") .bindBooleanFlow(preferenceRepository.euiccMemoryResetFlow) } diff --git a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt index 34d1cfd..c69c5e4 100644 --- a/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt +++ b/app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt @@ -31,6 +31,7 @@ internal object PreferenceKeys { // ---- Developer Options ---- val DEVELOPER_OPTIONS_ENABLED = booleanPreferencesKey("developer_options_enabled") + val REFRESH_AFTER_SWITCH = booleanPreferencesKey("refresh_after_switch") val UNFILTERED_PROFILE_LIST = booleanPreferencesKey("unfiltered_profile_list") val IGNORE_TLS_CERTIFICATE = booleanPreferencesKey("ignore_tls_certificate") val EUICC_MEMORY_RESET = booleanPreferencesKey("euicc_memory_reset") @@ -48,6 +49,7 @@ open class PreferenceRepository(private val context: Context) { val verboseLoggingFlow = bindFlow(PreferenceKeys.VERBOSE_LOGGING, false) // ---- Developer Options ---- + val refreshAfterSwitchFlow = bindFlow(PreferenceKeys.REFRESH_AFTER_SWITCH, true) val developerOptionsEnabledFlow = bindFlow(PreferenceKeys.DEVELOPER_OPTIONS_ENABLED, false) val unfilteredProfileListFlow = bindFlow(PreferenceKeys.UNFILTERED_PROFILE_LIST, false) val ignoreTLSCertificateFlow = bindFlow(PreferenceKeys.IGNORE_TLS_CERTIFICATE, false) @@ -60,15 +62,12 @@ open class PreferenceRepository(private val context: Context) { class PreferenceFlowWrapper private constructor( private val context: Context, private val key: Preferences.Key, - inner: Flow + inner: Flow, ) : Flow by inner { - internal constructor(context: Context, key: Preferences.Key, defaultValue: T) : this( - context, - key, - context.dataStore.data.map { it[key] ?: defaultValue } - ) + internal constructor(context: Context, key: Preferences.Key, defaultValue: T) : + this(context, key, context.dataStore.data.map { it[key] ?: defaultValue }) suspend fun updatePreference(value: T) { context.dataStore.edit { it[key] = value } } -} \ No newline at end of file +} diff --git a/app-common/src/main/res/values/strings.xml b/app-common/src/main/res/values/strings.xml index cc84381..2e458e8 100644 --- a/app-common/src/main/res/values/strings.xml +++ b/app-common/src/main/res/values/strings.xml @@ -181,6 +181,8 @@ Logs View recent debug logs of the application Developer Options + Refresh status after switching + If crash after switch, Please trying disable the function Show unfiltered profile list Include non-production profiles in the list Ignore SM-DP+ TLS certificate diff --git a/app-common/src/main/res/xml/pref_settings.xml b/app-common/src/main/res/xml/pref_settings.xml index 7d25118..ce700f5 100644 --- a/app-common/src/main/res/xml/pref_settings.xml +++ b/app-common/src/main/res/xml/pref_settings.xml @@ -57,6 +57,12 @@ app:title="@string/pref_developer" app:iconSpaceReserved="false"> + +