Display remaining space on card when downloading new profiles
TODO: Refuse to download more profiles (or at least warn) if running out of space.
This commit is contained in:
parent
47b2a7060b
commit
af75b8f5fb
|
@ -3,9 +3,11 @@ package im.angry.openeuicc.ui
|
|||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.format.Formatter
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.fragment.app.DialogFragment
|
||||
|
@ -34,8 +36,11 @@ class ProfileDownloadFragment : DialogFragment(), EuiccFragmentMarker, Toolbar.O
|
|||
private lateinit var profileDownloadCode: TextInputLayout
|
||||
private lateinit var profileDownloadConfirmationCode: TextInputLayout
|
||||
private lateinit var profileDownloadIMEI: TextInputLayout
|
||||
private lateinit var profileDownloadFreeSpace: TextView
|
||||
private lateinit var progress: ProgressBar
|
||||
|
||||
private var freeNvram: Int = -1
|
||||
|
||||
private var downloading = false
|
||||
|
||||
private val barcodeScannerLauncher = registerForActivityResult(ScanContract()) { result ->
|
||||
|
@ -60,6 +65,7 @@ class ProfileDownloadFragment : DialogFragment(), EuiccFragmentMarker, Toolbar.O
|
|||
profileDownloadCode = view.findViewById(R.id.profile_download_code)
|
||||
profileDownloadConfirmationCode = view.findViewById(R.id.profile_download_confirmation_code)
|
||||
profileDownloadIMEI = view.findViewById(R.id.profile_download_imei)
|
||||
profileDownloadFreeSpace = view.findViewById(R.id.profile_download_free_space)
|
||||
progress = view.findViewById(R.id.progress)
|
||||
|
||||
toolbar.inflateMenu(R.menu.fragment_profile_download)
|
||||
|
@ -102,6 +108,18 @@ class ProfileDownloadFragment : DialogFragment(), EuiccFragmentMarker, Toolbar.O
|
|||
override fun onStart() {
|
||||
super.onStart()
|
||||
profileDownloadIMEI.editText!!.text = Editable.Factory.getInstance().newEditable(channel.imei)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
// Fetch remaining NVRAM
|
||||
val str = channel.lpa.euiccInfo2?.freeNvram?.also {
|
||||
freeNvram = it
|
||||
}?.let { Formatter.formatShortFileSize(requireContext(), it.toLong()) }
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
profileDownloadFreeSpace.text = getString(R.string.profile_download_free_space,
|
||||
str ?: getText(R.string.unknown))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
|
|
|
@ -102,13 +102,14 @@
|
|||
android:id="@+id/profile_download_imei"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:hint="@string/profile_download_imei"
|
||||
style="@style/Widget.OpenEUICC.Input"
|
||||
app:layout_constraintTop_toBottomOf="@id/profile_download_confirmation_code"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/profile_download_free_space"
|
||||
app:layout_constraintWidth_percent=".8"
|
||||
app:passwordToggleEnabled="true">
|
||||
|
||||
|
@ -120,4 +121,16 @@
|
|||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/profile_download_free_space"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textSize="11sp"
|
||||
android:layout_marginBottom="4dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/profile_download_imei"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="no_euicc">No eUICC card on this device is accessible by this app.\nInsert a supported eUICC card, or try out the privileged OpenEUICC app instead.</string>
|
||||
<string name="unknown">Unknown</string>
|
||||
|
||||
<string name="enabled">Enabled</string>
|
||||
<string name="disabled">Disabled</string>
|
||||
|
@ -21,6 +22,7 @@
|
|||
<string name="profile_download_code">Activation Code</string>
|
||||
<string name="profile_download_confirmation_code">Confirmation Code (Optional)</string>
|
||||
<string name="profile_download_imei">IMEI (Optional)</string>
|
||||
<string name="profile_download_free_space">Space remaining: %s</string>
|
||||
<string name="profile_download_scan">Scan QR Code</string>
|
||||
<string name="profile_download_ok">Download</string>
|
||||
<string name="profile_download_failed">Failed to download eSIM. Check your activation / QR code.</string>
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package net.typeblog.lpac_jni
|
||||
|
||||
/* Corresponds to EuiccInfo2 in SGP.22 */
|
||||
data class EuiccInfo2(
|
||||
val profileVersion: String,
|
||||
val sgp22Version: String,
|
||||
val euiccFirmwareVersion: String,
|
||||
val uiccFirmwareVersion: String,
|
||||
val globalPlatformVersion: String,
|
||||
val sasAccreditationNumber: String,
|
||||
val ppVersion: String,
|
||||
val installedApp: Int,
|
||||
val freeNvram: Int,
|
||||
val freeRam: Int,
|
||||
)
|
|
@ -3,6 +3,8 @@ package net.typeblog.lpac_jni
|
|||
interface LocalProfileAssistant {
|
||||
val profiles: List<LocalProfileInfo>
|
||||
val eID: String
|
||||
// Extended EuiccInfo for use with LUIs, containing information such as firmware version
|
||||
val euiccInfo2: EuiccInfo2?
|
||||
|
||||
fun enableProfile(iccid: String): Boolean
|
||||
fun disableProfile(iccid: String): Boolean
|
||||
|
|
|
@ -25,4 +25,7 @@ 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
|
||||
|
||||
// es10cex (actually part of es10b)
|
||||
external fun es10cexGetEuiccInfo2(handle: Long): EuiccInfo2?
|
||||
}
|
|
@ -2,6 +2,7 @@ package net.typeblog.lpac_jni.impl
|
|||
|
||||
import net.typeblog.lpac_jni.LpacJni
|
||||
import net.typeblog.lpac_jni.ApduInterface
|
||||
import net.typeblog.lpac_jni.EuiccInfo2
|
||||
import net.typeblog.lpac_jni.HttpInterface
|
||||
import net.typeblog.lpac_jni.LocalProfileAssistant
|
||||
import net.typeblog.lpac_jni.LocalProfileInfo
|
||||
|
@ -25,6 +26,9 @@ class LocalProfileAssistantImpl(
|
|||
LpacJni.es10cGetEid(contextHandle)!!
|
||||
}
|
||||
|
||||
override val euiccInfo2: EuiccInfo2?
|
||||
get() = LpacJni.es10cexGetEuiccInfo2(contextHandle)
|
||||
|
||||
override fun enableProfile(iccid: String): Boolean {
|
||||
return LpacJni.es10cEnableProfile(contextHandle, iccid) == 0
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@ jstring empty_string;
|
|||
jclass string_class;
|
||||
jmethodID string_constructor;
|
||||
|
||||
jclass euicc_info2_class;
|
||||
jmethodID euicc_info2_constructor;
|
||||
|
||||
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
jvm = vm;
|
||||
interface_wrapper_init();
|
||||
|
@ -58,6 +61,10 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
|||
local_profile_class_operational = (*env)->GetStaticObjectField(env, local_profile_class_class, field_operational);
|
||||
local_profile_class_operational = (*env)->NewGlobalRef(env, local_profile_class_operational);
|
||||
|
||||
euicc_info2_class = (*env)->FindClass(env, "net/typeblog/lpac_jni/EuiccInfo2");
|
||||
euicc_info2_class = (*env)->NewGlobalRef(env, euicc_info2_class);
|
||||
euicc_info2_constructor = (*env)->GetMethodID(env, euicc_info2_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;III)V");
|
||||
|
||||
const char _unused[1];
|
||||
empty_string = (*env)->NewString(env, _unused, 0);
|
||||
empty_string = (*env)->NewGlobalRef(env, empty_string);
|
||||
|
@ -230,3 +237,44 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10cDeleteProfile(JNIEnv *env, jobject thiz
|
|||
(*env)->ReleaseStringUTFChars(env, iccid, _iccid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_net_typeblog_lpac_1jni_LpacJni_es10cexGetEuiccInfo2(JNIEnv *env, jobject thiz, jlong handle) {
|
||||
struct euicc_ctx *ctx = (struct euicc_ctx *) handle;
|
||||
struct es10cex_euiccinfo2 info;
|
||||
jstring sas_accreditation_number = NULL;
|
||||
jstring global_platform_version = NULL;
|
||||
jstring euicc_firmware_version = NULL;
|
||||
jstring uicc_firmware_version = NULL;
|
||||
jstring profile_version = NULL;
|
||||
jstring sgp22_version = NULL;
|
||||
jstring pp_version = NULL;
|
||||
jobject ret = NULL;
|
||||
|
||||
if (es10cex_get_euiccinfo2(ctx, &info) < 0)
|
||||
goto out;
|
||||
|
||||
profile_version = toJString(env, info.profile_version);
|
||||
sgp22_version = toJString(env, info.sgp22_version);
|
||||
euicc_firmware_version = toJString(env, info.euicc_firmware_version);
|
||||
uicc_firmware_version = toJString(env, info.uicc_firmware_version);
|
||||
global_platform_version = toJString(env, info.global_platform_version);
|
||||
sas_accreditation_number = toJString(env, info.sas_accreditation_number);
|
||||
pp_version = toJString(env, info.pp_version);
|
||||
|
||||
ret = (*env)->NewObject(env, euicc_info2_class, euicc_info2_constructor,
|
||||
profile_version, sgp22_version, euicc_firmware_version,
|
||||
uicc_firmware_version, global_platform_version,
|
||||
sas_accreditation_number, pp_version,
|
||||
info.installed_app, info.free_nvram, info.free_ram);
|
||||
|
||||
out:
|
||||
(*env)->DeleteLocalRef(env, profile_version);
|
||||
(*env)->DeleteLocalRef(env, sgp22_version);
|
||||
(*env)->DeleteLocalRef(env, euicc_firmware_version);
|
||||
(*env)->DeleteLocalRef(env, uicc_firmware_version);
|
||||
(*env)->DeleteLocalRef(env, global_platform_version);
|
||||
(*env)->DeleteLocalRef(env, sas_accreditation_number);
|
||||
(*env)->DeleteLocalRef(env, pp_version);
|
||||
return ret;
|
||||
}
|
Loading…
Reference in a new issue