Browse Source

feat: support disabling refresh after switch in settings

peter: Reworked strings and i18 translations. Also removed the ad-hoc
function in favor of a lambda.
septs 10 months ago
parent
commit
dc6b3a4810

+ 21 - 16
app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt

@@ -12,6 +12,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
@@ -456,30 +457,34 @@ 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)
+                val (response, refreshed) =
+                    euiccChannelManager.withEuiccChannel(slotId, portId) { channel ->
+                        val refresh = preferenceRepository.refreshAfterSwitchFlow.first()
+                        val response = channel.lpa.switchProfile(iccid, enable, refresh)
+                        if (response || !refresh) {
+                            Pair(response, refresh)
+                        } else {
+                            // 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.
+                            Pair(
+                                channel.lpa.switchProfile(iccid, enable, refresh = false),
+                                false
+                            )
+                        }
                     }
-                }
 
-                if (!res) {
+                if (!response) {
                     throw RuntimeException("Could not switch profile")
                 }
 

+ 3 - 0
app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt

@@ -78,6 +78,9 @@ open class SettingsFragment: PreferenceFragmentCompat() {
         requirePreference<CheckBoxPreference>("pref_developer_ignore_tls_certificate")
             .bindBooleanFlow(preferenceRepository.ignoreTLSCertificateFlow)
 
+        requirePreference<CheckBoxPreference>("pref_developer_refresh_after_switch")
+            .bindBooleanFlow(preferenceRepository.refreshAfterSwitchFlow)
+
         requirePreference<CheckBoxPreference>("pref_developer_euicc_memory_reset")
             .bindBooleanFlow(preferenceRepository.euiccMemoryResetFlow)
     }

+ 6 - 7
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<T> private constructor(
     private val context: Context,
     private val key: Preferences.Key<T>,
-    inner: Flow<T>
+    inner: Flow<T>,
 ) : Flow<T> by inner {
-    internal constructor(context: Context, key: Preferences.Key<T>, defaultValue: T) : this(
-        context,
-        key,
-        context.dataStore.data.map { it[key] ?: defaultValue }
-    )
+    internal constructor(context: Context, key: Preferences.Key<T>, defaultValue: T) :
+            this(context, key, context.dataStore.data.map { it[key] ?: defaultValue })
 
     suspend fun updatePreference(value: T) {
         context.dataStore.edit { it[key] = value }
     }
-}
+}

+ 2 - 0
app-common/src/main/res/values-ja/strings.xml

@@ -143,6 +143,7 @@
     <string name="pref_advanced_logs">ログ</string>
     <string name="pref_advanced_logs_desc">アプリの最新デバッグログを表示します</string>
     <string name="pref_developer">開発者オプション</string>
+    <string name="pref_developer_refresh_after_switch_desc">プロファイルを切り替えた後にモデムに更新コマンドを送信するかどうか。クラッシュが発生する場合は、これを無効にしてみてください。</string>
     <string name="pref_developer_unfiltered_profile_list">フィルタリングされていないプロファイル一覧を表示</string>
     <string name="pref_developer_unfiltered_profile_list_desc">非運用のプロファイルも含めます</string>
     <string name="pref_developer_ignore_tls_certificate">SM-DP+ TLS 証明書を無視する</string>
@@ -162,4 +163,5 @@
     <string name="euicc_memory_reset_invoke_button">消去する</string>
     <string name="pref_developer_euicc_memory_reset">eUICC の消去を可能にする</string>
     <string name="pref_developer_euicc_memory_reset_desc">この操作は、デフォルトでは非表示になっている危険な操作です。代わりに、すべての構成ファイルを手動で削除することもできます。</string>
+    <string name="pref_developer_refresh_after_switch">モデムに更新コマンドを送信</string>
 </resources>

+ 2 - 0
app-common/src/main/res/values-zh-rCN/strings.xml

@@ -145,6 +145,7 @@
     <string name="pref_advanced_language">语言</string>
     <string name="pref_advanced_language_desc">选择 App 语言</string>
     <string name="pref_developer">开发者选项</string>
+    <string name="pref_developer_refresh_after_switch_desc">切换配置文件后是否向基带发送刷新命令。如果发现崩溃,请尝试禁用此功能。</string>
     <string name="pref_developer_unfiltered_profile_list">显示未经过滤的配置文件列表</string>
     <string name="pref_developer_unfiltered_profile_list_desc">在配置文件列表中包括非生产环境的配置文件</string>
     <string name="pref_developer_ignore_tls_certificate">无视 SM-DP+ 的 TLS 证书</string>
@@ -162,4 +163,5 @@
     <string name="euicc_memory_reset_invoke_button">擦除</string>
     <string name="pref_developer_euicc_memory_reset">允许擦除 eUICC</string>
     <string name="pref_developer_euicc_memory_reset_desc">此操作是默认隐藏的危险操作。作为替代方案,您可以手动删除所有配置文件。</string>
+    <string name="pref_developer_refresh_after_switch">向基带发送刷新命令</string>
 </resources>

+ 2 - 0
app-common/src/main/res/values-zh-rTW/strings.xml

@@ -145,6 +145,7 @@
     <string name="pref_advanced_language">語言</string>
     <string name="pref_advanced_language_desc">選擇 App 語言</string>
     <string name="pref_developer">開發人員選項</string>
+    <string name="pref_developer_refresh_after_switch_desc">切換設定檔後是否向基帶發送刷新命令。如果發現崩潰,請嘗試停用此功能。</string>
     <string name="pref_developer_unfiltered_profile_list">顯示未經過濾的設定檔列表</string>
     <string name="pref_developer_unfiltered_profile_list_desc">在設定檔列表中包括非生產環境的設定檔</string>
     <string name="pref_developer_ignore_tls_certificate">忽略 SM-DP+ 的 TLS 證書</string>
@@ -162,4 +163,5 @@
     <string name="euicc_memory_reset_invoke_button">擦除</string>
     <string name="pref_developer_euicc_memory_reset">允許擦除 eUICC</string>
     <string name="pref_developer_euicc_memory_reset_desc">此操作是預設隱藏的危險操作。作為替代方案,您可以手動刪除所有設定檔。</string>
+    <string name="pref_developer_refresh_after_switch">向基帶發送刷新命令</string>
 </resources>

+ 2 - 0
app-common/src/main/res/values/strings.xml

@@ -181,6 +181,8 @@
     <string name="pref_advanced_logs">Logs</string>
     <string name="pref_advanced_logs_desc">View recent debug logs of the application</string>
     <string name="pref_developer">Developer Options</string>
+    <string name="pref_developer_refresh_after_switch">Send refresh command to modem</string>
+    <string name="pref_developer_refresh_after_switch_desc">Whether to send a refresh command to the modem after switching profiles. Try disabling this if you see crashes.</string>
     <string name="pref_developer_unfiltered_profile_list">Show unfiltered profile list</string>
     <string name="pref_developer_unfiltered_profile_list_desc">Include non-production profiles in the list</string>
     <string name="pref_developer_ignore_tls_certificate">Ignore SM-DP+ TLS certificate</string>

+ 6 - 0
app-common/src/main/res/xml/pref_settings.xml

@@ -57,6 +57,12 @@
         app:title="@string/pref_developer"
         app:iconSpaceReserved="false">
 
+        <CheckBoxPreference
+            app:iconSpaceReserved="false"
+            app:key="pref_developer_refresh_after_switch"
+            app:summary="@string/pref_developer_refresh_after_switch_desc"
+            app:title="@string/pref_developer_refresh_after_switch" />
+
         <CheckBoxPreference
             app:iconSpaceReserved="false"
             app:key="pref_developer_unfiltered_profile_list"