forked from PeterCxy/OpenEUICC
Compare commits
11 commits
43f247a71b
...
d0b3d54c66
Author | SHA1 | Date | |
---|---|---|---|
d0b3d54c66 | |||
3a860601a3 | |||
6b4723daee | |||
3ef78a23db | |||
31d595a6b1 | |||
e7ef370e46 | |||
653a7b32ee | |||
0f8749ee04 | |||
c0a6917645 | |||
6e3176668a | |||
66bee041a0 |
19 changed files with 107 additions and 38 deletions
|
@ -0,0 +1,5 @@
|
||||||
|
package im.angry.openeuicc.core
|
||||||
|
|
||||||
|
interface ApduInterfaceAtrProvider {
|
||||||
|
val atr: ByteArray?
|
||||||
|
}
|
|
@ -184,20 +184,30 @@ open class DefaultEuiccChannelManager(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun waitForReconnect(physicalSlotId: Int, portId: Int, timeoutMillis: Long) {
|
override suspend fun waitForReconnect(physicalSlotId: Int, portId: Int, timeoutMillis: Long) {
|
||||||
if (physicalSlotId == EuiccChannelManager.USB_CHANNEL_ID) return
|
if (physicalSlotId == EuiccChannelManager.USB_CHANNEL_ID) {
|
||||||
|
usbChannel?.close()
|
||||||
|
usbChannel = null
|
||||||
|
} else {
|
||||||
// If there is already a valid channel, we close it proactively
|
// If there is already a valid channel, we close it proactively
|
||||||
// Sometimes the current channel can linger on for a bit even after it should have become invalid
|
// Sometimes the current channel can linger on for a bit even after it should have become invalid
|
||||||
channelCache.find { it.slotId == physicalSlotId && it.portId == portId }?.apply {
|
channelCache.find { it.slotId == physicalSlotId && it.portId == portId }?.apply {
|
||||||
if (valid) close()
|
if (valid) close()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
withTimeout(timeoutMillis) {
|
withTimeout(timeoutMillis) {
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
|
val channel = if (physicalSlotId == EuiccChannelManager.USB_CHANNEL_ID) {
|
||||||
|
// tryOpenUsbEuiccChannel() will always try to reopen the channel, even if
|
||||||
|
// a USB channel already exists
|
||||||
|
tryOpenUsbEuiccChannel()
|
||||||
|
usbChannel!!
|
||||||
|
} else {
|
||||||
// tryOpenEuiccChannel() will automatically dispose of invalid channels
|
// tryOpenEuiccChannel() will automatically dispose of invalid channels
|
||||||
// and recreate when needed
|
// and recreate when needed
|
||||||
val channel = findEuiccChannelByPort(physicalSlotId, portId)!!
|
findEuiccChannelByPort(physicalSlotId, portId)!!
|
||||||
|
}
|
||||||
check(channel.valid) { "Invalid channel" }
|
check(channel.valid) { "Invalid channel" }
|
||||||
break
|
break
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
|
@ -16,6 +16,11 @@ interface EuiccChannel {
|
||||||
|
|
||||||
val valid: Boolean
|
val valid: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer to Reset (ATR) value of the underlying interface, if any
|
||||||
|
*/
|
||||||
|
val atr: ByteArray?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Intrinsic name of this channel. For device-internal SIM slots,
|
* Intrinsic name of this channel. For device-internal SIM slots,
|
||||||
* this should be null; for USB readers, this should be the name of
|
* this should be null; for USB readers, this should be the name of
|
||||||
|
|
|
@ -11,7 +11,7 @@ class EuiccChannelImpl(
|
||||||
override val type: String,
|
override val type: String,
|
||||||
override val port: UiccPortInfoCompat,
|
override val port: UiccPortInfoCompat,
|
||||||
override val intrinsicChannelName: String?,
|
override val intrinsicChannelName: String?,
|
||||||
apduInterface: ApduInterface,
|
private val apduInterface: ApduInterface,
|
||||||
verboseLoggingFlow: Flow<Boolean>,
|
verboseLoggingFlow: Flow<Boolean>,
|
||||||
ignoreTLSCertificateFlow: Flow<Boolean>
|
ignoreTLSCertificateFlow: Flow<Boolean>
|
||||||
) : EuiccChannel {
|
) : EuiccChannel {
|
||||||
|
@ -22,6 +22,9 @@ class EuiccChannelImpl(
|
||||||
override val lpa: LocalProfileAssistant =
|
override val lpa: LocalProfileAssistant =
|
||||||
LocalProfileAssistantImpl(apduInterface, HttpInterfaceImpl(verboseLoggingFlow, ignoreTLSCertificateFlow))
|
LocalProfileAssistantImpl(apduInterface, HttpInterfaceImpl(verboseLoggingFlow, ignoreTLSCertificateFlow))
|
||||||
|
|
||||||
|
override val atr: ByteArray?
|
||||||
|
get() = (apduInterface as? ApduInterfaceAtrProvider)?.atr
|
||||||
|
|
||||||
override val valid: Boolean
|
override val valid: Boolean
|
||||||
get() = lpa.valid
|
get() = lpa.valid
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@ class EuiccChannelWrapper(orig: EuiccChannel) : EuiccChannel {
|
||||||
get() = channel.valid
|
get() = channel.valid
|
||||||
override val intrinsicChannelName: String?
|
override val intrinsicChannelName: String?
|
||||||
get() = channel.intrinsicChannelName
|
get() = channel.intrinsicChannelName
|
||||||
|
override val atr: ByteArray?
|
||||||
|
get() = channel.atr
|
||||||
|
|
||||||
override fun close() = channel.close()
|
override fun close() = channel.close()
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ class OmapiApduInterface(
|
||||||
private val service: SEService,
|
private val service: SEService,
|
||||||
private val port: UiccPortInfoCompat,
|
private val port: UiccPortInfoCompat,
|
||||||
private val verboseLoggingFlow: Flow<Boolean>
|
private val verboseLoggingFlow: Flow<Boolean>
|
||||||
): ApduInterface {
|
): ApduInterface, ApduInterfaceAtrProvider {
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "OmapiApduInterface"
|
const val TAG = "OmapiApduInterface"
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,9 @@ class OmapiApduInterface(
|
||||||
override val valid: Boolean
|
override val valid: Boolean
|
||||||
get() = service.isConnected && (this::session.isInitialized && !session.isClosed)
|
get() = service.isConnected && (this::session.isInitialized && !session.isClosed)
|
||||||
|
|
||||||
|
override val atr: ByteArray?
|
||||||
|
get() = session.atr
|
||||||
|
|
||||||
override fun connect() {
|
override fun connect() {
|
||||||
session = service.getUiccReaderCompat(port.logicalSlotIndex + 1).openSession()
|
session = service.getUiccReaderCompat(port.logicalSlotIndex + 1).openSession()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package im.angry.openeuicc.core.usb
|
||||||
import android.hardware.usb.UsbDeviceConnection
|
import android.hardware.usb.UsbDeviceConnection
|
||||||
import android.hardware.usb.UsbEndpoint
|
import android.hardware.usb.UsbEndpoint
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import im.angry.openeuicc.core.ApduInterfaceAtrProvider
|
||||||
import im.angry.openeuicc.util.*
|
import im.angry.openeuicc.util.*
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import net.typeblog.lpac_jni.ApduInterface
|
import net.typeblog.lpac_jni.ApduInterface
|
||||||
|
@ -12,7 +13,7 @@ class UsbApduInterface(
|
||||||
private val bulkIn: UsbEndpoint,
|
private val bulkIn: UsbEndpoint,
|
||||||
private val bulkOut: UsbEndpoint,
|
private val bulkOut: UsbEndpoint,
|
||||||
private val verboseLoggingFlow: Flow<Boolean>
|
private val verboseLoggingFlow: Flow<Boolean>
|
||||||
): ApduInterface {
|
) : ApduInterface, ApduInterfaceAtrProvider {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "UsbApduInterface"
|
private const val TAG = "UsbApduInterface"
|
||||||
}
|
}
|
||||||
|
@ -22,6 +23,8 @@ class UsbApduInterface(
|
||||||
|
|
||||||
private var channelId = -1
|
private var channelId = -1
|
||||||
|
|
||||||
|
override var atr: ByteArray? = null
|
||||||
|
|
||||||
override fun connect() {
|
override fun connect() {
|
||||||
ccidDescription = UsbCcidDescription.fromRawDescriptors(conn.rawDescriptors)!!
|
ccidDescription = UsbCcidDescription.fromRawDescriptors(conn.rawDescriptors)!!
|
||||||
|
|
||||||
|
@ -32,7 +35,9 @@ class UsbApduInterface(
|
||||||
transceiver = UsbCcidTransceiver(conn, bulkIn, bulkOut, ccidDescription, verboseLoggingFlow)
|
transceiver = UsbCcidTransceiver(conn, bulkIn, bulkOut, ccidDescription, verboseLoggingFlow)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
transceiver.iccPowerOn()
|
// 6.1.1.1 PC_to_RDR_IccPowerOn (Page 20 of 40)
|
||||||
|
// https://www.usb.org/sites/default/files/DWG_Smart-Card_USB-ICC_ICCD_rev10.pdf
|
||||||
|
atr = transceiver.iccPowerOn().data
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
throw e
|
throw e
|
||||||
|
|
|
@ -362,9 +362,6 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val isForegroundTaskRunning: Boolean
|
|
||||||
get() = foregroundTaskState.value != ForegroundTaskState.Idle
|
|
||||||
|
|
||||||
suspend fun waitForForegroundTask() {
|
suspend fun waitForForegroundTask() {
|
||||||
foregroundTaskState.takeWhile { it != ForegroundTaskState.Idle }
|
foregroundTaskState.takeWhile { it != ForegroundTaskState.Idle }
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -448,7 +445,7 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker {
|
||||||
portId: Int,
|
portId: Int,
|
||||||
iccid: String,
|
iccid: String,
|
||||||
enable: Boolean, // Enable or disable the profile indicated in iccid
|
enable: Boolean, // Enable or disable the profile indicated in iccid
|
||||||
reconnectTimeoutMillis: Long = 0 // 0 = do not wait for reconnect, useful for USB readers
|
reconnectTimeoutMillis: Long = 0 // 0 = do not wait for reconnect
|
||||||
): ForegroundTaskSubscriberFlow =
|
): ForegroundTaskSubscriberFlow =
|
||||||
launchForegroundTask(
|
launchForegroundTask(
|
||||||
getString(R.string.task_profile_switch),
|
getString(R.string.task_profile_switch),
|
||||||
|
|
|
@ -41,7 +41,7 @@ class EuiccInfoActivity : BaseEuiccAccessActivity(), OpenEuiccContextMarker {
|
||||||
@StringRes
|
@StringRes
|
||||||
val titleResId: Int,
|
val titleResId: Int,
|
||||||
val content: String?,
|
val content: String?,
|
||||||
val copiedToastResId: Int? = null
|
val copiedToastResId: Int? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -114,6 +114,7 @@ class EuiccInfoActivity : BaseEuiccAccessActivity(), OpenEuiccContextMarker {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
channel.lpa.euiccInfo2.let { info ->
|
channel.lpa.euiccInfo2.let { info ->
|
||||||
|
add(Item(R.string.euicc_info_sgp22_version, info?.sgp22Version))
|
||||||
add(Item(R.string.euicc_info_firmware_version, info?.euiccFirmwareVersion))
|
add(Item(R.string.euicc_info_firmware_version, info?.euiccFirmwareVersion))
|
||||||
add(Item(R.string.euicc_info_globalplatform_version, info?.globalPlatformVersion))
|
add(Item(R.string.euicc_info_globalplatform_version, info?.globalPlatformVersion))
|
||||||
add(Item(R.string.euicc_info_pp_version, info?.ppVersion))
|
add(Item(R.string.euicc_info_pp_version, info?.ppVersion))
|
||||||
|
@ -133,6 +134,13 @@ class EuiccInfoActivity : BaseEuiccAccessActivity(), OpenEuiccContextMarker {
|
||||||
}
|
}
|
||||||
add(Item(R.string.euicc_info_ci_type, getString(resId)))
|
add(Item(R.string.euicc_info_ci_type, getString(resId)))
|
||||||
}
|
}
|
||||||
|
add(
|
||||||
|
Item(
|
||||||
|
R.string.euicc_info_atr,
|
||||||
|
channel.atr?.encodeHex() ?: getString(R.string.unavailable),
|
||||||
|
copiedToastResId = R.string.toast_atr_copied,
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun formatByBoolean(b: Boolean, res: Pair<Int, Int>): String =
|
private fun formatByBoolean(b: Boolean, res: Pair<Int, Int>): String =
|
||||||
|
|
|
@ -228,11 +228,7 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
|
||||||
portId,
|
portId,
|
||||||
iccid,
|
iccid,
|
||||||
enable,
|
enable,
|
||||||
reconnectTimeoutMillis = if (isUsb) {
|
reconnectTimeoutMillis = 30 * 1000
|
||||||
0
|
|
||||||
} else {
|
|
||||||
30 * 1000
|
|
||||||
}
|
|
||||||
).waitDone()
|
).waitDone()
|
||||||
|
|
||||||
when (err) {
|
when (err) {
|
||||||
|
|
|
@ -54,6 +54,7 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
profileRenameNewName.editText!!.setText(requireArguments().getString("currentName"))
|
||||||
toolbar.apply {
|
toolbar.apply {
|
||||||
setTitle(R.string.rename)
|
setTitle(R.string.rename)
|
||||||
setNavigationOnClickListener {
|
setNavigationOnClickListener {
|
||||||
|
@ -66,11 +67,6 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
super.onStart()
|
|
||||||
profileRenameNewName.editText!!.setText(requireArguments().getString("currentName"))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
setWidthPercent(95)
|
setWidthPercent(95)
|
||||||
|
|
|
@ -5,15 +5,21 @@ import android.view.View
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import im.angry.openeuicc.common.R
|
import im.angry.openeuicc.common.R
|
||||||
|
import im.angry.openeuicc.core.EuiccChannelManager
|
||||||
import im.angry.openeuicc.ui.BaseEuiccAccessActivity
|
import im.angry.openeuicc.ui.BaseEuiccAccessActivity
|
||||||
import im.angry.openeuicc.util.*
|
import im.angry.openeuicc.util.*
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import net.typeblog.lpac_jni.LocalProfileAssistant
|
import net.typeblog.lpac_jni.LocalProfileAssistant
|
||||||
|
|
||||||
class DownloadWizardActivity: BaseEuiccAccessActivity() {
|
class DownloadWizardActivity: BaseEuiccAccessActivity() {
|
||||||
|
@ -149,6 +155,31 @@ class DownloadWizardActivity: BaseEuiccAccessActivity() {
|
||||||
private fun onNextPressed() {
|
private fun onNextPressed() {
|
||||||
hideIme()
|
hideIme()
|
||||||
|
|
||||||
|
nextButton.isEnabled = false
|
||||||
|
progressBar.visibility = View.VISIBLE
|
||||||
|
progressBar.isIndeterminate = true
|
||||||
|
|
||||||
|
lifecycleScope.launch(Dispatchers.Main) {
|
||||||
|
if (state.selectedLogicalSlot >= 0) {
|
||||||
|
try {
|
||||||
|
// This is run on IO by default
|
||||||
|
euiccChannelManager.withEuiccChannel(state.selectedLogicalSlot) { channel ->
|
||||||
|
// Be _very_ sure that the channel we got is valid
|
||||||
|
if (!channel.valid) throw EuiccChannelManager.EuiccChannelNotFoundException()
|
||||||
|
}
|
||||||
|
} catch (e: EuiccChannelManager.EuiccChannelNotFoundException) {
|
||||||
|
Toast.makeText(
|
||||||
|
this@DownloadWizardActivity,
|
||||||
|
R.string.download_wizard_slot_removed,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
progressBar.visibility = View.GONE
|
||||||
|
nextButton.isEnabled = true
|
||||||
|
|
||||||
if (currentFragment?.hasNext == true) {
|
if (currentFragment?.hasNext == true) {
|
||||||
currentFragment?.beforeNext()
|
currentFragment?.beforeNext()
|
||||||
val nextFrag = currentFragment?.createNextFragment()
|
val nextFrag = currentFragment?.createNextFragment()
|
||||||
|
@ -159,6 +190,7 @@ class DownloadWizardActivity: BaseEuiccAccessActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onInit() {
|
override fun onInit() {
|
||||||
progressBar.visibility = View.GONE
|
progressBar.visibility = View.GONE
|
||||||
|
|
|
@ -22,8 +22,6 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="24dp"
|
android:layout_marginHorizontal="24dp"
|
||||||
android:layout_marginVertical="12dp"
|
android:layout_marginVertical="12dp"
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="marquee"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/euicc_info_title"
|
app:layout_constraintTop_toBottomOf="@id/euicc_info_title"
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:inputType="textPassword" />
|
android:inputType="numberPassword" />
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<string name="no_euicc">No removable eUICC card accessible by this app is detected on this device. Insert a compatible card or a USB reader.</string>
|
<string name="no_euicc">No removable eUICC card accessible by this app is detected on this device. Insert a compatible card or a USB reader.</string>
|
||||||
<string name="no_profile">No profiles (yet) on this eSIM.</string>
|
<string name="no_profile">No profiles (yet) on this eSIM.</string>
|
||||||
<string name="unknown">Unknown</string>
|
<string name="unknown">Unknown</string>
|
||||||
|
<string name="unavailable">Unavailable</string>
|
||||||
<string name="help">Help</string>
|
<string name="help">Help</string>
|
||||||
<string name="reload">Reload Slots</string>
|
<string name="reload">Reload Slots</string>
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
<string name="toast_profile_delete_confirm_text_mismatched">Confirmation string mismatch</string>
|
<string name="toast_profile_delete_confirm_text_mismatched">Confirmation string mismatch</string>
|
||||||
<string name="toast_iccid_copied">ICCID copied to clipboard</string>
|
<string name="toast_iccid_copied">ICCID copied to clipboard</string>
|
||||||
<string name="toast_eid_copied">EID copied to clipboard</string>
|
<string name="toast_eid_copied">EID copied to clipboard</string>
|
||||||
|
<string name="toast_atr_copied">ATR copied to clipboard</string>
|
||||||
|
|
||||||
<string name="usb_permission">Grant USB permission</string>
|
<string name="usb_permission">Grant USB permission</string>
|
||||||
<string name="usb_permission_needed">Permission is needed to access the USB smart card reader.</string>
|
<string name="usb_permission_needed">Permission is needed to access the USB smart card reader.</string>
|
||||||
|
@ -61,6 +63,7 @@
|
||||||
<string name="download_wizard">Download Wizard</string>
|
<string name="download_wizard">Download Wizard</string>
|
||||||
<string name="download_wizard_back">Back</string>
|
<string name="download_wizard_back">Back</string>
|
||||||
<string name="download_wizard_next">Next</string>
|
<string name="download_wizard_next">Next</string>
|
||||||
|
<string name="download_wizard_slot_removed">Selected SIM has been removed</string>
|
||||||
<string name="download_wizard_slot_select">Select or confirm the eSIM you would like to download to:</string>
|
<string name="download_wizard_slot_select">Select or confirm the eSIM you would like to download to:</string>
|
||||||
<string name="download_wizard_slot_type">Type:</string>
|
<string name="download_wizard_slot_type">Type:</string>
|
||||||
<string name="download_wizard_slot_type_removable">Removable</string>
|
<string name="download_wizard_slot_type_removable">Removable</string>
|
||||||
|
@ -121,6 +124,7 @@
|
||||||
<string name="euicc_info_access_mode">Access Mode</string>
|
<string name="euicc_info_access_mode">Access Mode</string>
|
||||||
<string name="euicc_info_removable">Removable</string>
|
<string name="euicc_info_removable">Removable</string>
|
||||||
<string name="euicc_info_eid" translatable="false">EID</string>
|
<string name="euicc_info_eid" translatable="false">EID</string>
|
||||||
|
<string name="euicc_info_sgp22_version">SGP.22 Version</string>
|
||||||
<string name="euicc_info_firmware_version">eUICC OS Version</string>
|
<string name="euicc_info_firmware_version">eUICC OS Version</string>
|
||||||
<string name="euicc_info_globalplatform_version">GlobalPlatform Version</string>
|
<string name="euicc_info_globalplatform_version">GlobalPlatform Version</string>
|
||||||
<string name="euicc_info_sas_accreditation_number">SAS Accreditation Number</string>
|
<string name="euicc_info_sas_accreditation_number">SAS Accreditation Number</string>
|
||||||
|
@ -130,6 +134,7 @@
|
||||||
<string name="euicc_info_ci_gsma_live">GSMA Live CI</string>
|
<string name="euicc_info_ci_gsma_live">GSMA Live CI</string>
|
||||||
<string name="euicc_info_ci_gsma_test">GSMA Test CI</string>
|
<string name="euicc_info_ci_gsma_test">GSMA Test CI</string>
|
||||||
<string name="euicc_info_ci_unknown">Unknown eSIM CI</string>
|
<string name="euicc_info_ci_unknown">Unknown eSIM CI</string>
|
||||||
|
<string name="euicc_info_atr" translatable="false">Answer To Reset (ATR)</string>
|
||||||
|
|
||||||
<string name="yes">Yes</string>
|
<string name="yes">Yes</string>
|
||||||
<string name="no">No</string>
|
<string name="no">No</string>
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.typeblog.lpac_jni
|
||||||
|
|
||||||
/* Corresponds to EuiccInfo2 in SGP.22 */
|
/* Corresponds to EuiccInfo2 in SGP.22 */
|
||||||
data class EuiccInfo2(
|
data class EuiccInfo2(
|
||||||
|
val sgp22Version: String,
|
||||||
val profileVersion: String,
|
val profileVersion: String,
|
||||||
val euiccFirmwareVersion: String,
|
val euiccFirmwareVersion: String,
|
||||||
val globalPlatformVersion: String,
|
val globalPlatformVersion: String,
|
||||||
|
|
|
@ -62,6 +62,7 @@ internal object LpacJni {
|
||||||
external fun notificationsFree(head: Long)
|
external fun notificationsFree(head: Long)
|
||||||
// EuiccInfo2
|
// EuiccInfo2
|
||||||
external fun euiccInfo2Free(info: Long)
|
external fun euiccInfo2Free(info: Long)
|
||||||
|
external fun euiccInfo2GetSGP22Version(info: Long): String
|
||||||
external fun euiccInfo2GetProfileVersion(info: Long): String
|
external fun euiccInfo2GetProfileVersion(info: Long): String
|
||||||
external fun euiccInfo2GetEuiccFirmwareVersion(info: Long): String
|
external fun euiccInfo2GetEuiccFirmwareVersion(info: Long): String
|
||||||
external fun euiccInfo2GetGlobalPlatformVersion(info: Long): String
|
external fun euiccInfo2GetGlobalPlatformVersion(info: Long): String
|
||||||
|
|
|
@ -171,6 +171,7 @@ class LocalProfileAssistantImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
val ret = EuiccInfo2(
|
val ret = EuiccInfo2(
|
||||||
|
LpacJni.euiccInfo2GetSGP22Version(cInfo),
|
||||||
LpacJni.euiccInfo2GetProfileVersion(cInfo),
|
LpacJni.euiccInfo2GetProfileVersion(cInfo),
|
||||||
LpacJni.euiccInfo2GetEuiccFirmwareVersion(cInfo),
|
LpacJni.euiccInfo2GetEuiccFirmwareVersion(cInfo),
|
||||||
LpacJni.euiccInfo2GetGlobalPlatformVersion(cInfo),
|
LpacJni.euiccInfo2GetGlobalPlatformVersion(cInfo),
|
||||||
|
|
|
@ -266,6 +266,7 @@ void lpac_jni_euiccinfo2_free(struct es10c_ex_euiccinfo2 *info) {
|
||||||
|
|
||||||
LPAC_JNI_STRUCT_GETTER_NULL_TERM_LIST_NEXT(char*, stringArr)
|
LPAC_JNI_STRUCT_GETTER_NULL_TERM_LIST_NEXT(char*, stringArr)
|
||||||
LPAC_JNI_STRUCT_FREE(struct es10c_ex_euiccinfo2, euiccInfo2, lpac_jni_euiccinfo2_free)
|
LPAC_JNI_STRUCT_FREE(struct es10c_ex_euiccinfo2, euiccInfo2, lpac_jni_euiccinfo2_free)
|
||||||
|
LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, svn, SGP22Version)
|
||||||
LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, profileVersion, ProfileVersion)
|
LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, profileVersion, ProfileVersion)
|
||||||
LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, euiccFirmwareVer, EuiccFirmwareVersion)
|
LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, euiccFirmwareVer, EuiccFirmwareVersion)
|
||||||
LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, globalplatformVersion, GlobalPlatformVersion)
|
LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, globalplatformVersion, GlobalPlatformVersion)
|
||||||
|
|
Loading…
Add table
Reference in a new issue