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.app.Dialog
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
|
import android.text.format.Formatter
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
|
@ -34,8 +36,11 @@ class ProfileDownloadFragment : DialogFragment(), EuiccFragmentMarker, Toolbar.O
|
||||||
private lateinit var profileDownloadCode: TextInputLayout
|
private lateinit var profileDownloadCode: TextInputLayout
|
||||||
private lateinit var profileDownloadConfirmationCode: TextInputLayout
|
private lateinit var profileDownloadConfirmationCode: TextInputLayout
|
||||||
private lateinit var profileDownloadIMEI: TextInputLayout
|
private lateinit var profileDownloadIMEI: TextInputLayout
|
||||||
|
private lateinit var profileDownloadFreeSpace: TextView
|
||||||
private lateinit var progress: ProgressBar
|
private lateinit var progress: ProgressBar
|
||||||
|
|
||||||
|
private var freeNvram: Int = -1
|
||||||
|
|
||||||
private var downloading = false
|
private var downloading = false
|
||||||
|
|
||||||
private val barcodeScannerLauncher = registerForActivityResult(ScanContract()) { result ->
|
private val barcodeScannerLauncher = registerForActivityResult(ScanContract()) { result ->
|
||||||
|
@ -60,6 +65,7 @@ class ProfileDownloadFragment : DialogFragment(), EuiccFragmentMarker, Toolbar.O
|
||||||
profileDownloadCode = view.findViewById(R.id.profile_download_code)
|
profileDownloadCode = view.findViewById(R.id.profile_download_code)
|
||||||
profileDownloadConfirmationCode = view.findViewById(R.id.profile_download_confirmation_code)
|
profileDownloadConfirmationCode = view.findViewById(R.id.profile_download_confirmation_code)
|
||||||
profileDownloadIMEI = view.findViewById(R.id.profile_download_imei)
|
profileDownloadIMEI = view.findViewById(R.id.profile_download_imei)
|
||||||
|
profileDownloadFreeSpace = view.findViewById(R.id.profile_download_free_space)
|
||||||
progress = view.findViewById(R.id.progress)
|
progress = view.findViewById(R.id.progress)
|
||||||
|
|
||||||
toolbar.inflateMenu(R.menu.fragment_profile_download)
|
toolbar.inflateMenu(R.menu.fragment_profile_download)
|
||||||
|
@ -102,6 +108,18 @@ class ProfileDownloadFragment : DialogFragment(), EuiccFragmentMarker, Toolbar.O
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
profileDownloadIMEI.editText!!.text = Editable.Factory.getInstance().newEditable(channel.imei)
|
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 {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
|
|
@ -102,13 +102,14 @@
|
||||||
android:id="@+id/profile_download_imei"
|
android:id="@+id/profile_download_imei"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginVertical="15dp"
|
android:layout_marginTop="15dp"
|
||||||
|
android:layout_marginBottom="6dp"
|
||||||
android:hint="@string/profile_download_imei"
|
android:hint="@string/profile_download_imei"
|
||||||
style="@style/Widget.OpenEUICC.Input"
|
style="@style/Widget.OpenEUICC.Input"
|
||||||
app:layout_constraintTop_toBottomOf="@id/profile_download_confirmation_code"
|
app:layout_constraintTop_toBottomOf="@id/profile_download_confirmation_code"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="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:layout_constraintWidth_percent=".8"
|
||||||
app:passwordToggleEnabled="true">
|
app:passwordToggleEnabled="true">
|
||||||
|
|
||||||
|
@ -120,4 +121,16 @@
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</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>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<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="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="enabled">Enabled</string>
|
||||||
<string name="disabled">Disabled</string>
|
<string name="disabled">Disabled</string>
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
<string name="profile_download_code">Activation Code</string>
|
<string name="profile_download_code">Activation Code</string>
|
||||||
<string name="profile_download_confirmation_code">Confirmation Code (Optional)</string>
|
<string name="profile_download_confirmation_code">Confirmation Code (Optional)</string>
|
||||||
<string name="profile_download_imei">IMEI (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_scan">Scan QR Code</string>
|
||||||
<string name="profile_download_ok">Download</string>
|
<string name="profile_download_ok">Download</string>
|
||||||
<string name="profile_download_failed">Failed to download eSIM. Check your activation / QR code.</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 {
|
interface LocalProfileAssistant {
|
||||||
val profiles: List<LocalProfileInfo>
|
val profiles: List<LocalProfileInfo>
|
||||||
val eID: String
|
val eID: String
|
||||||
|
// Extended EuiccInfo for use with LUIs, containing information such as firmware version
|
||||||
|
val euiccInfo2: EuiccInfo2?
|
||||||
|
|
||||||
fun enableProfile(iccid: String): Boolean
|
fun enableProfile(iccid: String): Boolean
|
||||||
fun disableProfile(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 :)
|
// We do not expose all of the functions because of tediousness :)
|
||||||
external fun downloadProfile(handle: Long, smdp: String, matchingId: String?, imei: String?,
|
external fun downloadProfile(handle: Long, smdp: String, matchingId: String?, imei: String?,
|
||||||
confirmationCode: String?, callback: ProfileDownloadCallback): Int
|
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.LpacJni
|
||||||
import net.typeblog.lpac_jni.ApduInterface
|
import net.typeblog.lpac_jni.ApduInterface
|
||||||
|
import net.typeblog.lpac_jni.EuiccInfo2
|
||||||
import net.typeblog.lpac_jni.HttpInterface
|
import net.typeblog.lpac_jni.HttpInterface
|
||||||
import net.typeblog.lpac_jni.LocalProfileAssistant
|
import net.typeblog.lpac_jni.LocalProfileAssistant
|
||||||
import net.typeblog.lpac_jni.LocalProfileInfo
|
import net.typeblog.lpac_jni.LocalProfileInfo
|
||||||
|
@ -25,6 +26,9 @@ class LocalProfileAssistantImpl(
|
||||||
LpacJni.es10cGetEid(contextHandle)!!
|
LpacJni.es10cGetEid(contextHandle)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val euiccInfo2: EuiccInfo2?
|
||||||
|
get() = LpacJni.es10cexGetEuiccInfo2(contextHandle)
|
||||||
|
|
||||||
override fun enableProfile(iccid: String): Boolean {
|
override fun enableProfile(iccid: String): Boolean {
|
||||||
return LpacJni.es10cEnableProfile(contextHandle, iccid) == 0
|
return LpacJni.es10cEnableProfile(contextHandle, iccid) == 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,9 @@ jstring empty_string;
|
||||||
jclass string_class;
|
jclass string_class;
|
||||||
jmethodID string_constructor;
|
jmethodID string_constructor;
|
||||||
|
|
||||||
|
jclass euicc_info2_class;
|
||||||
|
jmethodID euicc_info2_constructor;
|
||||||
|
|
||||||
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||||
jvm = vm;
|
jvm = vm;
|
||||||
interface_wrapper_init();
|
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)->GetStaticObjectField(env, local_profile_class_class, field_operational);
|
||||||
local_profile_class_operational = (*env)->NewGlobalRef(env, local_profile_class_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];
|
const char _unused[1];
|
||||||
empty_string = (*env)->NewString(env, _unused, 0);
|
empty_string = (*env)->NewString(env, _unused, 0);
|
||||||
empty_string = (*env)->NewGlobalRef(env, empty_string);
|
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);
|
(*env)->ReleaseStringUTFChars(env, iccid, _iccid);
|
||||||
return ret;
|
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