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 e744f91..6f70bc4 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 @@ -19,14 +19,14 @@ internal object LpacJni { // es10c // null returns signify errors external fun es10cGetEid(handle: Long): String? - external fun es10cGetProfilesInfo(handle: Long): List + external fun es10cGetProfilesInfo(handle: Long, profiles: List): Long external fun es10cEnableProfile(handle: Long, iccid: String, refresh: Boolean): Int external fun es10cDisableProfile(handle: Long, iccid: String, refresh: Boolean): Int external fun es10cDeleteProfile(handle: Long, iccid: String): Int external fun es10cSetNickname(handle: Long, iccid: String, nickNullTerminated: ByteArray): Int // es10b - external fun es10bListNotification(handle: Long): List + external fun es10bListNotification(handle: Long, elements: List): Int external fun es10bDeleteNotification(handle: Long, seqNumber: Long): Int // es10a diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/ProfileDiscoveryCallback.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/ProfileDiscoveryCallback.kt index d51eb74..4cd7761 100644 --- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/ProfileDiscoveryCallback.kt +++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/ProfileDiscoveryCallback.kt @@ -1,5 +1,7 @@ package net.typeblog.lpac_jni +import java.util.ArrayList + interface ProfileDiscoveryCallback { - fun onDiscovered(servers: Set) + fun onDiscovered(servers: ArrayList) } 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 c6f3cbf..01a8b9d 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 @@ -108,11 +108,21 @@ class LocalProfileAssistantImpl( override val profiles: List @Synchronized - get() = LpacJni.es10cGetProfilesInfo(contextHandle) + get() { + val profiles = mutableListOf() + val ret = LpacJni.es10cGetProfilesInfo(contextHandle, profiles) + if (ret < 0) throw IllegalStateException("Failed to get profiles") + return profiles + } override val notifications: List @Synchronized - get() = LpacJni.es10bListNotification(contextHandle).sortedBy { it.seqNumber }.reversed() + get() { + val notifications = mutableListOf() + val ret = LpacJni.es10bListNotification(contextHandle, notifications) + check(ret > 0) { "Failed to get notifications" } + return notifications.sortedBy { it.seqNumber }.reversed() + } override val eID: String @Synchronized diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-convertor.c b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-convertor.c index 1b1518d..19f4010 100644 --- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-convertor.c +++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-convertor.c @@ -132,6 +132,19 @@ jobject to_version(JNIEnv *env, const char *version) { return (*env)->NewObject(env, version_class, version_constructor, value); } +jobject to_string_list(JNIEnv *env, char **values) { + jclass array_class = (*env)->FindClass(env, ARRAY_LIST_CLASS); + jmethodID array_constructor = (*env)->GetMethodID(env, array_class, "", "()V"); + jobject elements = (*env)->NewObject(env, array_class, array_constructor); + jmethodID add_element = (*env)->GetMethodID(env, array_class, "add", "(Ljava/lang/Object;)Z"); + jstring element = NULL; + for (jsize index = 0; values[index] != NULL; index++) { + element = toJString(env, values[index]); + (*env)->CallBooleanMethod(env, elements, add_element, element); + } + return elements; +} + jobject to_string_set(JNIEnv *env, char **values) { jclass set_class = (*env)->FindClass(env, HASH_SET_CLASS); jmethodID set_constructor = (*env)->GetMethodID(env, set_class, "", "()V"); @@ -187,9 +200,3 @@ jobject to_profile_management_operation(enum es10b_profile_management_operation return NULL; } } - -jobject new_array_list(JNIEnv *env) { - jclass array_list_class = (*env)->FindClass(env, ARRAY_LIST_CLASS); - jmethodID array_list_constructor = (*env)->GetMethodID(env, array_list_class, "", "()V"); - return (*env)->NewObject(env, array_list_class, array_list_constructor); -} diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-convertor.h b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-convertor.h index dfed36b..79cbe8d 100644 --- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-convertor.h +++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-convertor.h @@ -13,6 +13,7 @@ #define LOCAL_PROFILE_NOTIFICATION_CLASS PACKAGE_NAME "/LocalProfileNotification" #define PROFILE_MANAGEMENT_OPERATION_CLASS PACKAGE_NAME "/ProfileManagementOperation" #define EUICC_CONFIGURED_ADDRESSES_CLASS PACKAGE_NAME "/EuiccConfiguredAddresses" +#define DISCOVERY_CALLBACK_CLASS PACKAGE_NAME "/ProfileDiscoveryCallback" #define VERSION_CLASS PACKAGE_NAME "/Version" #define HASH_SET_CLASS "java/util/HashSet" #define ARRAY_LIST_CLASS "java/util/ArrayList" @@ -31,10 +32,10 @@ jobject to_profile_class(enum es10c_profile_class profile_class); jobject to_version(JNIEnv *env, const char *version); +jobject to_string_list(JNIEnv *env, char **values); + jobject to_string_set(JNIEnv *env, char **values); jobject build_profile_metadata(JNIEnv *env, struct es8p_metadata *metadata); -jobject to_profile_management_operation(enum es10b_profile_management_operation operation); - -jobject new_array_list(JNIEnv *env); +jobject to_profile_management_operation(enum es10b_profile_management_operation operation); \ No newline at end of file diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-discovery.c b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-discovery.c index 446521b..3e9ff69 100644 --- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-discovery.c +++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-discovery.c @@ -7,6 +7,23 @@ #include "lpac-convertor.h" #include "lpac-discovery.h" +jclass euicc_configured_addresses_class; +jmethodID euicc_configured_addresses_constructor; + +jmethodID on_discovered; + +void lpac_discovery_init(JNIEnv *env) { + jclass download_callback_class = (*env)->FindClass(env, DISCOVERY_CALLBACK_CLASS); + on_discovered = (*env)->GetMethodID(env, download_callback_class, "onDiscovered", + "(Ljava/util/ArrayList;)V"); + + euicc_configured_addresses_class = (*env)->FindClass(env, EUICC_CONFIGURED_ADDRESSES_CLASS); + euicc_configured_addresses_class = (*env)->NewGlobalRef(env, euicc_configured_addresses_class); + euicc_configured_addresses_constructor = (*env)->GetMethodID( + env, euicc_configured_addresses_class, "", + "(Ljava/lang/String;Ljava/lang/String;)V"); +} + JNIEXPORT jobject JNICALL Java_net_typeblog_lpac_1jni_LpacJni_es10aGetEuiccConfiguredAddresses( JNIEnv *env, @@ -19,21 +36,11 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10aGetEuiccConfiguredAddresses( if (es10a_get_euicc_configured_addresses(ctx, &addresses) < 0) { goto out; } - jclass configured_addresses_class = (*env)->FindClass(env, EUICC_CONFIGURED_ADDRESSES_CLASS); - jmethodID configured_addresses_constructor = (*env)->GetMethodID( - env, configured_addresses_class, "", - "(" - "Ljava/lang/String;" // default dp address - "Ljava/lang/String;" // root ds address - ")" - "V" // (returns) void - ); - ret = (*env)->NewObject( - env, configured_addresses_class, - configured_addresses_constructor, - toJString(env, addresses.defaultDpAddress), - toJString(env, addresses.rootDsAddress) - ); + jstring default_dp_address = toJString(env, addresses.defaultDpAddress); + jstring root_ds_address = toJString(env, addresses.rootDsAddress); + ret = (*env)->NewObject(env, euicc_configured_addresses_class, + euicc_configured_addresses_constructor, + default_dp_address, root_ds_address); out: es10a_euicc_configured_addresses_free(&addresses); return ret; @@ -50,10 +57,6 @@ Java_net_typeblog_lpac_1jni_LpacJni_discoveryProfile( ) { struct euicc_ctx *ctx = (struct euicc_ctx *) handle; - jclass callback_class = (*env)->GetObjectClass(env, callback); - jmethodID on_discovered = (*env)->GetMethodID(env, callback_class, "onDiscovered", - "(Ljava/util/Set;)V"); - const char *_address = (*env)->GetStringUTFChars(env, address, NULL); const char *_imei = NULL; @@ -95,7 +98,7 @@ Java_net_typeblog_lpac_1jni_LpacJni_discoveryProfile( goto out; } - (*env)->CallVoidMethod(env, callback, on_discovered, to_string_set(env, smdp_list)); + (*env)->CallVoidMethod(env, callback, on_discovered, to_string_list(env, smdp_list)); out: diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-discovery.h b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-discovery.h index 511de2f..d66e1c2 100644 --- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-discovery.h +++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-discovery.h @@ -2,3 +2,5 @@ #include #include "lpac-jni.h" + +void lpac_discovery_init(JNIEnv *env); diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c index 0b6b496..e3dcdaf 100644 --- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c +++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c @@ -22,6 +22,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) { interface_wrapper_init(env); lpac_convertor_init(env); + lpac_discovery_init(env); lpac_download_init(env); return JNI_VERSION_1_6; @@ -29,8 +30,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEXPORT jlong JNICALL Java_net_typeblog_lpac_1jni_LpacJni_createContext( - JNIEnv *env, - jobject thiz, + JNIEnv *env, jobject thiz, jbyteArray isdr_aid, jobject apdu_interface, jobject http_interface @@ -104,17 +104,21 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10cGetEid(JNIEnv *env, jobject thiz, jlong return ret; } -JNIEXPORT jobject JNICALL +JNIEXPORT jlong JNICALL Java_net_typeblog_lpac_1jni_LpacJni_es10cGetProfilesInfo( JNIEnv *env, __attribute__((unused)) jobject thiz, - jlong handle + jlong handle, + jobject profiles ) { struct euicc_ctx *ctx = (struct euicc_ctx *) handle; struct es10c_profile_info_list *info = NULL; - jobject profile_list = new_array_list(env); int ret = es10c_get_profiles_info(ctx, &info); - if (ret < 0) goto out; + if (ret < 0) return ret; + + jclass profile_list_class = (*env)->GetObjectClass(env, profiles); + jmethodID add_profile = (*env)->GetMethodID(env, profile_list_class, "add", + "(Ljava/lang/Object;)Z"); jclass profile_info_class = (*env)->FindClass(env, LOCAL_PROFILE_INFO_CLASS); jmethodID profile_info_class_constructor = (*env)->GetMethodID( @@ -131,9 +135,6 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10cGetProfilesInfo( "V" // (returns) void ); - jclass profile_list_class = (*env)->GetObjectClass(env, profile_list); - jmethodID add_profile = (*env)->GetMethodID(env, profile_list_class, "add", "(Ljava/lang/Object;)Z"); - jobject element = NULL; while (info) { element = (*env)->NewObject( @@ -146,12 +147,12 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10cGetProfilesInfo( toJString(env, info->isdpAid), to_profile_class(info->profileClass) ); - (*env)->CallBooleanMethod(env, profile_list, add_profile, element); + (*env)->CallBooleanMethod(env, profiles, add_profile, element); info = info->next; } - out: + es10c_profile_info_list_free_all(info); - return profile_list; + return ret; } JNIEXPORT jint JNICALL diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-notifications.c b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-notifications.c index e6c0069..4d4c293 100644 --- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-notifications.c +++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-notifications.c @@ -5,15 +5,15 @@ #include "lpac-convertor.h" #include "lpac-notifications.h" -JNIEXPORT jobject JNICALL +JNIEXPORT jint JNICALL Java_net_typeblog_lpac_1jni_LpacJni_es10bListNotification( JNIEnv *env, - __attribute__((unused)) jobject thiz, - jlong handle + jobject thiz, + jlong handle, + jobject notifications ) { struct euicc_ctx *ctx = (struct euicc_ctx *) handle; struct es10b_notification_metadata_list *metadata = NULL; - jobject notification_list = new_array_list(env); int ret = es10b_list_notification(ctx, &metadata); if (ret < 0) goto out; @@ -29,26 +29,28 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10bListNotification( ")" "V" // (returns) void ); - - jclass notification_list_class = (*env)->GetObjectClass(env, notification_list); - jmethodID add_notification = (*env)->GetMethodID(env, notification_list_class, "add", "(Ljava/lang/Object;)Z"); + jmethodID add_notification = (*env)->GetMethodID( + env, + (*env)->GetObjectClass(env, notifications), + "add", "(Ljava/lang/Object;)Z" + ); jobject element; while (metadata) { + jlong sequence_number = metadata->seqNumber; + jobject operation = to_profile_management_operation(metadata->profileManagementOperation); + jstring address = toJString(env, metadata->notificationAddress); + jstring iccid = toJString(env, metadata->iccid); element = (*env)->NewObject( env, local_profile_notification_class, local_profile_notification_constructor, - (jlong) metadata->seqNumber, - to_profile_management_operation(metadata->profileManagementOperation), - toJString(env, metadata->notificationAddress), - toJString(env, metadata->iccid) - ); - (*env)->CallBooleanMethod(env, notification_list, add_notification, element); + sequence_number, operation, address, iccid); + (*env)->CallBooleanMethod(env, notifications, add_notification, element); metadata = metadata->next; } out: es10b_notification_metadata_list_free_all(metadata); - return notification_list; + return ret; } JNIEXPORT jint JNICALL