From 359c6dd598782b4057671d1d3c4753dd01fb5b85 Mon Sep 17 00:00:00 2001 From: septs Date: Mon, 10 Mar 2025 20:27:35 +0800 Subject: [PATCH] feat: cancellable download --- .../service/EuiccChannelManagerService.kt | 17 +++++--- .../lpac_jni/ProfileDownloadCallback.kt | 2 + .../src/main/jni/lpac-jni/lpac-download.c | 43 +++++++++++++++++++ 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt b/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt index 9957f30..d9025c6 100644 --- a/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt +++ b/app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt @@ -380,6 +380,14 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker { getString(R.string.task_profile_download_failure), R.drawable.ic_task_sim_card_download ) { + val callback = object : ProfileDownloadCallback { + override var isCancelled: Boolean = false + + override fun onStateUpdate(state: ProfileDownloadCallback.DownloadState) { + if (state.progress == 0) return + foregroundTaskState.value = ForegroundTaskState.InProgress(state.progress) + } + } euiccChannelManager.beginTrackedOperation(slotId, portId) { euiccChannelManager.withEuiccChannel(slotId, portId) { channel -> channel.lpa.downloadProfile( @@ -387,13 +395,8 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker { matchingId, imei, confirmationCode, - object : ProfileDownloadCallback { - override fun onStateUpdate(state: ProfileDownloadCallback.DownloadState) { - if (state.progress == 0) return - foregroundTaskState.value = - ForegroundTaskState.InProgress(state.progress) - } - }) + callback + ) } preferenceRepository.notificationDownloadFlow.first() diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/ProfileDownloadCallback.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/ProfileDownloadCallback.kt index 289ddf6..9af49c3 100644 --- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/ProfileDownloadCallback.kt +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/ProfileDownloadCallback.kt @@ -21,5 +21,7 @@ interface ProfileDownloadCallback { Finalizing(80), // load bpp } + var isCancelled: Boolean + fun onStateUpdate(state: DownloadState) } \ No newline at end of file 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 bae2ee8..6e74c8c 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 @@ -12,6 +12,8 @@ jobject download_state_downloading; jobject download_state_finalizing; jmethodID on_state_update; +jmethodID is_cancelled; +jmethodID set_cancelled; void lpac_download_init() { LPAC_JNI_SETUP_ENV; @@ -54,8 +56,13 @@ void lpac_download_init() { "net/typeblog/lpac_jni/ProfileDownloadCallback"); on_state_update = (*env)->GetMethodID(env, download_callback_class, "onStateUpdate", "(Lnet/typeblog/lpac_jni/ProfileDownloadCallback$DownloadState;)V"); + is_cancelled = (*env)->GetMethodID(env, download_callback_class, "isCancelled", "()Z"); + set_cancelled = (*env)->GetMethodID(env, download_callback_class, "setCancelled", "(Z)V"); } +#define IS_CANCELLED (*env)->CallBooleanMethod(env, callback, is_cancelled) == JNI_TRUE +#define SET_CANCELLED(VALUE) (*env)->CallVoidMethod(env, callback, set_cancelled, VALUE) + JNIEXPORT jint JNICALL Java_net_typeblog_lpac_1jni_LpacJni_downloadProfile(JNIEnv *env, jobject thiz, jlong handle, jstring smdp, jstring matching_id, @@ -79,52 +86,88 @@ Java_net_typeblog_lpac_1jni_LpacJni_downloadProfile(JNIEnv *env, jobject thiz, j ctx->http.server_address = _smdp; + if (IS_CANCELLED) { + ret = -ES10B_ERROR_REASON_UNDEFINED; + goto out; + } (*env)->CallVoidMethod(env, callback, on_state_update, download_state_preparing); ret = es10b_get_euicc_challenge_and_info(ctx); syslog(LOG_INFO, "es10b_get_euicc_challenge_and_info %d", ret); if (ret < 0) { + SET_CANCELLED(JNI_TRUE); ret = -ES10B_ERROR_REASON_UNDEFINED; goto out; } + if (IS_CANCELLED) { + ret = -ES10B_ERROR_REASON_UNDEFINED; + goto out; + } (*env)->CallVoidMethod(env, callback, on_state_update, download_state_connecting); ret = es9p_initiate_authentication(ctx); syslog(LOG_INFO, "es9p_initiate_authentication %d", ret); if (ret < 0) { + SET_CANCELLED(JNI_TRUE); ret = -ES10B_ERROR_REASON_UNDEFINED; goto out; } + if (IS_CANCELLED) { + ret = -ES10B_ERROR_REASON_UNDEFINED; + goto out; + } (*env)->CallVoidMethod(env, callback, on_state_update, download_state_authenticating); ret = es10b_authenticate_server(ctx, _matching_id, _imei); syslog(LOG_INFO, "es10b_authenticate_server %d", ret); if (ret < 0) { + SET_CANCELLED(JNI_TRUE); ret = -ES10B_ERROR_REASON_UNDEFINED; goto out; } + if (IS_CANCELLED) { + ret = -ES10B_ERROR_REASON_UNDEFINED; + goto out; + } ret = es9p_authenticate_client(ctx); + syslog(LOG_INFO, "es9p_authenticate_client %d", ret); if (ret < 0) { + SET_CANCELLED(JNI_TRUE); ret = -ES10B_ERROR_REASON_UNDEFINED; goto out; } + if (IS_CANCELLED) { + ret = -ES10B_ERROR_REASON_UNDEFINED; + goto out; + } (*env)->CallVoidMethod(env, callback, on_state_update, download_state_downloading); ret = es10b_prepare_download(ctx, _confirmation_code); syslog(LOG_INFO, "es10b_prepare_download %d", ret); if (ret < 0) { + SET_CANCELLED(JNI_TRUE); ret = -ES10B_ERROR_REASON_UNDEFINED; goto out; } + if (IS_CANCELLED) { + ret = -ES10B_ERROR_REASON_UNDEFINED; + goto out; + } ret = es9p_get_bound_profile_package(ctx); + syslog(LOG_INFO, "es9p_get_bound_profile_package %d", ret); if (ret < 0) goto out; + if (IS_CANCELLED) { + ret = -ES10B_ERROR_REASON_UNDEFINED; + goto out; + } (*env)->CallVoidMethod(env, callback, on_state_update, download_state_finalizing); ret = es10b_load_bound_profile_package(ctx, &es10b_load_bound_profile_package_result); syslog(LOG_INFO, "es10b_load_bound_profile_package %d, reason %d", ret, es10b_load_bound_profile_package_result.errorReason); if (ret < 0) { + SET_CANCELLED(JNI_TRUE); ret = - (int) es10b_load_bound_profile_package_result.errorReason; goto out; }