Compare commits
2 commits
ff427759d7
...
0e86a922d1
Author | SHA1 | Date | |
---|---|---|---|
0e86a922d1 | |||
2b3f042e39 |
3 changed files with 19 additions and 13 deletions
|
@ -1,18 +1,32 @@
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
fun LocalProfileAssistant.disableActiveProfileWithUndo(): () -> Unit =
|
val List<EuiccChannel>.hasMultipleChips: Boolean
|
||||||
profiles.find { it.state == LocalProfileInfo.State.Enabled }?.let {
|
get() = distinctBy { it.slotId }.size > 1
|
||||||
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) }
|
||||||
} ?: { }
|
} ?: { }
|
|
@ -11,14 +11,12 @@ 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
|
||||||
|
@ -60,12 +58,6 @@ 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
|
||||||
|
|
|
@ -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()
|
it.lpa.disableActiveProfileWithUndo(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
return@mapNotNull channel.lpa.disableActiveProfileWithUndo(false)
|
||||||
} 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.
|
||||||
|
|
Loading…
Add table
Reference in a new issue