diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/EuiccInfoActivity.kt b/app-common/src/main/java/im/angry/openeuicc/ui/EuiccInfoActivity.kt index bb1d5b6..8e475df 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/EuiccInfoActivity.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/EuiccInfoActivity.kt @@ -15,18 +15,12 @@ import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.ViewHolder import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import im.angry.openeuicc.common.R -import im.angry.openeuicc.core.EuiccChannel import im.angry.openeuicc.util.* import kotlinx.coroutines.launch import net.typeblog.lpac_jni.impl.DEFAULT_PKID_GSMA_RSP2_ROOT_CI1 import net.typeblog.lpac_jni.impl.PKID_GSMA_TEST_CI class EuiccInfoActivity : BaseEuiccAccessActivity() { - companion object { - private val YES_NO = Pair(R.string.yes, R.string.no) - private val SUPPORTED_UNSUPPORTED = Pair(R.string.supported, R.string.unsupported) - } - private lateinit var swipeRefresh: SwipeRefreshLayout private lateinit var infoList: RecyclerView @@ -77,59 +71,104 @@ class EuiccInfoActivity : BaseEuiccAccessActivity() { swipeRefresh.isRefreshing = true lifecycleScope.launch { - (infoList.adapter!! as EuiccInfoAdapter).euiccInfoItems = - euiccChannelManager.withEuiccChannel(logicalSlotId, ::buildPairs).map { - Pair(getString(it.first), it.second ?: getString(R.string.unknown)) - } + val unknownStr = getString(R.string.unknown) + + val newItems = mutableListOf>() + + newItems.add( + Pair( + getString(R.string.euicc_info_access_mode), + euiccChannelManager.withEuiccChannel(logicalSlotId) { channel -> channel.type } + ) + ) + + newItems.add( + Pair( + getString(R.string.euicc_info_removable), + if (euiccChannelManager.withEuiccChannel(logicalSlotId) { channel -> channel.port.card.isRemovable }) { + getString(R.string.yes) + } else { + getString(R.string.no) + } + ) + ) + + newItems.add( + Pair( + getString(R.string.euicc_info_eid), + euiccChannelManager.withEuiccChannel(logicalSlotId) { channel -> channel.lpa.eID } + ) + ) + + val euiccInfo2 = euiccChannelManager.withEuiccChannel(logicalSlotId) { channel -> + channel.lpa.euiccInfo2 + } + + newItems.add( + Pair( + getString(R.string.euicc_info_firmware_version), + euiccInfo2?.euiccFirmwareVersion ?: unknownStr + ) + ) + + newItems.add( + Pair( + getString(R.string.euicc_info_globalplatform_version), + euiccInfo2?.globalPlatformVersion ?: unknownStr + ) + ) + + newItems.add( + Pair( + getString(R.string.euicc_info_pp_version), + euiccInfo2?.ppVersion ?: unknownStr + ) + ) + + newItems.add( + Pair( + getString(R.string.euicc_info_sas_accreditation_number), + euiccInfo2?.sasAccreditationNumber ?: unknownStr + ) + ) + + newItems.add( + Pair( + getString(R.string.euicc_info_free_nvram), + euiccInfo2?.freeNvram?.let { formatFreeSpace(it) } ?: unknownStr + )) + + newItems.add( + Pair( + getString(R.string.euicc_info_gsma_prod), + if (euiccInfo2?.euiccCiPKIdListForSigning?.contains( + DEFAULT_PKID_GSMA_RSP2_ROOT_CI1 + ) == true + ) { + getString(R.string.supported) + } else { + getString(R.string.unsupported) + } + ) + ) + + newItems.add( + Pair( + getString(R.string.euicc_info_gsma_test), + if (PKID_GSMA_TEST_CI.any { euiccInfo2?.euiccCiPKIdListForSigning?.contains(it) == true }) { + getString(R.string.supported) + } else { + getString(R.string.unsupported) + } + ) + ) + + (infoList.adapter!! as EuiccInfoAdapter).euiccInfoItems = newItems swipeRefresh.isRefreshing = false } } - private fun buildPairs(channel: EuiccChannel) = buildList { - add(Pair(R.string.euicc_info_access_mode, channel.type)) - add( - Pair( - R.string.euicc_info_removable, - formatByBoolean(channel.port.card.isRemovable, YES_NO) - ) - ) - add(Pair(R.string.euicc_info_eid, channel.lpa.eID)) - channel.lpa.euiccInfo2.let { info -> - add(Pair(R.string.euicc_info_firmware_version, info?.euiccFirmwareVersion)) - add(Pair(R.string.euicc_info_globalplatform_version, info?.globalPlatformVersion)) - add(Pair(R.string.euicc_info_pp_version, info?.ppVersion)) - add(Pair(R.string.euicc_info_sas_accreditation_number, info?.sasAccreditationNumber)) - add(Pair(R.string.euicc_info_free_nvram, info?.freeNvram?.let(::formatFreeSpace))) - } - channel.lpa.euiccInfo2?.euiccCiPKIdListForSigning.orEmpty().let { signers -> - add( - Pair( - R.string.euicc_info_gsma_prod, - formatByBoolean( - signers.contains(DEFAULT_PKID_GSMA_RSP2_ROOT_CI1), - SUPPORTED_UNSUPPORTED - ) - ) - ) - add( - Pair( - R.string.euicc_info_gsma_test, - formatByBoolean(PKID_GSMA_TEST_CI.any(signers::contains), SUPPORTED_UNSUPPORTED) - ) - ) - } - } - - private fun formatByBoolean(b: Boolean, res: Pair): String = - getString( - if (b) { - res.first - } else { - res.second - } - ) - inner class EuiccInfoViewHolder(root: View) : ViewHolder(root) { private val title: TextView = root.requireViewById(R.id.euicc_info_title) private val content: TextView = root.requireViewById(R.id.euicc_info_content) diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt index 6ad74c4..f10f134 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt @@ -47,6 +47,10 @@ class SettingsFragment: PreferenceFragmentCompat() { setOnPreferenceClickListener(::onAppVersionClicked) } + findPreference("pref_info_source_code")?.apply { + intent = Intent(Intent.ACTION_VIEW, Uri.parse(summary.toString())) + } + findPreference("pref_language")?.apply { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return@apply isVisible = true diff --git a/app-common/src/main/res/layout/euicc_profile.xml b/app-common/src/main/res/layout/euicc_profile.xml index 58d55ab..7971017 100644 --- a/app-common/src/main/res/layout/euicc_profile.xml +++ b/app-common/src/main/res/layout/euicc_profile.xml @@ -28,8 +28,7 @@ app:layout_constraintRight_toLeftOf="@+id/profile_menu" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@+id/state" - app:layout_constraintHorizontal_bias="0" - app:layout_constrainedWidth="true" /> + app:layout_constraintHorizontal_bias="0" /> アプリの言語を選択 すべてのプロファイルを表示 プロダクション以外のプロファイルも表示する - タイプ: - テスティング - 準備中 - 動作中 diff --git a/app-common/src/main/res/xml/pref_settings.xml b/app-common/src/main/res/xml/pref_settings.xml index 52815b9..107e0b4 100644 --- a/app-common/src/main/res/xml/pref_settings.xml +++ b/app-common/src/main/res/xml/pref_settings.xml @@ -1,6 +1,5 @@ - + - - + app:key="pref_info_source_code"/> \ No newline at end of file diff --git a/app-unpriv/src/main/java/im/angry/openeuicc/ui/CompatibilityCheckActivity.kt b/app-unpriv/src/main/java/im/angry/openeuicc/ui/CompatibilityCheckActivity.kt index 39a360f..433f9c3 100644 --- a/app-unpriv/src/main/java/im/angry/openeuicc/ui/CompatibilityCheckActivity.kt +++ b/app-unpriv/src/main/java/im/angry/openeuicc/ui/CompatibilityCheckActivity.kt @@ -1,8 +1,6 @@ package im.angry.openeuicc.ui -import android.annotation.SuppressLint import android.os.Bundle -import android.text.Html import android.view.MenuItem import android.view.View import android.view.ViewGroup @@ -10,7 +8,6 @@ import android.widget.TextView import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.children -import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager @@ -32,16 +29,15 @@ class CompatibilityCheckActivity: AppCompatActivity() { setupToolbarInsets() supportActionBar!!.setDisplayHomeAsUpEnabled(true) - compatibilityCheckList = requireViewById(R.id.recycler_view).also { - it.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) - it.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL)) - it.adapter = adapter - } + compatibilityCheckList = requireViewById(R.id.recycler_view) + compatibilityCheckList.layoutManager = + LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) + compatibilityCheckList.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL)) + compatibilityCheckList.adapter = adapter setupRootViewInsets(compatibilityCheckList) } - @SuppressLint("NotifyDataSetChanged") override fun onStart() { super.onStart() lifecycleScope.launch { @@ -65,10 +61,10 @@ class CompatibilityCheckActivity: AppCompatActivity() { fun bindItem(item: CompatibilityCheck) { titleView.text = item.title - descView.text = Html.fromHtml(item.description, Html.FROM_HTML_MODE_COMPACT) + descView.text = item.description statusContainer.children.forEach { - it.isVisible = false + it.visibility = View.GONE } val viewId = when (item.state) { @@ -77,7 +73,7 @@ class CompatibilityCheckActivity: AppCompatActivity() { CompatibilityCheck.State.FAILURE_UNKNOWN -> R.id.compatibility_check_unknown else -> R.id.compatibility_check_progress_bar } - root.requireViewById(viewId).isVisible = true + root.requireViewById(viewId).visibility = View.VISIBLE } } diff --git a/app-unpriv/src/main/res/values/strings.xml b/app-unpriv/src/main/res/values/strings.xml index 3cf7347..a754848 100644 --- a/app-unpriv/src/main/res/values/strings.xml +++ b/app-unpriv/src/main/res/values/strings.xml @@ -12,11 +12,11 @@ OMAPI Connectivity Does your device allow access to Secure Elements on SIM cards via OMAPI? Unable to detect Secure Element readers for SIM cards via OMAPI. If you have not inserted a SIM in this device, try inserting one and retry this check. - Successfully detected Secure Element access, but only for the following SIM slots: <b>SIM%s</b>. + Successfully detected Secure Element access, but only for the following SIM slots: SIM%s. ISD-R Channel Access Does your device support opening an ISD-R (management) channel to eSIMs via OMAPI? Cannot determine whether ISD-R access through OMAPI is supported. You might want to retry with SIM cards inserted (any SIM card will do) if not already. - OMAPI access to ISD-R is only possible on the following SIM slots: <b>SIM%s</b>. + OMAPI access to ISD-R is only possible on the following SIM slots: SIM%s. Not on the Known Broken List Making sure your device is not known to have bugs associated with removable eSIMs. Oops, your device is known to have bugs when accessing removable eSIMs. This does not necessarily mean that it will not work at all, but you will have to proceed with caution. diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LocalProfileAssistant.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LocalProfileAssistant.kt index 4ff65fa..58f25aa 100644 --- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LocalProfileAssistant.kt +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LocalProfileAssistant.kt @@ -5,7 +5,6 @@ import net.typeblog.lpac_jni.HttpInterface.HttpResponse interface LocalProfileAssistant { @Suppress("ArrayInDataClass") data class ProfileDownloadException( - val lpaErrorReason: String, val lastHttpResponse: HttpResponse?, val lastHttpException: Exception?, val lastApduResponse: ByteArray?, diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LpacJni.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LpacJni.kt index 8e3f53a..09c0117 100644 --- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LpacJni.kt +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LpacJni.kt @@ -29,7 +29,6 @@ internal object LpacJni { // We do not expose all of the functions because of tediousness :) external fun downloadProfile(handle: Long, smdp: String, matchingId: String?, imei: String?, confirmationCode: String?, callback: ProfileDownloadCallback): Int - external fun downloadErrCodeToString(code: Int): String external fun handleNotification(handle: Long, seqNumber: Long): Int // Cancel any ongoing es9p and/or es10b sessions external fun cancelSessions(handle: Long) diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/HttpInterfaceImpl.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/HttpInterfaceImpl.kt index c1b15f7..77227f8 100644 --- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/HttpInterfaceImpl.kt +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/HttpInterfaceImpl.kt @@ -83,7 +83,7 @@ class HttpInterfaceImpl( private fun getSocketFactory(): SSLSocketFactory { val trustManagers = if (runBlocking { ignoreTLSCertificateFlow.first() }) { - arrayOf(AllowAllTrustManager()) + arrayOf(IgnoreTLSCertificate()) } else { this.trustManagers } diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/AllowAllTrustManager.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/IgnoreTLSCertificate.kt similarity index 92% rename from libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/AllowAllTrustManager.kt rename to libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/IgnoreTLSCertificate.kt index 55b28fe..7b13282 100644 --- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/AllowAllTrustManager.kt +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/IgnoreTLSCertificate.kt @@ -5,7 +5,7 @@ import java.security.cert.X509Certificate import javax.net.ssl.X509TrustManager @SuppressLint("CustomX509TrustManager") -class AllowAllTrustManager : X509TrustManager { +class IgnoreTLSCertificate : X509TrustManager { @SuppressLint("TrustAllX509TrustManager") override fun checkClientTrusted(p0: Array?, p1: String?) { return diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt index b617f2b..0cbebf0 100644 --- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt @@ -214,7 +214,6 @@ class LocalProfileAssistantImpl( if (res != 0) { // Construct the error now to store any error information we _can_ access val err = LocalProfileAssistant.ProfileDownloadException( - lpaErrorReason = LpacJni.downloadErrCodeToString(-res), httpInterface.lastHttpResponse, httpInterface.lastHttpException, apduInterface.lastApduResponse, diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-download.c b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-download.c index 028e30d..f63585a 100644 --- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-download.c +++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-download.c @@ -148,34 +148,4 @@ Java_net_typeblog_lpac_1jni_LpacJni_cancelSessions(JNIEnv *env, jobject thiz, jl es9p_cancel_session(ctx); es10b_cancel_session(ctx, ES10B_CANCEL_SESSION_REASON_UNDEFINED); euicc_http_cleanup(ctx); -} - -#define QUOTE(S) #S -#define ERRCODE_ENUM_TO_STRING(VARIANT) case VARIANT: return toJString(env, QUOTE(VARIANT)) - -JNIEXPORT jstring JNICALL -Java_net_typeblog_lpac_1jni_LpacJni_downloadErrCodeToString(JNIEnv *env, jobject thiz, jint code) { - switch (code) { - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_INCORRECT_INPUT_VALUES); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_INVALID_SIGNATURE); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_INVALID_TRANSACTION_ID); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_UNSUPPORTED_CRT_VALUES); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_UNSUPPORTED_REMOTE_OPERATION_TYPE); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_UNSUPPORTED_PROFILE_CLASS); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_SCP03T_STRUCTURE_ERROR); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_SCP03T_SECURITY_ERROR); - ERRCODE_ENUM_TO_STRING( - ES10B_ERROR_REASON_INSTALL_FAILED_DUE_TO_ICCID_ALREADY_EXISTS_ON_EUICC); - ERRCODE_ENUM_TO_STRING( - ES10B_ERROR_REASON_INSTALL_FAILED_DUE_TO_INSUFFICIENT_MEMORY_FOR_PROFILE); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_INSTALL_FAILED_DUE_TO_INTERRUPTION); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_INSTALL_FAILED_DUE_TO_PE_PROCESSING_ERROR); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_INSTALL_FAILED_DUE_TO_ICCID_MISMATCH); - ERRCODE_ENUM_TO_STRING( - ES10B_ERROR_REASON_TEST_PROFILE_INSTALL_FAILED_DUE_TO_INVALID_NAA_KEY); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_PPR_NOT_ALLOWED); - ERRCODE_ENUM_TO_STRING(ES10B_ERROR_REASON_INSTALL_FAILED_DUE_TO_UNKNOWN_ERROR); - default: - return toJString(env, "ES10B_ERROR_REASON_UNDEFINED"); - } } \ No newline at end of file