Compare commits

..

No commits in common. "dc6b3a4810bd05b25bd5433993cece12a79c5945" and "360760b78fbc2298c62521921f8960d82ad41242" have entirely different histories.

15 changed files with 37 additions and 80 deletions

View file

@ -7,7 +7,6 @@
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application <application
android:enableOnBackInvokedCallback="true" android:enableOnBackInvokedCallback="true"

View file

@ -4,7 +4,6 @@ import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Binder import android.os.Binder
import android.os.IBinder import android.os.IBinder
import android.os.PowerManager
import android.util.Log import android.util.Log
import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
@ -12,7 +11,6 @@ import androidx.core.app.NotificationManagerCompat
import androidx.lifecycle.LifecycleService import androidx.lifecycle.LifecycleService
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import im.angry.openeuicc.common.R import im.angry.openeuicc.common.R
import im.angry.openeuicc.core.EuiccChannel
import im.angry.openeuicc.core.EuiccChannelManager import im.angry.openeuicc.core.EuiccChannelManager
import im.angry.openeuicc.util.* import im.angry.openeuicc.util.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -93,12 +91,6 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker {
} }
val euiccChannelManager: EuiccChannelManager by euiccChannelManagerDelegate val euiccChannelManager: EuiccChannelManager by euiccChannelManagerDelegate
private val wakeLock: PowerManager.WakeLock by lazy {
(getSystemService(POWER_SERVICE) as PowerManager).run {
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this::class.simpleName)
}
}
/** /**
* The state of a "foreground" task (named so due to the need to startForeground()) * The state of a "foreground" task (named so due to the need to startForeground())
*/ */
@ -283,8 +275,6 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker {
updateForegroundNotification(title, iconRes) updateForegroundNotification(title, iconRes)
wakeLock.acquire(10 * 60 * 1000L /*10 minutes*/)
try { try {
withContext(Dispatchers.IO + NonCancellable) { // Any LPA-related task must always complete withContext(Dispatchers.IO + NonCancellable) { // Any LPA-related task must always complete
this@EuiccChannelManagerService.task() this@EuiccChannelManagerService.task()
@ -300,7 +290,6 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker {
postForegroundTaskFailureNotification(failureTitle) postForegroundTaskFailureNotification(failureTitle)
} }
} finally { } finally {
wakeLock.release()
if (isActive) { if (isActive) {
stopSelf() stopSelf()
} }
@ -457,34 +446,30 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker {
iccid: String, iccid: String,
enable: Boolean, // Enable or disable the profile indicated in iccid enable: Boolean, // Enable or disable the profile indicated in iccid
reconnectTimeoutMillis: Long = 0 // 0 = do not wait for reconnect reconnectTimeoutMillis: Long = 0 // 0 = do not wait for reconnect
) = ): ForegroundTaskSubscriberFlow =
launchForegroundTask( launchForegroundTask(
getString(R.string.task_profile_switch), getString(R.string.task_profile_switch),
getString(R.string.task_profile_switch_failure), getString(R.string.task_profile_switch_failure),
R.drawable.ic_task_switch R.drawable.ic_task_switch
) { ) {
euiccChannelManager.beginTrackedOperation(slotId, portId) { euiccChannelManager.beginTrackedOperation(slotId, portId) {
val (response, refreshed) = val (res, refreshed) = euiccChannelManager.withEuiccChannel(
euiccChannelManager.withEuiccChannel(slotId, portId) { channel -> slotId,
val refresh = preferenceRepository.refreshAfterSwitchFlow.first() portId
val response = channel.lpa.switchProfile(iccid, enable, refresh) ) { channel ->
if (response || !refresh) { if (!channel.lpa.switchProfile(iccid, enable, refresh = true)) {
Pair(response, refresh) // Sometimes, we *can* enable or disable the profile, but we cannot
} else { // send the refresh command to the modem because the profile somehow
// refresh failed, but refresh was requested // makes the modem "busy". In this case, we can still switch by setting
// Sometimes, we *can* enable or disable the profile, but we cannot // refresh to false, but then the switch cannot take effect until the
// send the refresh command to the modem because the profile somehow // user resets the modem manually by toggling airplane mode or rebooting.
// makes the modem "busy". In this case, we can still switch by setting Pair(channel.lpa.switchProfile(iccid, enable, refresh = false), false)
// refresh to false, but then the switch cannot take effect until the } else {
// user resets the modem manually by toggling airplane mode or rebooting. Pair(true, true)
Pair(
channel.lpa.switchProfile(iccid, enable, refresh = false),
false
)
}
} }
}
if (!response) { if (!res) {
throw RuntimeException("Could not switch profile") throw RuntimeException("Could not switch profile")
} }

View file

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

View file

@ -3,7 +3,6 @@ package im.angry.openeuicc.ui.wizard
import android.app.assist.AssistContent import android.app.assist.AssistContent
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.Button import android.widget.Button
import android.widget.ProgressBar import android.widget.ProgressBar
@ -252,14 +251,6 @@ class DownloadWizardActivity: BaseEuiccAccessActivity() {
supportFragmentManager.beginTransaction().setCustomAnimations(enterAnim, exitAnim) supportFragmentManager.beginTransaction().setCustomAnimations(enterAnim, exitAnim)
.replace(R.id.step_fragment_container, nextFrag) .replace(R.id.step_fragment_container, nextFrag)
.commit() .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() refreshButtons()
} }
@ -289,8 +280,6 @@ class DownloadWizardActivity: BaseEuiccAccessActivity() {
protected val state: DownloadWizardState protected val state: DownloadWizardState
get() = (requireActivity() as DownloadWizardActivity).state get() = (requireActivity() as DownloadWizardActivity).state
open val keepScreenOn = false
abstract val hasNext: Boolean abstract val hasNext: Boolean
abstract val hasPrev: Boolean abstract val hasPrev: Boolean
abstract fun createNextFragment(): DownloadWizardStepFragment? abstract fun createNextFragment(): DownloadWizardStepFragment?

View file

@ -59,9 +59,6 @@ class DownloadWizardProgressFragment : DownloadWizardActivity.DownloadWizardStep
private val adapter = ProgressItemAdapter() private val adapter = ProgressItemAdapter()
// We don't want to turn off the screen during a download
override val keepScreenOn = true
private var isDone = false private var isDone = false
override val hasNext: Boolean override val hasNext: Boolean

View file

@ -31,7 +31,6 @@ internal object PreferenceKeys {
// ---- Developer Options ---- // ---- Developer Options ----
val DEVELOPER_OPTIONS_ENABLED = booleanPreferencesKey("developer_options_enabled") 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 UNFILTERED_PROFILE_LIST = booleanPreferencesKey("unfiltered_profile_list")
val IGNORE_TLS_CERTIFICATE = booleanPreferencesKey("ignore_tls_certificate") val IGNORE_TLS_CERTIFICATE = booleanPreferencesKey("ignore_tls_certificate")
val EUICC_MEMORY_RESET = booleanPreferencesKey("euicc_memory_reset") val EUICC_MEMORY_RESET = booleanPreferencesKey("euicc_memory_reset")
@ -49,7 +48,6 @@ open class PreferenceRepository(private val context: Context) {
val verboseLoggingFlow = bindFlow(PreferenceKeys.VERBOSE_LOGGING, false) val verboseLoggingFlow = bindFlow(PreferenceKeys.VERBOSE_LOGGING, false)
// ---- Developer Options ---- // ---- Developer Options ----
val refreshAfterSwitchFlow = bindFlow(PreferenceKeys.REFRESH_AFTER_SWITCH, true)
val developerOptionsEnabledFlow = bindFlow(PreferenceKeys.DEVELOPER_OPTIONS_ENABLED, false) val developerOptionsEnabledFlow = bindFlow(PreferenceKeys.DEVELOPER_OPTIONS_ENABLED, false)
val unfilteredProfileListFlow = bindFlow(PreferenceKeys.UNFILTERED_PROFILE_LIST, false) val unfilteredProfileListFlow = bindFlow(PreferenceKeys.UNFILTERED_PROFILE_LIST, false)
val ignoreTLSCertificateFlow = bindFlow(PreferenceKeys.IGNORE_TLS_CERTIFICATE, false) val ignoreTLSCertificateFlow = bindFlow(PreferenceKeys.IGNORE_TLS_CERTIFICATE, false)
@ -62,10 +60,13 @@ open class PreferenceRepository(private val context: Context) {
class PreferenceFlowWrapper<T> private constructor( class PreferenceFlowWrapper<T> private constructor(
private val context: Context, private val context: Context,
private val key: Preferences.Key<T>, private val key: Preferences.Key<T>,
inner: Flow<T>, inner: Flow<T>
) : Flow<T> by inner { ) : Flow<T> by inner {
internal constructor(context: Context, key: Preferences.Key<T>, defaultValue: T) : internal constructor(context: Context, key: Preferences.Key<T>, defaultValue: T) : this(
this(context, key, context.dataStore.data.map { it[key] ?: defaultValue }) context,
key,
context.dataStore.data.map { it[key] ?: defaultValue }
)
suspend fun updatePreference(value: T) { suspend fun updatePreference(value: T) {
context.dataStore.edit { it[key] = value } context.dataStore.edit { it[key] = value }

View file

@ -54,9 +54,6 @@ interface OpenEuiccContextMarker {
val appContainer: AppContainer val appContainer: AppContainer
get() = openEuiccApplication.appContainer get() = openEuiccApplication.appContainer
val preferenceRepository: PreferenceRepository
get() = appContainer.preferenceRepository
val telephonyManager: TelephonyManager val telephonyManager: TelephonyManager
get() = appContainer.telephonyManager get() = appContainer.telephonyManager
} }

View file

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

View file

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

View file

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

View file

@ -181,8 +181,6 @@
<string name="pref_advanced_logs">Logs</string> <string name="pref_advanced_logs">Logs</string>
<string name="pref_advanced_logs_desc">View recent debug logs of the application</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">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">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_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> <string name="pref_developer_ignore_tls_certificate">Ignore SM-DP+ TLS certificate</string>

View file

@ -57,12 +57,6 @@
app:title="@string/pref_developer" app:title="@string/pref_developer"
app:iconSpaceReserved="false"> 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 <CheckBoxPreference
app:iconSpaceReserved="false" app:iconSpaceReserved="false"
app:key="pref_developer_unfiltered_profile_list" app:key="pref_developer_unfiltered_profile_list"

View file

@ -5,14 +5,12 @@
<item>com.android.stk/.StkMainHide</item> <item>com.android.stk/.StkMainHide</item>
<item>com.android.stk/.StkListActivity</item> <item>com.android.stk/.StkListActivity</item>
<item>com.android.stk/.StkLauncherListActivity</item> <item>com.android.stk/.StkLauncherListActivity</item>
<item>com.android.stk/.StkSelectionActivity</item>
</string-array> </string-array>
<string-array name="sim_toolkit_slot_1"> <string-array name="sim_toolkit_slot_1">
<item>com.android.stk/.StkMain1</item> <item>com.android.stk/.StkMain1</item>
<item>com.android.stk/.PrimaryStkMain</item> <item>com.android.stk/.PrimaryStkMain</item>
<item>com.android.stk/.StkLauncherActivity</item> <item>com.android.stk/.StkLauncherActivity</item>
<item>com.android.stk/.StkLauncherActivity_Chn</item> <item>com.android.stk/.StkLauncherActivity_Chn</item>
<item>com.android.stk/.StkLauncherActivity1</item>
<item>com.android.stk/.StkLauncherActivityI</item> <item>com.android.stk/.StkLauncherActivityI</item>
<item>com.android.stk/.OppoStkLauncherActivity1</item> <item>com.android.stk/.OppoStkLauncherActivity1</item>
<item>com.android.stk/.OplusStkLauncherActivity1</item> <item>com.android.stk/.OplusStkLauncherActivity1</item>

View file

@ -10,8 +10,9 @@ import java.lang.IllegalArgumentException
class PrivilegedEuiccChannelFactory(context: Context) : DefaultEuiccChannelFactory(context), class PrivilegedEuiccChannelFactory(context: Context) : DefaultEuiccChannelFactory(context),
PrivilegedEuiccContextMarker { PrivilegedEuiccContextMarker {
override val openEuiccMarkerContext: Context private val tm by lazy {
get() = context (context.applicationContext as OpenEuiccApplication).appContainer.telephonyManager
}
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
override suspend fun tryOpenEuiccChannel(port: UiccPortInfoCompat): EuiccChannel? { override suspend fun tryOpenEuiccChannel(port: UiccPortInfoCompat): EuiccChannel? {
@ -34,7 +35,7 @@ class PrivilegedEuiccChannelFactory(context: Context) : DefaultEuiccChannelFacto
intrinsicChannelName = null, intrinsicChannelName = null,
TelephonyManagerApduInterface( TelephonyManagerApduInterface(
port, port,
telephonyManager, tm,
context.preferenceRepository.verboseLoggingFlow context.preferenceRepository.verboseLoggingFlow
), ),
context.preferenceRepository.verboseLoggingFlow, context.preferenceRepository.verboseLoggingFlow,

View file

@ -10,9 +10,16 @@ import java.util.concurrent.Executors
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.suspendCoroutine
interface PrivilegedEuiccContextMarker : OpenEuiccContextMarker { interface PrivilegedEuiccContextMarker {
override val preferenceRepository: PrivilegedPreferenceRepository val privilegedEuiccMarkerContext: Context
get() = appContainer.preferenceRepository as PrivilegedPreferenceRepository 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
} }
suspend fun Context.bindServiceSuspended(intent: Intent, flags: Int): Pair<IBinder?, () -> Unit> = suspend fun Context.bindServiceSuspended(intent: Intent, flags: Int): Pair<IBinder?, () -> Unit> =