diff --git a/app-common/src/main/AndroidManifest.xml b/app-common/src/main/AndroidManifest.xml index 6edaaf1..464ae0f 100644 --- a/app-common/src/main/AndroidManifest.xml +++ b/app-common/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ + - 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") } 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/ui/wizard/DownloadWizardActivity.kt b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardActivity.kt index a9f868f..9e312d4 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardActivity.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardActivity.kt @@ -3,6 +3,7 @@ package im.angry.openeuicc.ui.wizard import android.app.assist.AssistContent import android.os.Bundle import android.view.View +import android.view.WindowManager import android.view.inputmethod.InputMethodManager import android.widget.Button import android.widget.ProgressBar @@ -251,6 +252,14 @@ class DownloadWizardActivity: BaseEuiccAccessActivity() { supportFragmentManager.beginTransaction().setCustomAnimations(enterAnim, exitAnim) .replace(R.id.step_fragment_container, nextFrag) .commit() + + // Sync screen on state + if (nextFrag.keepScreenOn) { + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } else { + window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + refreshButtons() } @@ -280,6 +289,8 @@ class DownloadWizardActivity: BaseEuiccAccessActivity() { protected val state: DownloadWizardState get() = (requireActivity() as DownloadWizardActivity).state + open val keepScreenOn = false + abstract val hasNext: Boolean abstract val hasPrev: Boolean abstract fun createNextFragment(): DownloadWizardStepFragment? diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardProgressFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardProgressFragment.kt index 1b816d4..342a687 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardProgressFragment.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/wizard/DownloadWizardProgressFragment.kt @@ -59,6 +59,9 @@ class DownloadWizardProgressFragment : DownloadWizardActivity.DownloadWizardStep private val adapter = ProgressItemAdapter() + // We don't want to turn off the screen during a download + override val keepScreenOn = true + private var isDone = false override val hasNext: Boolean 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/java/im/angry/openeuicc/util/Utils.kt b/app-common/src/main/java/im/angry/openeuicc/util/Utils.kt index 5a559f9..046657f 100644 --- a/app-common/src/main/java/im/angry/openeuicc/util/Utils.kt +++ b/app-common/src/main/java/im/angry/openeuicc/util/Utils.kt @@ -54,6 +54,9 @@ interface OpenEuiccContextMarker { val appContainer: AppContainer get() = openEuiccApplication.appContainer + val preferenceRepository: PreferenceRepository + get() = appContainer.preferenceRepository + val telephonyManager: TelephonyManager get() = appContainer.telephonyManager } diff --git a/app-common/src/main/res/values-ja/strings.xml b/app-common/src/main/res/values-ja/strings.xml index 644e564..35fd400 100644 --- a/app-common/src/main/res/values-ja/strings.xml +++ b/app-common/src/main/res/values-ja/strings.xml @@ -143,6 +143,7 @@ ログ アプリの最新デバッグログを表示します 開発者オプション + プロファイルを切り替えた後にモデムに更新コマンドを送信するかどうか。クラッシュが発生する場合は、これを無効にしてみてください。 フィルタリングされていないプロファイル一覧を表示 非運用のプロファイルも含めます SM-DP+ TLS 証明書を無視する @@ -162,4 +163,5 @@ 消去する eUICC の消去を可能にする この操作は、デフォルトでは非表示になっている危険な操作です。代わりに、すべての構成ファイルを手動で削除することもできます。 + モデムに更新コマンドを送信 diff --git a/app-common/src/main/res/values-zh-rCN/strings.xml b/app-common/src/main/res/values-zh-rCN/strings.xml index 789b532..2e069bd 100644 --- a/app-common/src/main/res/values-zh-rCN/strings.xml +++ b/app-common/src/main/res/values-zh-rCN/strings.xml @@ -145,6 +145,7 @@ 语言 选择 App 语言 开发者选项 + 切换配置文件后是否向基带发送刷新命令。如果发现崩溃,请尝试禁用此功能。 显示未经过滤的配置文件列表 在配置文件列表中包括非生产环境的配置文件 无视 SM-DP+ 的 TLS 证书 @@ -162,4 +163,5 @@ 擦除 允许擦除 eUICC 此操作是默认隐藏的危险操作。作为替代方案,您可以手动删除所有配置文件。 + 向基带发送刷新命令 \ No newline at end of file diff --git a/app-common/src/main/res/values-zh-rTW/strings.xml b/app-common/src/main/res/values-zh-rTW/strings.xml index 53be571..729893c 100644 --- a/app-common/src/main/res/values-zh-rTW/strings.xml +++ b/app-common/src/main/res/values-zh-rTW/strings.xml @@ -145,6 +145,7 @@ 語言 選擇 App 語言 開發人員選項 + 切換設定檔後是否向基帶發送刷新命令。如果發現崩潰,請嘗試停用此功能。 顯示未經過濾的設定檔列表 在設定檔列表中包括非生產環境的設定檔 忽略 SM-DP+ 的 TLS 證書 @@ -162,4 +163,5 @@ 擦除 允許擦除 eUICC 此操作是預設隱藏的危險操作。作為替代方案,您可以手動刪除所有設定檔。 + 向基帶發送刷新命令 \ 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 8146f54..a366b88 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 + Send refresh command to modem + Whether to send a refresh command to the modem after switching profiles. Try disabling this if you see crashes. 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"> + + com.android.stk/.StkMainHide com.android.stk/.StkListActivity com.android.stk/.StkLauncherListActivity + com.android.stk/.StkSelectionActivity com.android.stk/.StkMain1 com.android.stk/.PrimaryStkMain com.android.stk/.StkLauncherActivity com.android.stk/.StkLauncherActivity_Chn + com.android.stk/.StkLauncherActivity1 com.android.stk/.StkLauncherActivityI com.android.stk/.OppoStkLauncherActivity1 com.android.stk/.OplusStkLauncherActivity1 diff --git a/app/src/main/java/im/angry/openeuicc/core/PrivilegedEuiccChannelFactory.kt b/app/src/main/java/im/angry/openeuicc/core/PrivilegedEuiccChannelFactory.kt index 6dccda9..d9bceda 100644 --- a/app/src/main/java/im/angry/openeuicc/core/PrivilegedEuiccChannelFactory.kt +++ b/app/src/main/java/im/angry/openeuicc/core/PrivilegedEuiccChannelFactory.kt @@ -10,9 +10,8 @@ import java.lang.IllegalArgumentException class PrivilegedEuiccChannelFactory(context: Context) : DefaultEuiccChannelFactory(context), PrivilegedEuiccContextMarker { - private val tm by lazy { - (context.applicationContext as OpenEuiccApplication).appContainer.telephonyManager - } + override val openEuiccMarkerContext: Context + get() = context @Suppress("NAME_SHADOWING") override suspend fun tryOpenEuiccChannel(port: UiccPortInfoCompat): EuiccChannel? { @@ -35,7 +34,7 @@ class PrivilegedEuiccChannelFactory(context: Context) : DefaultEuiccChannelFacto intrinsicChannelName = null, TelephonyManagerApduInterface( port, - tm, + telephonyManager, context.preferenceRepository.verboseLoggingFlow ), context.preferenceRepository.verboseLoggingFlow, diff --git a/app/src/main/java/im/angry/openeuicc/util/PrivilegedUtils.kt b/app/src/main/java/im/angry/openeuicc/util/PrivilegedUtils.kt index 21c8002..6418581 100644 --- a/app/src/main/java/im/angry/openeuicc/util/PrivilegedUtils.kt +++ b/app/src/main/java/im/angry/openeuicc/util/PrivilegedUtils.kt @@ -10,16 +10,9 @@ import java.util.concurrent.Executors import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine -interface PrivilegedEuiccContextMarker { - val privilegedEuiccMarkerContext: Context - get() = when (this) { - is Context -> this - is Fragment -> requireContext() - else -> throw RuntimeException("PrivilegedEuiccContextMarker shall only be used on Fragments or UI types that derive from Context") - } - - val preferenceRepository: PrivilegedPreferenceRepository - get() = privilegedEuiccMarkerContext.preferenceRepository as PrivilegedPreferenceRepository +interface PrivilegedEuiccContextMarker : OpenEuiccContextMarker { + override val preferenceRepository: PrivilegedPreferenceRepository + get() = appContainer.preferenceRepository as PrivilegedPreferenceRepository } suspend fun Context.bindServiceSuspended(intent: Intent, flags: Int): Pair Unit> =