diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
deleted file mode 100644
index 913d49d9..00000000
--- a/.idea/deploymentTargetSelector.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 589fc6ca..163d6b48 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -4,20 +4,11 @@
diff --git a/.idea/migrations.xml b/.idea/migrations.xml
deleted file mode 100644
index f8051a6f..00000000
--- a/.idea/migrations.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app-common/src/main/java/im/angry/openeuicc/core/OmapiApduInterface.kt b/app-common/src/main/java/im/angry/openeuicc/core/OmapiApduInterface.kt
index 711658ad..227977c9 100644
--- a/app-common/src/main/java/im/angry/openeuicc/core/OmapiApduInterface.kt
+++ b/app-common/src/main/java/im/angry/openeuicc/core/OmapiApduInterface.kt
@@ -3,7 +3,6 @@ package im.angry.openeuicc.core
import android.se.omapi.Channel
import android.se.omapi.SEService
import android.se.omapi.Session
-import android.util.Log
import im.angry.openeuicc.util.*
import net.typeblog.lpac_jni.ApduInterface
@@ -11,10 +10,6 @@ class OmapiApduInterface(
private val service: SEService,
private val port: UiccPortInfoCompat
): ApduInterface {
- companion object {
- const val TAG = "OmapiApduInterface"
- }
-
private lateinit var session: Session
private lateinit var lastChannel: Channel
@@ -49,17 +44,7 @@ class OmapiApduInterface(
"Unknown channel"
}
- Log.d(TAG, "OMAPI APDU: ${tx.encodeHex()}")
-
- try {
- return lastChannel.transmit(tx).also {
- Log.d(TAG, "OMAPI APDU response: ${it.encodeHex()}")
- }
- } catch (e: Exception) {
- Log.e(TAG, "OMAPI APDU exception")
- e.printStackTrace()
- throw e
- }
+ return lastChannel.transmit(tx)
}
}
\ No newline at end of file
diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt b/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt
index ac0a99f8..3374f07b 100644
--- a/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt
+++ b/app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt
@@ -296,7 +296,7 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
}
iccid.setOnLongClickListener {
- requireContext().getSystemService(ClipboardManager::class.java)!!
+ requireContext().getSystemService(ClipboardManager::class.java)
.setPrimaryClip(ClipData.newPlainText("iccid", iccid.text))
Toast.makeText(requireContext(), R.string.toast_iccid_copied, Toast.LENGTH_SHORT)
.show()
diff --git a/app-deps/build.gradle.kts b/app-deps/build.gradle.kts
index 6cde72d6..21114360 100644
--- a/app-deps/build.gradle.kts
+++ b/app-deps/build.gradle.kts
@@ -13,7 +13,7 @@ apply {
android {
namespace = "im.angry.openeuicc_deps"
- compileSdk = 34
+ compileSdk = 33
defaultConfig {
minSdk = 28
diff --git a/app-unpriv/src/main/java/im/angry/openeuicc/util/CompatibilityCheck.kt b/app-unpriv/src/main/java/im/angry/openeuicc/util/CompatibilityCheck.kt
index 8424c550..49811bc5 100644
--- a/app-unpriv/src/main/java/im/angry/openeuicc/util/CompatibilityCheck.kt
+++ b/app-unpriv/src/main/java/im/angry/openeuicc/util/CompatibilityCheck.kt
@@ -193,7 +193,7 @@ internal class IsdrChannelAccessCheck(private val context: Context): Compatibili
internal class KnownBrokenCheck(private val context: Context): CompatibilityCheck(context) {
companion object {
- val BROKEN_MANUFACTURERS = arrayOf("xiaomi", "huawei", "honor")
+ val BROKEN_MANUFACTURERS = arrayOf("xiaomi")
}
override val title: String
diff --git a/libs/lpac-jni/build.gradle.kts b/libs/lpac-jni/build.gradle.kts
index 7f451776..b50a9534 100644
--- a/libs/lpac-jni/build.gradle.kts
+++ b/libs/lpac-jni/build.gradle.kts
@@ -5,7 +5,7 @@ plugins {
android {
namespace = "net.typeblog.lpac_jni"
- compileSdk = 34
+ compileSdk = 33
ndkVersion = "26.1.10909125"
defaultConfig {
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 32fbb0aa..5a706b9a 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
@@ -14,14 +14,14 @@ internal object LpacJni {
// es10c
// null returns signify errors
external fun es10cGetEid(handle: Long): String?
- external fun es10cGetProfilesInfo(handle: Long): Long
+ external fun es10cGetProfilesInfo(handle: Long): Array?
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, nick: String): Int
// es10b
- external fun es10bListNotification(handle: Long): Long // A native pointer to a linked list. Handle with linked list-related methods below. May be 0 (null)
+ external fun es10bListNotification(handle: Long): Array?
external fun es10bDeleteNotification(handle: Long, seqNumber: Long): Int
// es9p + es10b
@@ -31,39 +31,5 @@ internal object LpacJni {
external fun handleNotification(handle: Long, seqNumber: Long): Int
// es10cex (actually part of es10b)
- external fun es10cexGetEuiccInfo2(handle: Long): Long
-
- // C <-> Java struct / linked list handling
- // C String arrays
- external fun stringArrNext(curr: Long): Long
- external fun stringDeref(curr: Long): String
- // Profiles
- external fun profilesNext(curr: Long): Long
- external fun profilesFree(head: Long): Long
- external fun profileGetIccid(curr: Long): String
- external fun profileGetIsdpAid(curr: Long): String
- external fun profileGetName(curr: Long): String
- external fun profileGetNickname(curr: Long): String
- external fun profileGetServiceProvider(curr: Long): String
- external fun profileGetStateString(curr: Long): String
- external fun profileGetClassString(curr: Long): String
- // Notifications
- external fun notificationsNext(curr: Long): Long
- external fun notificationGetSeq(curr: Long): Long
- external fun notificationGetOperationString(curr: Long): String
- external fun notificationGetAddress(curr: Long): String
- external fun notificationGetIccid(curr: Long): String
- external fun notificationsFree(head: Long)
- // EuiccInfo2
- external fun euiccInfo2Free(info: Long)
- external fun euiccInfo2GetProfileVersion(info: Long): String
- external fun euiccInfo2GetEuiccFirmwareVersion(info: Long): String
- external fun euiccInfo2GetGlobalPlatformVersion(info: Long): String
- external fun euiccInfo2GetSasAcreditationNumber(info: Long): String
- external fun euiccInfo2GetPpVersion(info: Long): String
- external fun euiccInfo2GetFreeNonVolatileMemory(info: Long): Long
- external fun euiccInfo2GetFreeVolatileMemory(info: Long): Long
- // C String Arrays
- external fun euiccInfo2GetEuiccCiPKIdListForSigning(info: Long): Long
- external fun euiccInfo2GetEuiccCiPKIdListForVerification(info: Long): Long
+ external fun es10cexGetEuiccInfo2(handle: Long): EuiccInfo2?
}
\ No newline at end of file
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 61491d79..361c594b 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
@@ -42,85 +42,18 @@ class LocalProfileAssistantImpl(
}
override val profiles: List
- get() {
- val head = LpacJni.es10cGetProfilesInfo(contextHandle)
- var curr = head
- val ret = mutableListOf()
- while (curr != 0L) {
- val state = LocalProfileInfo.State.fromString(LpacJni.profileGetStateString(curr))
- val clazz = LocalProfileInfo.Clazz.fromString(LpacJni.profileGetClassString(curr))
- ret.add(LocalProfileInfo(
- LpacJni.profileGetIccid(curr),
- state,
- LpacJni.profileGetName(curr),
- LpacJni.profileGetNickname(curr),
- LpacJni.profileGetServiceProvider(curr),
- LpacJni.profileGetIsdpAid(curr),
- clazz
- ))
- curr = LpacJni.profilesNext(curr)
- }
-
- LpacJni.profilesFree(curr)
- return ret
- }
+ get() = LpacJni.es10cGetProfilesInfo(contextHandle)?.asList() ?: listOf()
override val notifications: List
- get() {
- val head = LpacJni.es10bListNotification(contextHandle)
- var curr = head
- val ret = mutableListOf()
- while (curr != 0L) {
- ret.add(LocalProfileNotification(
- LpacJni.notificationGetSeq(curr),
- LocalProfileNotification.Operation.fromString(LpacJni.notificationGetOperationString(curr)),
- LpacJni.notificationGetAddress(curr),
- LpacJni.notificationGetIccid(curr),
- ))
- curr = LpacJni.notificationsNext(curr)
- }
- LpacJni.notificationsFree(head)
- return ret.sortedBy { it.seqNumber }.reversed()
- }
+ get() =
+ (LpacJni.es10bListNotification(contextHandle) ?: arrayOf())
+ .sortedBy { it.seqNumber }.reversed()
override val eID: String
get() = LpacJni.es10cGetEid(contextHandle)!!
override val euiccInfo2: EuiccInfo2?
- get() {
- val cInfo = LpacJni.es10cexGetEuiccInfo2(contextHandle)
- if (cInfo == 0L) return null
-
- val euiccCiPKIdListForSigning = mutableListOf()
- var curr = LpacJni.euiccInfo2GetEuiccCiPKIdListForSigning(cInfo)
- while (curr != 0L) {
- euiccCiPKIdListForSigning.add(LpacJni.stringDeref(curr))
- curr = LpacJni.stringArrNext(curr)
- }
-
- val euiccCiPKIdListForVerification = mutableListOf()
- curr = LpacJni.euiccInfo2GetEuiccCiPKIdListForVerification(cInfo)
- while (curr != 0L) {
- euiccCiPKIdListForVerification.add(LpacJni.stringDeref(curr))
- curr = LpacJni.stringArrNext(curr)
- }
-
- val ret = EuiccInfo2(
- LpacJni.euiccInfo2GetProfileVersion(cInfo),
- LpacJni.euiccInfo2GetEuiccFirmwareVersion(cInfo),
- LpacJni.euiccInfo2GetGlobalPlatformVersion(cInfo),
- LpacJni.euiccInfo2GetSasAcreditationNumber(cInfo),
- LpacJni.euiccInfo2GetPpVersion(cInfo),
- LpacJni.euiccInfo2GetFreeNonVolatileMemory(cInfo).toInt(),
- LpacJni.euiccInfo2GetFreeVolatileMemory(cInfo).toInt(),
- euiccCiPKIdListForSigning.toTypedArray(),
- euiccCiPKIdListForVerification.toTypedArray()
- )
-
- LpacJni.euiccInfo2Free(cInfo)
-
- return ret
- }
+ get() = LpacJni.es10cexGetEuiccInfo2(contextHandle)
override fun enableProfile(iccid: String, refresh: Boolean): Boolean =
LpacJni.es10cEnableProfile(contextHandle, iccid, refresh) == 0
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 91676daf..f8b27ff0 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
@@ -114,7 +114,7 @@ Java_net_typeblog_lpac_1jni_LpacJni_downloadProfile(JNIEnv *env, jobject thiz, j
(*env)->CallVoidMethod(env, callback, on_state_update, download_state_finalizing);
// TODO: Expose error code as Java-side exceptions?
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);
+ syslog(LOG_INFO, "es10b_load_bound_profile_package %d", ret);
out:
euicc_http_cleanup(ctx);
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 1721b772..6ba8ebf7 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
@@ -12,15 +12,28 @@
JavaVM *jvm = NULL;
+jclass local_profile_info_class;
+jmethodID local_profile_info_constructor;
+
+jclass local_profile_state_class;
+jmethodID local_profile_state_from_string;
+
+jclass local_profile_class_class;
+jmethodID local_profile_class_from_string;
+
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();
lpac_download_init();
+ lpac_notifications_init();
LPAC_JNI_SETUP_ENV;
string_class = (*env)->FindClass(env, "java/lang/String");
@@ -28,6 +41,30 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
string_constructor = (*env)->GetMethodID(env, string_class, "",
"([BLjava/lang/String;)V");
+ local_profile_info_class = (*env)->FindClass(env, "net/typeblog/lpac_jni/LocalProfileInfo");
+ local_profile_info_class = (*env)->NewGlobalRef(env, local_profile_info_class);
+ local_profile_info_constructor = (*env)->GetMethodID(env, local_profile_info_class, "",
+ "(Ljava/lang/String;Lnet/typeblog/lpac_jni/LocalProfileInfo$State;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lnet/typeblog/lpac_jni/LocalProfileInfo$Clazz;)V");
+
+ local_profile_state_class = (*env)->FindClass(env,
+ "net/typeblog/lpac_jni/LocalProfileInfo$State");
+ local_profile_state_class = (*env)->NewGlobalRef(env, local_profile_state_class);
+ local_profile_state_from_string = (*env)->GetStaticMethodID(env, local_profile_state_class,
+ "fromString",
+ "(Ljava/lang/String;)Lnet/typeblog/lpac_jni/LocalProfileInfo$State;");
+
+ local_profile_class_class = (*env)->FindClass(env,
+ "net/typeblog/lpac_jni/LocalProfileInfo$Clazz");
+ local_profile_class_class = (*env)->NewGlobalRef(env, local_profile_class_class);
+ local_profile_class_from_string = (*env)->GetStaticMethodID(env, local_profile_class_class,
+ "fromString",
+ "(Ljava/lang/String;)Lnet/typeblog/lpac_jni/LocalProfileInfo$Clazz;");
+
+ 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, "",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II[Ljava/lang/String;[Ljava/lang/String;)V");
+
const char _unused[1];
empty_string = (*env)->NewString(env, _unused, 0);
empty_string = (*env)->NewGlobalRef(env, empty_string);
@@ -108,23 +145,25 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10cGetEid(JNIEnv *env, jobject thiz, jlong
return ret;
}
-JNIEXPORT jlong JNICALL
-Java_net_typeblog_lpac_1jni_LpacJni_es10cGetProfilesInfo(JNIEnv *env, jobject thiz, jlong handle) {
- struct euicc_ctx *ctx = (struct euicc_ctx *) handle;
- struct es10c_profile_info_list *info = NULL;
-
- if (es10c_get_profiles_info(ctx, &info) < 0) {
- return 0;
- }
-
- return (jlong) info;
-}
-
-JNIEXPORT jstring JNICALL
-Java_net_typeblog_lpac_1jni_LpacJni_profileGetStateString(JNIEnv *env, jobject thiz, jlong curr) {
- struct es10c_profile_info_list *info = (struct es10c_profile_info_list *) curr;
+jobject profile_info_native_to_java(JNIEnv *env, struct es10c_profile_info_list *info) {
const char *profileStateStr = NULL;
+ const char *profileClassStr = NULL;
+ jstring serviceProvider = NULL;
+ jstring nickName = NULL;
+ jstring isdpAid = NULL;
+ jstring iccid = NULL;
+ jstring name = NULL;
+ jobject state = NULL;
+ jobject class = NULL;
+ jobject jinfo = NULL;
+ iccid = toJString(env, info->iccid);
+ isdpAid = toJString(env, info->isdpAid);
+ name = toJString(env, info->profileName);
+ nickName = toJString(env, info->profileNickname);
+ serviceProvider = toJString(env, info->serviceProviderName);
+
+ // TODO: Maybe we should pass a Java object directly here?
switch (info->profileState) {
case ES10C_PROFILE_STATE_ENABLED:
profileStateStr = "enabled";
@@ -136,13 +175,9 @@ Java_net_typeblog_lpac_1jni_LpacJni_profileGetStateString(JNIEnv *env, jobject t
profileStateStr = "unknown";
}
- return toJString(env, profileStateStr);
-}
-
-JNIEXPORT jstring JNICALL
-Java_net_typeblog_lpac_1jni_LpacJni_profileGetClassString(JNIEnv *env, jobject thiz, jlong curr) {
- struct es10c_profile_info_list *info = (struct es10c_profile_info_list *) curr;
- const char *profileClassStr = NULL;
+ state = (*env)->CallStaticObjectMethod(env, local_profile_state_class,
+ local_profile_state_from_string,
+ toJString(env, profileStateStr));
switch (info->profileClass) {
case ES10C_PROFILE_CLASS_TEST:
@@ -159,16 +194,51 @@ Java_net_typeblog_lpac_1jni_LpacJni_profileGetClassString(JNIEnv *env, jobject t
break;
}
- return toJString(env, profileClassStr);
+ class = (*env)->CallStaticObjectMethod(env, local_profile_class_class,
+ local_profile_class_from_string,
+ toJString(env, profileClassStr));
+
+ jinfo = (*env)->NewObject(env, local_profile_info_class, local_profile_info_constructor,
+ iccid, state, name, nickName, serviceProvider, isdpAid, class);
+
+ (*env)->DeleteLocalRef(env, class);
+ (*env)->DeleteLocalRef(env, state);
+ (*env)->DeleteLocalRef(env, serviceProvider);
+ (*env)->DeleteLocalRef(env, nickName);
+ (*env)->DeleteLocalRef(env, name);
+ (*env)->DeleteLocalRef(env, isdpAid);
+ (*env)->DeleteLocalRef(env, iccid);
+
+ return jinfo;
}
-LPAC_JNI_STRUCT_GETTER_LINKED_LIST_NEXT(struct es10c_profile_info_list, profiles)
-LPAC_JNI_STRUCT_FREE(struct es10c_profile_info_list, profiles, es10c_profile_info_list_free_all)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_profile_info_list, profile, iccid, Iccid)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_profile_info_list, profile, isdpAid, IsdpAid)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_profile_info_list, profile, profileName, Name)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_profile_info_list, profile, profileNickname, Nickname)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_profile_info_list, profile, serviceProviderName, ServiceProvider)
+JNIEXPORT jobjectArray JNICALL
+Java_net_typeblog_lpac_1jni_LpacJni_es10cGetProfilesInfo(JNIEnv *env, jobject thiz, jlong handle) {
+ struct euicc_ctx *ctx = (struct euicc_ctx *) handle;
+ struct es10c_profile_info_list *info = NULL;
+ struct es10c_profile_info_list *curr = NULL;
+ jobjectArray ret = NULL;
+ jobject jinfo = NULL;
+ int count = 0;
+
+ if (es10c_get_profiles_info(ctx, &info) < 0) {
+ return NULL;
+ }
+
+ count = LPAC_JNI_LINKED_LIST_COUNT(info, curr);
+
+ ret = (*env)->NewObjectArray(env, count, local_profile_info_class, NULL);
+
+ // Convert the native info array to Java
+ LPAC_JNI_LINKED_LIST_FOREACH(info, curr, {
+ jinfo = profile_info_native_to_java(env, curr);
+ (*env)->SetObjectArrayElement(env, ret, i, jinfo);
+ (*env)->DeleteLocalRef(env, jinfo);
+ });
+
+ es10c_profile_info_list_free_all(info);
+ return ret;
+}
JNIEXPORT jint JNICALL
Java_net_typeblog_lpac_1jni_LpacJni_es10cEnableProfile(JNIEnv *env, jobject thiz, jlong handle,
@@ -225,38 +295,58 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10cDeleteProfile(JNIEnv *env, jobject thiz
return ret;
}
-JNIEXPORT jlong JNICALL
+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 es10c_ex_euiccinfo2 *info = malloc(sizeof(struct es10c_ex_euiccinfo2));
+ struct es10c_ex_euiccinfo2 info = {0};
+ jobjectArray euiccCiPKIdListForVerification = NULL;
+ jobjectArray euiccCiPKIdListForSigning = NULL;
+ jstring sas_accreditation_number = NULL;
+ jstring global_platform_version = NULL;
+ jstring euicc_firmware_version = NULL;
+ jstring profile_version = NULL;
+ jstring pp_version = NULL;
+ jobject ret = NULL;
+ char **curr = NULL;
+ int count = 0;
- if (es10c_ex_get_euiccinfo2(ctx, info) < 0) {
- free(info);
- return 0;
- }
+ if (es10c_ex_get_euiccinfo2(ctx, &info) < 0)
+ goto out;
- return (jlong) info;
-}
+ profile_version = toJString(env, info.profileVersion);
+ euicc_firmware_version = toJString(env, info.euiccFirmwareVer);
+ global_platform_version = toJString(env, info.globalplatformVersion);
+ sas_accreditation_number = toJString(env, info.sasAcreditationNumber);
+ pp_version = toJString(env, info.ppVersion);
-JNIEXPORT jstring JNICALL
-Java_net_typeblog_lpac_1jni_LpacJni_stringDeref(JNIEnv *env, jobject thiz, jlong curr) {
- return toJString(env, *((char **) curr));
-}
+ count = LPAC_JNI_NULL_TERM_LIST_COUNT(info.euiccCiPKIdListForSigning, curr);
+ euiccCiPKIdListForSigning = (*env)->NewObjectArray(env, count, string_class, NULL);
+ LPAC_JNI_NULL_TERM_LIST_FOREACH(info.euiccCiPKIdListForSigning, curr, {
+ (*env)->SetObjectArrayElement(env, euiccCiPKIdListForSigning, i, toJString(env, *curr));
+ });
-void lpac_jni_euiccinfo2_free(struct es10c_ex_euiccinfo2 *info) {
- es10c_ex_euiccinfo2_free(info);
- free(info);
-}
+ count = LPAC_JNI_NULL_TERM_LIST_COUNT(info.euiccCiPKIdListForVerification, curr);
+ euiccCiPKIdListForVerification = (*env)->NewObjectArray(env, count, string_class, NULL);
+ LPAC_JNI_NULL_TERM_LIST_FOREACH(info.euiccCiPKIdListForVerification, curr, {
+ (*env)->SetObjectArrayElement(env, euiccCiPKIdListForVerification, i,
+ toJString(env, *curr));
+ });
-LPAC_JNI_STRUCT_GETTER_NULL_TERM_LIST_NEXT(char*, stringArr)
-LPAC_JNI_STRUCT_FREE(struct es10c_ex_euiccinfo2, euiccInfo2, lpac_jni_euiccinfo2_free)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, profileVersion, ProfileVersion)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, euiccFirmwareVer, EuiccFirmwareVersion)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, globalplatformVersion, GlobalPlatformVersion)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, sasAcreditationNumber, SasAcreditationNumber)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10c_ex_euiccinfo2, euiccInfo2, ppVersion, PpVersion)
-LPAC_JNI_STRUCT_GETTER_LONG(struct es10c_ex_euiccinfo2, euiccInfo2, extCardResource.freeNonVolatileMemory, FreeNonVolatileMemory)
-LPAC_JNI_STRUCT_GETTER_LONG(struct es10c_ex_euiccinfo2, euiccInfo2, extCardResource.freeVolatileMemory, FreeVolatileMemory)
+ ret = (*env)->NewObject(env, euicc_info2_class, euicc_info2_constructor,
+ profile_version, euicc_firmware_version,
+ global_platform_version,
+ sas_accreditation_number, pp_version,
+ info.extCardResource.freeNonVolatileMemory,
+ info.extCardResource.freeVolatileMemory,
+ euiccCiPKIdListForSigning,
+ euiccCiPKIdListForVerification);
-LPAC_JNI_STRUCT_GETTER_LONG(struct es10c_ex_euiccinfo2, euiccInfo2, euiccCiPKIdListForSigning, EuiccCiPKIdListForSigning)
-LPAC_JNI_STRUCT_GETTER_LONG(struct es10c_ex_euiccinfo2, euiccInfo2, euiccCiPKIdListForVerification, EuiccCiPKIdListForVerification)
+ out:
+ (*env)->DeleteLocalRef(env, profile_version);
+ (*env)->DeleteLocalRef(env, euicc_firmware_version);
+ (*env)->DeleteLocalRef(env, global_platform_version);
+ (*env)->DeleteLocalRef(env, sas_accreditation_number);
+ (*env)->DeleteLocalRef(env, pp_version);
+ es10c_ex_euiccinfo2_free(&info);
+ return ret;
+}
\ No newline at end of file
diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.h b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.h
index a5d6262d..1915c5e4 100644
--- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.h
+++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.h
@@ -17,42 +17,37 @@ struct lpac_jni_ctx {
JNIEnv *env; \
(*jvm)->AttachCurrentThread(jvm, &env, NULL)
+#define __LPAC_JNI_LINKED_LIST_FOREACH(list, curr, body, after) { \
+ int i = 0; \
+ curr = list; \
+ while (curr != NULL) { \
+ body; \
+ curr = curr->next; \
+ i++; \
+ }; \
+ after; \
+}
+#define LPAC_JNI_LINKED_LIST_FOREACH(list, curr, body) \
+ __LPAC_JNI_LINKED_LIST_FOREACH(list, curr, body, {})
+#define LPAC_JNI_LINKED_LIST_COUNT(list, curr) \
+ (__LPAC_JNI_LINKED_LIST_FOREACH(list, curr, {}, i))
+
+#define __LPAC_JNI_NULL_TERM_LIST_FOREACH(list, curr, body, after) { \
+ int i = 0; \
+ curr = list; \
+ while (*curr != NULL) { \
+ body; \
+ curr++; \
+ i++; \
+ }; \
+ after; \
+}
+#define LPAC_JNI_NULL_TERM_LIST_FOREACH(list, curr, body) \
+ __LPAC_JNI_NULL_TERM_LIST_FOREACH(list, curr, body, {})
+#define LPAC_JNI_NULL_TERM_LIST_COUNT(list, curr) \
+ (__LPAC_JNI_NULL_TERM_LIST_FOREACH(list, curr, {}, i))
+
extern JavaVM *jvm;
extern jclass string_class;
-jstring toJString(JNIEnv *env, const char *pat);
-
-#define LPAC_JNI_STRUCT_GETTER_LINKED_LIST_NEXT(st, st_jname) \
- JNIEXPORT jlong JNICALL Java_net_typeblog_lpac_1jni_LpacJni_##st_jname##Next(JNIEnv *env, jobject thiz, jlong raw) { \
- st *p = (st *) raw; \
- if (p == NULL) return 0; \
- return (jlong) p->next; \
- }
-
-#define LPAC_JNI_STRUCT_GETTER_NULL_TERM_LIST_NEXT(st, st_jname) \
- JNIEXPORT jlong JNICALL Java_net_typeblog_lpac_1jni_LpacJni_##st_jname##Next(JNIEnv *env, jobject thiz, jlong raw) { \
- st *p = (st *) raw; \
- p++; \
- if (*p == NULL) return 0; \
- return (jlong) p; \
- }
-
-#define LPAC_JNI_STRUCT_FREE(st, st_jname, free_func) \
- JNIEXPORT void JNICALL Java_net_typeblog_lpac_1jni_LpacJni_##st_jname##Free(JNIEnv *env, jobject thiz, jlong raw) { \
- st *p = (st *) raw; \
- if (p == NULL) return; \
- free_func(p); \
- }
-
-#define LPAC_JNI_STRUCT_GETTER_LONG(st, st_name, name, jname) \
- JNIEXPORT jlong JNICALL Java_net_typeblog_lpac_1jni_LpacJni_##st_name##Get##jname(JNIEnv *env, jobject thiz, jlong raw) { \
- st *p = (st *) raw; \
- if (p == NULL) return 0; \
- return (jlong) p->name; \
- }
-
-#define LPAC_JNI_STRUCT_GETTER_STRING(st, st_name, name, jname) \
- JNIEXPORT jstring JNICALL Java_net_typeblog_lpac_1jni_LpacJni_##st_name##Get##jname(JNIEnv *env, jobject thiz, jlong raw) { \
- st *p = (st *) raw; \
- return toJString(env, p->name); \
- }
\ No newline at end of file
+jstring toJString(JNIEnv *env, const char *pat);
\ No newline at end of file
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 cf402cf8..1a5ac7c2 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
@@ -4,15 +4,88 @@
#include
#include
-JNIEXPORT jlong JNICALL
+jclass local_profile_notification_class;
+jmethodID local_profile_notification_constructor;
+
+jclass local_profile_notification_operation_class;
+jmethodID local_profile_notification_operation_from_string;
+
+void lpac_notifications_init() {
+ LPAC_JNI_SETUP_ENV;
+
+ local_profile_notification_class =
+ (*env)->FindClass(env, "net/typeblog/lpac_jni/LocalProfileNotification");
+ local_profile_notification_class =
+ (*env)->NewGlobalRef(env, local_profile_notification_class);
+ local_profile_notification_constructor =
+ (*env)->GetMethodID(env, local_profile_notification_class, "",
+ "(JLnet/typeblog/lpac_jni/LocalProfileNotification$Operation;Ljava/lang/String;Ljava/lang/String;)V");
+
+ local_profile_notification_operation_class =
+ (*env)->FindClass(env, "net/typeblog/lpac_jni/LocalProfileNotification$Operation");
+ local_profile_notification_operation_class =
+ (*env)->NewGlobalRef(env, local_profile_notification_operation_class);
+ local_profile_notification_operation_from_string =
+ (*env)->GetStaticMethodID(env, local_profile_notification_operation_class, "fromString",
+ "(Ljava/lang/String;)Lnet/typeblog/lpac_jni/LocalProfileNotification$Operation;");
+}
+
+JNIEXPORT jobject JNICALL
Java_net_typeblog_lpac_1jni_LpacJni_es10bListNotification(JNIEnv *env, jobject thiz, jlong handle) {
struct euicc_ctx *ctx = (struct euicc_ctx *) handle;
struct es10b_notification_metadata_list *info = NULL;
+ struct es10b_notification_metadata_list *curr = NULL;
+ const char *profileManagementOperationStr = NULL;
+ jobject notification = NULL;
+ jobject operation = NULL;
+ jobjectArray ret = NULL;
+ int count = 0;
if (es10b_list_notification(ctx, &info) < 0)
- return 0;
+ return NULL;
- return (jlong) info;
+ count = LPAC_JNI_LINKED_LIST_COUNT(info, curr);
+
+ ret = (*env)->NewObjectArray(env, count, local_profile_notification_class, NULL);
+
+ LPAC_JNI_LINKED_LIST_FOREACH(info, curr, {
+ switch (curr->profileManagementOperation) {
+ case ES10B_PROFILE_MANAGEMENT_OPERATION_INSTALL:
+ profileManagementOperationStr = "install";
+ break;
+ case ES10B_PROFILE_MANAGEMENT_OPERATION_DELETE:
+ profileManagementOperationStr = "delete";
+ break;
+ case ES10B_PROFILE_MANAGEMENT_OPERATION_ENABLE:
+ profileManagementOperationStr = "enable";
+ break;
+ case ES10B_PROFILE_MANAGEMENT_OPERATION_DISABLE:
+ profileManagementOperationStr = "disable";
+ break;
+ default:
+ profileManagementOperationStr = "unknown";
+ }
+
+ operation =
+ (*env)->CallStaticObjectMethod(env, local_profile_notification_operation_class,
+ local_profile_notification_operation_from_string,
+ toJString(env, profileManagementOperationStr));
+
+ notification =
+ (*env)->NewObject(env, local_profile_notification_class,
+ local_profile_notification_constructor, curr->seqNumber,
+ operation,
+ toJString(env, curr->notificationAddress),
+ toJString(env, curr->iccid));
+
+ (*env)->SetObjectArrayElement(env, ret, i, notification);
+
+ (*env)->DeleteLocalRef(env, operation);
+ (*env)->DeleteLocalRef(env, notification);
+ });
+
+ es10b_notification_metadata_list_free_all(info);
+ return ret;
}
JNIEXPORT jint JNICALL
@@ -44,36 +117,4 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10bDeleteNotification(JNIEnv *env, jobject
jlong seq_number) {
struct euicc_ctx *ctx = (struct euicc_ctx *) handle;
return es10b_remove_notification_from_list(ctx, (unsigned long) seq_number);
-}
-
-JNIEXPORT jstring JNICALL
-Java_net_typeblog_lpac_1jni_LpacJni_notificationGetOperationString(JNIEnv *env, jobject thiz,
- jlong curr) {
- struct es10b_notification_metadata_list *info = (struct es10b_notification_metadata_list *) curr;
- const char *profileManagementOperationStr = NULL;
- switch (info->profileManagementOperation) {
- case ES10B_PROFILE_MANAGEMENT_OPERATION_INSTALL:
- profileManagementOperationStr = "install";
- break;
- case ES10B_PROFILE_MANAGEMENT_OPERATION_DELETE:
- profileManagementOperationStr = "delete";
- break;
- case ES10B_PROFILE_MANAGEMENT_OPERATION_ENABLE:
- profileManagementOperationStr = "enable";
- break;
- case ES10B_PROFILE_MANAGEMENT_OPERATION_DISABLE:
- profileManagementOperationStr = "disable";
- break;
- default:
- profileManagementOperationStr = "unknown";
- break;
- }
-
- return toJString(env, profileManagementOperationStr);
-}
-
-LPAC_JNI_STRUCT_GETTER_LINKED_LIST_NEXT(struct es10b_notification_metadata_list, notifications)
-LPAC_JNI_STRUCT_FREE(struct es10b_notification_metadata_list, notifications, es10b_notification_metadata_list_free_all)
-LPAC_JNI_STRUCT_GETTER_LONG(struct es10b_notification_metadata_list, notification, seqNumber, Seq)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10b_notification_metadata_list, notification, notificationAddress, Address)
-LPAC_JNI_STRUCT_GETTER_STRING(struct es10b_notification_metadata_list, notification, iccid, Iccid)
+}
\ No newline at end of file
diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-notifications.h b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-notifications.h
index 511de2fa..0b88555c 100644
--- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-notifications.h
+++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-notifications.h
@@ -2,3 +2,5 @@
#include
#include "lpac-jni.h"
+
+void lpac_notifications_init();
\ No newline at end of file