Compare commits

..

No commits in common. "0e86a922d158547aeb69c4cc3f292425cee8b973" and "ff427759d780971e53c19395ce8d0e5a78aa83c5" have entirely different histories.

3 changed files with 13 additions and 19 deletions

View file

@ -1,32 +1,18 @@
package im.angry.openeuicc.util package im.angry.openeuicc.util
import im.angry.openeuicc.core.EuiccChannel
import net.typeblog.lpac_jni.LocalProfileAssistant import net.typeblog.lpac_jni.LocalProfileAssistant
import net.typeblog.lpac_jni.LocalProfileInfo import net.typeblog.lpac_jni.LocalProfileInfo
val LocalProfileInfo.displayName: String val LocalProfileInfo.displayName: String
get() = nickName.ifEmpty { name } get() = nickName.ifEmpty { name }
val LocalProfileInfo.isEnabled: Boolean
get() = state == LocalProfileInfo.State.Enabled
val List<LocalProfileInfo>.operational: List<LocalProfileInfo> val List<LocalProfileInfo>.operational: List<LocalProfileInfo>
get() = filter { get() = filter {
it.profileClass == LocalProfileInfo.Clazz.Operational it.profileClass == LocalProfileInfo.Clazz.Operational
} }
val List<EuiccChannel>.hasMultipleChips: Boolean fun LocalProfileAssistant.disableActiveProfileWithUndo(): () -> Unit =
get() = distinctBy { it.slotId }.size > 1 profiles.find { it.state == LocalProfileInfo.State.Enabled }?.let {
disableProfile(it.iccid)
/**
* Disable the active profile, return a lambda that reverts this action when called.
* If refreshOnDisable is true, also cause a eUICC refresh command. Note that refreshing
* will disconnect the eUICC and might need some time before being operational again.
* See EuiccManager.waitForReconnect()
*/
fun LocalProfileAssistant.disableActiveProfileWithUndo(refreshOnDisable: Boolean): () -> Unit =
profiles.find { it.isEnabled }?.let {
disableProfile(it.iccid, refreshOnDisable)
return { enableProfile(it.iccid) } return { enableProfile(it.iccid) }
} ?: { } } ?: { }

View file

@ -11,12 +11,14 @@ import com.google.zxing.RGBLuminanceSource
import com.google.zxing.common.HybridBinarizer import com.google.zxing.common.HybridBinarizer
import com.google.zxing.qrcode.QRCodeReader import com.google.zxing.qrcode.QRCodeReader
import im.angry.openeuicc.OpenEuiccApplication import im.angry.openeuicc.OpenEuiccApplication
import im.angry.openeuicc.core.EuiccChannel
import im.angry.openeuicc.di.AppContainer import im.angry.openeuicc.di.AppContainer
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import net.typeblog.lpac_jni.LocalProfileInfo
import kotlin.RuntimeException import kotlin.RuntimeException
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException import kotlin.coroutines.resumeWithException
@ -58,6 +60,12 @@ interface OpenEuiccContextMarker {
get() = appContainer.telephonyManager get() = appContainer.telephonyManager
} }
val LocalProfileInfo.isEnabled: Boolean
get() = state == LocalProfileInfo.State.Enabled
val List<EuiccChannel>.hasMultipleChips: Boolean
get() = distinctBy { it.slotId }.size > 1
// Create an instance of OMAPI SEService in a manner that "makes sense" without unpredictable callbacks // Create an instance of OMAPI SEService in a manner that "makes sense" without unpredictable callbacks
suspend fun connectSEService(context: Context): SEService = suspendCoroutine { cont -> suspend fun connectSEService(context: Context): SEService = suspendCoroutine { cont ->
// Use a Mutex to make sure the continuation is run *after* the "service" variable is assigned // Use a Mutex to make sure the continuation is run *after* the "service" variable is assigned

View file

@ -22,7 +22,7 @@ fun TelephonyManager.setDsdsEnabled(euiccManager: EuiccChannelManager, enabled:
// Disable all eSIM profiles before performing a DSDS switch (only for internal eSIMs) // Disable all eSIM profiles before performing a DSDS switch (only for internal eSIMs)
knownChannels.forEach { knownChannels.forEach {
if (!it.removable) { if (!it.removable) {
it.lpa.disableActiveProfileWithUndo(false) it.lpa.disableActiveProfileWithUndo()
} }
} }
@ -45,7 +45,7 @@ fun TelephonyManager.updateSimSlotMapping(
val undo = unmapped.mapNotNull { mapping -> val undo = unmapped.mapNotNull { mapping ->
euiccManager.findEuiccChannelByPortBlocking(mapping.physicalSlotIndex, mapping.portIndex)?.let { channel -> euiccManager.findEuiccChannelByPortBlocking(mapping.physicalSlotIndex, mapping.portIndex)?.let { channel ->
if (!channel.removable) { if (!channel.removable) {
return@mapNotNull channel.lpa.disableActiveProfileWithUndo(false) return@mapNotNull channel.lpa.disableActiveProfileWithUndo()
} else { } else {
// Do not do anything for external eUICCs -- we can't really trust them to work properly // Do not do anything for external eUICCs -- we can't really trust them to work properly
// with no profile enabled. // with no profile enabled.