Compare commits

..

1 commit

Author SHA1 Message Date
fe7e3a551d
refactor: lpac-jni bridge 2025-03-11 03:03:58 +08:00
9 changed files with 88 additions and 60 deletions

View file

@ -19,14 +19,14 @@ internal object LpacJni {
// es10c
// null returns signify errors
external fun es10cGetEid(handle: Long): String?
external fun es10cGetProfilesInfo(handle: Long): List<LocalProfileInfo>
external fun es10cGetProfilesInfo(handle: Long, profiles: List<LocalProfileInfo>): 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<LocalProfileNotification>
external fun es10bListNotification(handle: Long, elements: List<LocalProfileNotification>): Int
external fun es10bDeleteNotification(handle: Long, seqNumber: Long): Int
// es10a

View file

@ -1,5 +1,7 @@
package net.typeblog.lpac_jni
import java.util.ArrayList
interface ProfileDiscoveryCallback {
fun onDiscovered(servers: Set<String>)
fun onDiscovered(servers: ArrayList<String>)
}

View file

@ -108,11 +108,21 @@ class LocalProfileAssistantImpl(
override val profiles: List<LocalProfileInfo>
@Synchronized
get() = LpacJni.es10cGetProfilesInfo(contextHandle)
get() {
val profiles = mutableListOf<LocalProfileInfo>()
val ret = LpacJni.es10cGetProfilesInfo(contextHandle, profiles)
if (ret < 0) throw IllegalStateException("Failed to get profiles")
return profiles
}
override val notifications: List<LocalProfileNotification>
@Synchronized
get() = LpacJni.es10bListNotification(contextHandle).sortedBy { it.seqNumber }.reversed()
get() {
val notifications = mutableListOf<LocalProfileNotification>()
val ret = LpacJni.es10bListNotification(contextHandle, notifications)
check(ret > 0) { "Failed to get notifications" }
return notifications.sortedBy { it.seqNumber }.reversed()
}
override val eID: String
@Synchronized

View file

@ -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, "<init>", "()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, "<init>", "()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, "<init>", "()V");
return (*env)->NewObject(env, array_list_class, array_list_constructor);
}

View file

@ -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);

View file

@ -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, "<init>",
"(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, "<init>",
"("
"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:

View file

@ -2,3 +2,5 @@
#include <jni.h>
#include "lpac-jni.h"
void lpac_discovery_init(JNIEnv *env);

View file

@ -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

View file

@ -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