Browse Source

feat: Allow forcing the use of TelephonyManager everywhere

Manual merge of #139, but removed all reference to "TMAPI" because such
a term does not exist.

Also reworked PreferenceRepository to allow extensibility from the
privileged app.
septs 11 months ago
parent
commit
17102be7cb

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

@@ -122,7 +122,7 @@ open class SettingsFragment: PreferenceFragmentCompat() {
         return true
     }
 
-    private fun CheckBoxPreference.bindBooleanFlow(flow: PreferenceFlowWrapper<Boolean>) {
+    protected fun CheckBoxPreference.bindBooleanFlow(flow: PreferenceFlowWrapper<Boolean>) {
         lifecycleScope.launch {
             flow.collect { isChecked = it }
         }

+ 2 - 2
app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt

@@ -35,7 +35,7 @@ internal object PreferenceKeys {
     val IGNORE_TLS_CERTIFICATE = booleanPreferencesKey("ignore_tls_certificate")
 }
 
-class PreferenceRepository(private val context: Context) {
+open class PreferenceRepository(private val context: Context) {
     // Expose flows so that we can also handle default values
     // ---- Profile Notifications ----
     val notificationDownloadFlow = bindFlow(PreferenceKeys.NOTIFICATION_DOWNLOAD, true)
@@ -51,7 +51,7 @@ class PreferenceRepository(private val context: Context) {
     val unfilteredProfileListFlow = bindFlow(PreferenceKeys.UNFILTERED_PROFILE_LIST, false)
     val ignoreTLSCertificateFlow = bindFlow(PreferenceKeys.IGNORE_TLS_CERTIFICATE, false)
 
-    private fun <T> bindFlow(key: Preferences.Key<T>, defaultValue: T): PreferenceFlowWrapper<T> =
+    protected fun <T> bindFlow(key: Preferences.Key<T>, defaultValue: T): PreferenceFlowWrapper<T> =
         PreferenceFlowWrapper(context, key, defaultValue)
 }
 

+ 2 - 2
app-common/src/main/res/xml/pref_settings.xml

@@ -52,7 +52,7 @@
 
     </PreferenceCategory>
 
-    <PreferenceCategory
+    <im.angry.openeuicc.ui.preference.LongSummaryPreferenceCategory
         app:key="pref_developer"
         app:title="@string/pref_developer"
         app:iconSpaceReserved="false">
@@ -69,7 +69,7 @@
             app:summary="@string/pref_developer_ignore_tls_certificate_desc"
             app:title="@string/pref_developer_ignore_tls_certificate" />
 
-    </PreferenceCategory>
+    </im.angry.openeuicc.ui.preference.LongSummaryPreferenceCategory>
 
     <PreferenceCategory
         app:key="pref_info"

+ 2 - 1
app/src/main/java/im/angry/openeuicc/core/PrivilegedEuiccChannelFactory.kt

@@ -5,6 +5,7 @@ import android.util.Log
 import im.angry.openeuicc.OpenEuiccApplication
 import im.angry.openeuicc.R
 import im.angry.openeuicc.util.*
+import kotlinx.coroutines.flow.first
 import java.lang.IllegalArgumentException
 
 class PrivilegedEuiccChannelFactory(context: Context) : DefaultEuiccChannelFactory(context) {
@@ -21,7 +22,7 @@ class PrivilegedEuiccChannelFactory(context: Context) : DefaultEuiccChannelFacto
             super.tryOpenEuiccChannel(port)?.let { return it }
         }
 
-        if (port.card.isEuicc) {
+        if (port.card.isEuicc || (context.preferenceRepository as PrivilegedPreferenceRepository).removableTelephonyManagerFlow.first()) {
             Log.i(
                 DefaultEuiccChannelManager.TAG,
                 "Trying TelephonyManager for slot ${port.card.physicalSlotIndex} port ${port.portIndex}"

+ 5 - 0
app/src/main/java/im/angry/openeuicc/di/PrivilegedAppContainer.kt

@@ -6,6 +6,7 @@ import im.angry.openeuicc.core.EuiccChannelManagerFactory
 import im.angry.openeuicc.core.PrivilegedEuiccChannelFactory
 import im.angry.openeuicc.core.PrivilegedEuiccChannelManager
 import im.angry.openeuicc.core.PrivilegedEuiccChannelManagerFactory
+import im.angry.openeuicc.util.*
 
 class PrivilegedAppContainer(context: Context) : DefaultAppContainer(context) {
     override val euiccChannelManager: EuiccChannelManager by lazy {
@@ -27,4 +28,8 @@ class PrivilegedAppContainer(context: Context) : DefaultAppContainer(context) {
     override val customizableTextProvider by lazy {
         PrivilegedCustomizableTextProvider(context)
     }
+
+    override val preferenceRepository by lazy {
+        PrivilegedPreferenceRepository(context)
+    }
 }

+ 10 - 0
app/src/main/java/im/angry/openeuicc/ui/PrivilegedSettingsFragment.kt

@@ -1,11 +1,17 @@
 package im.angry.openeuicc.ui
 
 import android.os.Bundle
+import androidx.preference.CheckBoxPreference
 import androidx.preference.Preference
+import im.angry.openeuicc.R
+import im.angry.openeuicc.util.*
 
 class PrivilegedSettingsFragment : SettingsFragment() {
     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
         super.onCreatePreferences(savedInstanceState, rootKey)
+        addPreferencesFromResource(R.xml.pref_privileged_settings)
+        mergePreferenceOverlay("pref_developer_overlay", "pref_developer")
+
         // It's stupid to _disable_ things for privileged, but for now, the per-app locale picker
         // is not usable for apps signed with the platform key.
         // ref: <https://android.googlesource.com/platform/packages/apps/Settings/+/refs/tags/android-15.0.0_r6/src/com/android/settings/applications/AppLocaleUtil.java#60>
@@ -13,5 +19,9 @@ class PrivilegedSettingsFragment : SettingsFragment() {
         // eventually work for platform-signed apps. Or, at some point we might introduce our own
         // locale picker, which hopefully works whether privileged or not.
         requirePreference<Preference>("pref_advanced_language").isVisible = false
+
+        // Force use TelephonyManager API
+        requirePreference<CheckBoxPreference>("pref_developer_tmapi_removable")
+            .bindBooleanFlow((preferenceRepository as PrivilegedPreferenceRepository).removableTelephonyManagerFlow)
     }
 }

+ 15 - 0
app/src/main/java/im/angry/openeuicc/util/PrivilegedPreferenceRepository.kt

@@ -0,0 +1,15 @@
+package im.angry.openeuicc.util
+
+import android.content.Context
+import androidx.datastore.preferences.core.booleanPreferencesKey
+
+internal object PrivilegedPreferenceKeys {
+    // ---- Developer Options ----
+    val REMOVABLE_TELEPHONY_MANAGER = booleanPreferencesKey("removable_telephony_manager")
+}
+
+class PrivilegedPreferenceRepository(context: Context) : PreferenceRepository(context) {
+    // ---- Developer Options ----
+    val removableTelephonyManagerFlow =
+        bindFlow(PrivilegedPreferenceKeys.REMOVABLE_TELEPHONY_MANAGER, false)
+}

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

@@ -17,4 +17,6 @@
     <string name="lui_desc">使用しているデバイスは eSIM をサポートしています。モバイルネットワークに接続するには通信事業者が発行した eSIM をダウンロードするか、物理 SIM を挿入してください。</string>
     <string name="lui_skip">スキップ</string>
     <string name="lui_download">eSIM をダウンロード</string>
+    <string name="pref_developer_telephony_manager_removable">TelephonyManagerをどこでも使用</string>
+    <string name="pref_developer_telephony_manager_removable_desc">デフォルトでは、非特権モード (EasyEUICC) と一致するように、取り外し可能な eUICC に対して OMAPI のみが試行されます。これは、一部のデバイスではうまく機能しない可能性があります。このオプションを選択する場合、取り外し可能な eUICC でも TelephonyManager を使用することになります。</string>
 </resources>

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

@@ -17,4 +17,6 @@
     <string name="lui_skip">跳过</string>
     <string name="lui_download">下载 eSIM</string>
     <string name="telephony_manager">TelephonyManager (特权)</string>
+    <string name="pref_developer_telephony_manager_removable">全局使用 TelephonyManager</string>
+    <string name="pref_developer_telephony_manager_removable_desc">在默认情况下,可移除 eUICC 将仅使用 OMAPI。这与非特权模式 (EasyEUICC) 一致。在某些设备上 OMAPI 可能存在问题 -- 选择此选项以强制使用 TelephonyManager。</string>
 </resources>

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

@@ -17,4 +17,6 @@
     <string name="lui_skip">跳過</string>
     <string name="lui_download">下載 eSIM</string>
     <string name="telephony_manager">TelephonyManager (特權)</string>
+    <string name="pref_developer_telephony_manager_removable">全域使用 TelephonyManager</string>
+    <string name="pref_developer_telephony_manager_removable_desc">在預設情況下,可移除 eUICC 將僅使用 OMAPI。這與非特權模式 (EasyEUICC) 一致。在某些裝置上 OMAPI 可能有問題 -- 選擇此選項以強制使用 TelephonyManager。</string>
 </resources>

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

@@ -22,4 +22,8 @@
     <string name="lui_desc">Your device supports eSIMs. To connect to mobile network, download your eSIM issued by a carrier, or insert a physical SIM.</string>
     <string name="lui_skip">Skip</string>
     <string name="lui_download">Download eSIM</string>
+
+    <!-- Preference -->
+    <string name="pref_developer_telephony_manager_removable">Use TelephonyManager everywhere</string>
+    <string name="pref_developer_telephony_manager_removable_desc">By default, only OMAPI is attempted for removable eUICCs to match what is done in unprivileged mode (i.e. EasyEUICC). This may not work well on some devices. Select this option to force the use of TelephonyManager even for removable eUICCs.</string>
 </resources>

+ 12 - 0
app/src/main/res/xml/pref_privileged_settings.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
+    <PreferenceCategory
+        app:isPreferenceVisible="false"
+        app:key="pref_developer_overlay">
+        <CheckBoxPreference
+            app:iconSpaceReserved="false"
+            app:key="pref_developer_tmapi_removable"
+            app:summary="@string/pref_developer_telephony_manager_removable_desc"
+            app:title="@string/pref_developer_telephony_manager_removable" />
+    </PreferenceCategory>
+</PreferenceScreen>