浏览代码

SlotMappingFragment: Disable profiles on unmapped slots

Peter Cai 2 年之前
父节点
当前提交
d4b875c808

+ 3 - 1
app/src/main/java/im/angry/openeuicc/ui/SlotMappingFragment.kt

@@ -98,7 +98,9 @@ class SlotMappingFragment: DialogFragment(), OnMenuItemClickListener {
         lifecycleScope.launch(Dispatchers.Main) {
         lifecycleScope.launch(Dispatchers.Main) {
             try {
             try {
                 withContext(Dispatchers.IO) {
                 withContext(Dispatchers.IO) {
-                    tm.simSlotMapping = adapter.mappings
+                    // Use the utility method from PrivilegedTelephonyUtils to ensure
+                    // unmapped ports have all profiles disabled
+                    tm.updateSimSlotMapping(openEuiccApplication.euiccChannelManager, adapter.mappings)
                 }
                 }
             } catch (e: Exception) {
             } catch (e: Exception) {
                 Toast.makeText(requireContext(), R.string.slot_mapping_failure, Toast.LENGTH_LONG).show()
                 Toast.makeText(requireContext(), R.string.slot_mapping_failure, Toast.LENGTH_LONG).show()

+ 31 - 0
app/src/main/java/im/angry/openeuicc/util/PrivilegedTelephonyUtils.kt

@@ -2,6 +2,9 @@ package im.angry.openeuicc.util
 
 
 import android.telephony.SubscriptionManager
 import android.telephony.SubscriptionManager
 import android.telephony.TelephonyManager
 import android.telephony.TelephonyManager
+import android.telephony.UiccSlotMapping
+import im.angry.openeuicc.core.EuiccChannelManager
+import net.typeblog.lpac_jni.LocalProfileInfo
 import java.lang.Exception
 import java.lang.Exception
 
 
 val TelephonyManager.supportsDSDS: Boolean
 val TelephonyManager.supportsDSDS: Boolean
@@ -13,6 +16,34 @@ var TelephonyManager.dsdsEnabled: Boolean
         switchMultiSimConfig(if (value) { 2 } else {1})
         switchMultiSimConfig(if (value) { 2 } else {1})
     }
     }
 
 
+// Disable eSIM profiles before switching the slot mapping
+// This ensures that unmapped eSIM ports never have "ghost" profiles enabled
+fun TelephonyManager.updateSimSlotMapping(euiccManager: EuiccChannelManager, newMapping: Collection<UiccSlotMapping>) {
+    val unmapped = simSlotMapping.filterNot { mapping ->
+        // If the same physical slot + port pair is not found in the new mapping, it is unmapped
+        newMapping.any {
+            it.physicalSlotIndex == mapping.physicalSlotIndex && it.portIndex == mapping.portIndex
+        }
+    }
+
+    val undo = unmapped.mapNotNull { mapping ->
+        euiccManager.findEuiccChannelByPortBlocking(mapping.physicalSlotIndex, mapping.portIndex)?.let { channel ->
+            channel.lpa.profiles.find { it.state == LocalProfileInfo.State.Enabled }?.let { profile ->
+                channel.lpa.disableProfile(profile.iccid)
+                return@mapNotNull { channel.lpa.enableProfile(profile.iccid) }
+            }
+        }
+    }
+
+    try {
+        simSlotMapping = newMapping
+    } catch (e: Exception) {
+        e.printStackTrace()
+        undo.forEach { it() } // Undo what we just did
+        throw e // Rethrow for caller to handle
+    }
+}
+
 fun SubscriptionManager.tryRefreshCachedEuiccInfo(cardId: Int) {
 fun SubscriptionManager.tryRefreshCachedEuiccInfo(cardId: Int) {
     if (cardId != 0) {
     if (cardId != 0) {
         try {
         try {