ソースを参照

OpenEuiccService: Start migrating to withEuiccChannel()

Peter Cai 1 年間 前
コミット
22ec3e3baf

+ 9 - 0
app-common/src/main/java/im/angry/openeuicc/core/DefaultEuiccChannelManager.kt

@@ -165,6 +165,15 @@ open class DefaultEuiccChannelManager(
             findEuiccChannelByPort(physicalSlotId, portId)
         }
 
+    override suspend fun findFirstAvailablePort(physicalSlotId: Int): Int =
+        withContext(Dispatchers.IO) {
+            if (physicalSlotId == EuiccChannelManager.USB_CHANNEL_ID) {
+                return@withContext 0
+            }
+
+            findAllEuiccChannelsByPhysicalSlot(physicalSlotId)?.getOrNull(0)?.portId ?: -1
+        }
+
     override suspend fun <R> withEuiccChannel(
         physicalSlotId: Int,
         portId: Int,

+ 6 - 0
app-common/src/main/java/im/angry/openeuicc/core/EuiccChannelManager.kt

@@ -72,6 +72,12 @@ interface EuiccChannelManager {
     suspend fun findEuiccChannelByPort(physicalSlotId: Int, portId: Int): EuiccChannel?
     fun findEuiccChannelByPortBlocking(physicalSlotId: Int, portId: Int): EuiccChannel?
 
+    /**
+     * Returns the first mapped & available port ID for a physical slot, or -1 if
+     * not found.
+     */
+    suspend fun findFirstAvailablePort(physicalSlotId: Int): Int
+
     class EuiccChannelNotFoundException: Exception("EuiccChannel not found")
 
     /**

+ 62 - 35
app/src/main/java/im/angry/openeuicc/service/OpenEuiccService.kt

@@ -13,6 +13,7 @@ import im.angry.openeuicc.core.EuiccChannel
 import im.angry.openeuicc.core.EuiccChannelManager
 import im.angry.openeuicc.util.*
 import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.last
 import kotlinx.coroutines.runBlocking
 import java.lang.IllegalStateException
 
@@ -37,8 +38,11 @@ class OpenEuiccService : EuiccService(), OpenEuiccContextMarker {
         }
 
     private data class EuiccChannelManagerContext(
-        val euiccChannelManager: EuiccChannelManager
+        val euiccChannelManagerService: EuiccChannelManagerService
     ) {
+        val euiccChannelManager
+            get() = euiccChannelManagerService.euiccChannelManager
+
         fun findChannel(physicalSlotId: Int): EuiccChannel? =
             euiccChannelManager.findEuiccChannelByPhysicalSlotBlocking(physicalSlotId)
 
@@ -59,7 +63,7 @@ class OpenEuiccService : EuiccService(), OpenEuiccContextMarker {
      *
      * This function cannot be inline because non-local returns may bypass the unbind
      */
-    private fun <T> withEuiccChannelManager(fn: EuiccChannelManagerContext.() -> T): T {
+    private fun <T> withEuiccChannelManager(fn: suspend EuiccChannelManagerContext.() -> T): T {
         val (binder, unbind) = runBlocking {
             bindServiceSuspended(
                 Intent(
@@ -73,8 +77,11 @@ class OpenEuiccService : EuiccService(), OpenEuiccContextMarker {
             throw RuntimeException("Unable to bind to EuiccChannelManagerService; aborting")
         }
 
-        val ret =
-            EuiccChannelManagerContext((binder as EuiccChannelManagerService.LocalBinder).service.euiccChannelManager).fn()
+        val localBinder = binder as EuiccChannelManagerService.LocalBinder
+
+        val ret = runBlocking {
+            EuiccChannelManagerContext(localBinder.service).fn()
+        }
 
         unbind()
         return ret
@@ -177,38 +184,54 @@ class OpenEuiccService : EuiccService(), OpenEuiccContextMarker {
         }
 
         // TODO: Temporarily enable the slot to access its profiles if it is currently unmapped
-        val channel =
-            findChannel(slotId) ?: return@withEuiccChannelManager GetEuiccProfileInfoListResult(
+        val port = euiccChannelManager.findFirstAvailablePort(slotId)
+        if (port == -1) {
+            return@withEuiccChannelManager GetEuiccProfileInfoListResult(
                 RESULT_FIRST_USER,
                 arrayOf(),
                 true
             )
-        val profiles = channel.lpa.profiles.operational.map {
-            EuiccProfileInfo.Builder(it.iccid).apply {
-                setProfileName(it.name)
-                setNickname(it.displayName)
-                setServiceProviderName(it.providerName)
-                setState(
-                    when (it.state) {
-                        LocalProfileInfo.State.Enabled -> EuiccProfileInfo.PROFILE_STATE_ENABLED
-                        LocalProfileInfo.State.Disabled -> EuiccProfileInfo.PROFILE_STATE_DISABLED
-                    }
-                )
-                setProfileClass(
-                    when (it.profileClass) {
-                        LocalProfileInfo.Clazz.Testing -> EuiccProfileInfo.PROFILE_CLASS_TESTING
-                        LocalProfileInfo.Clazz.Provisioning -> EuiccProfileInfo.PROFILE_CLASS_PROVISIONING
-                        LocalProfileInfo.Clazz.Operational -> EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL
-                    }
-                )
-            }.build()
         }
 
-        return@withEuiccChannelManager GetEuiccProfileInfoListResult(
-            RESULT_OK,
-            profiles.toTypedArray(),
-            channel.port.card.isRemovable
-        )
+        try {
+            return@withEuiccChannelManager euiccChannelManager.withEuiccChannel(
+                slotId,
+                port
+            ) { channel ->
+                val profiles = channel.lpa.profiles.operational.map {
+                    EuiccProfileInfo.Builder(it.iccid).apply {
+                        setProfileName(it.name)
+                        setNickname(it.displayName)
+                        setServiceProviderName(it.providerName)
+                        setState(
+                            when (it.state) {
+                                LocalProfileInfo.State.Enabled -> EuiccProfileInfo.PROFILE_STATE_ENABLED
+                                LocalProfileInfo.State.Disabled -> EuiccProfileInfo.PROFILE_STATE_DISABLED
+                            }
+                        )
+                        setProfileClass(
+                            when (it.profileClass) {
+                                LocalProfileInfo.Clazz.Testing -> EuiccProfileInfo.PROFILE_CLASS_TESTING
+                                LocalProfileInfo.Clazz.Provisioning -> EuiccProfileInfo.PROFILE_CLASS_PROVISIONING
+                                LocalProfileInfo.Clazz.Operational -> EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL
+                            }
+                        )
+                    }.build()
+                }
+
+                GetEuiccProfileInfoListResult(
+                    RESULT_OK,
+                    profiles.toTypedArray(),
+                    channel.port.card.isRemovable
+                )
+            }
+        } catch (e: EuiccChannelManager.EuiccChannelNotFoundException) {
+            return@withEuiccChannelManager GetEuiccProfileInfoListResult(
+                RESULT_FIRST_USER,
+                arrayOf(),
+                true
+            )
+        }
     }
 
     override fun onGetEuiccInfo(slotId: Int): EuiccInfo {
@@ -335,13 +358,17 @@ class OpenEuiccService : EuiccService(), OpenEuiccContextMarker {
                 "onUpdateSubscriptionNickname slotId=$slotId iccid=$iccid nickname=$nickname"
             )
             if (shouldIgnoreSlot(slotId)) return@withEuiccChannelManager RESULT_FIRST_USER
-            val channel = findChannel(slotId) ?: return@withEuiccChannelManager RESULT_FIRST_USER
-            if (!channel.profileExists(iccid)) {
+            val port = euiccChannelManager.findFirstAvailablePort(slotId)
+            if (port < 0) {
                 return@withEuiccChannelManager RESULT_FIRST_USER
             }
-            val success = channel.lpa
-                .setNickname(iccid, nickname!!)
-            appContainer.subscriptionManager.tryRefreshCachedEuiccInfo(channel.cardId)
+            val success =
+                (euiccChannelManagerService.launchProfileRenameTask(slotId, port, iccid, nickname!!)
+                    ?.last() as? EuiccChannelManagerService.ForegroundTaskState.Done)?.error == null
+
+            euiccChannelManager.withEuiccChannel(slotId, port) { channel ->
+                appContainer.subscriptionManager.tryRefreshCachedEuiccInfo(channel.cardId)
+            }
             return@withEuiccChannelManager if (success) {
                 RESULT_OK
             } else {