OpenEuiccService: Start migrating to withEuiccChannel()
All checks were successful
/ build-debug (push) Successful in 6m30s

This commit is contained in:
Peter Cai 2024-11-03 10:53:24 -05:00
commit 22ec3e3baf
3 changed files with 77 additions and 35 deletions

View file

@ -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,

View file

@ -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")
/**

View file

@ -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 {