refactor: profile list (lpac-jni) #173

Closed
septs wants to merge 1 commit from septs:profile-list into master
9 changed files with 146 additions and 132 deletions

View file

@ -43,6 +43,7 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import net.typeblog.lpac_jni.ProfileClass
open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener, open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
EuiccChannelFragmentMarker { EuiccChannelFragmentMarker {
@ -387,9 +388,9 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
profileClass.isVisible = unfilteredProfileListFlow.value profileClass.isVisible = unfilteredProfileListFlow.value
profileClass.setText( profileClass.setText(
when (profile.profileClass) { when (profile.profileClass) {
LocalProfileInfo.Clazz.Testing -> R.string.profile_class_testing ProfileClass.Testing -> R.string.profile_class_testing
LocalProfileInfo.Clazz.Provisioning -> R.string.profile_class_provisioning ProfileClass.Provisioning -> R.string.profile_class_provisioning
LocalProfileInfo.Clazz.Operational -> R.string.profile_class_operational ProfileClass.Operational -> R.string.profile_class_operational
} }
) )
iccid.text = profile.iccid iccid.text = profile.iccid

View file

@ -5,6 +5,8 @@ import im.angry.openeuicc.core.EuiccChannel
import im.angry.openeuicc.core.EuiccChannelManager import im.angry.openeuicc.core.EuiccChannelManager
import net.typeblog.lpac_jni.LocalProfileAssistant import net.typeblog.lpac_jni.LocalProfileAssistant
import net.typeblog.lpac_jni.LocalProfileInfo import net.typeblog.lpac_jni.LocalProfileInfo
import net.typeblog.lpac_jni.ProfileClass
import net.typeblog.lpac_jni.ProfileState
const val TAG = "LPAUtils" const val TAG = "LPAUtils"
@ -13,10 +15,10 @@ val LocalProfileInfo.displayName: String
val LocalProfileInfo.isEnabled: Boolean val LocalProfileInfo.isEnabled: Boolean
get() = state == LocalProfileInfo.State.Enabled get() = state == ProfileState.Enabled
val List<LocalProfileInfo>.operational: List<LocalProfileInfo> val List<LocalProfileInfo>.operational: List<LocalProfileInfo>
get() = filter { it.profileClass == LocalProfileInfo.Clazz.Operational } get() = filter { it.profileClass == ProfileClass.Operational }
val List<LocalProfileInfo>.enabled: LocalProfileInfo? val List<LocalProfileInfo>.enabled: LocalProfileInfo?
get() = find { it.isEnabled } get() = find { it.isEnabled }

View file

@ -15,6 +15,8 @@ import im.angry.openeuicc.util.*
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.typeblog.lpac_jni.ProfileClass
import net.typeblog.lpac_jni.ProfileState
import kotlin.IllegalStateException import kotlin.IllegalStateException
class OpenEuiccService : EuiccService(), OpenEuiccContextMarker { class OpenEuiccService : EuiccService(), OpenEuiccContextMarker {
@ -200,15 +202,15 @@ class OpenEuiccService : EuiccService(), OpenEuiccContextMarker {
setServiceProviderName(it.providerName) setServiceProviderName(it.providerName)
setState( setState(
when (it.state) { when (it.state) {
LocalProfileInfo.State.Enabled -> EuiccProfileInfo.PROFILE_STATE_ENABLED ProfileState.Enabled -> EuiccProfileInfo.PROFILE_STATE_ENABLED
LocalProfileInfo.State.Disabled -> EuiccProfileInfo.PROFILE_STATE_DISABLED ProfileState.Disabled -> EuiccProfileInfo.PROFILE_STATE_DISABLED
} }
) )
setProfileClass( setProfileClass(
when (it.profileClass) { when (it.profileClass) {
LocalProfileInfo.Clazz.Testing -> EuiccProfileInfo.PROFILE_CLASS_TESTING ProfileClass.Testing -> EuiccProfileInfo.PROFILE_CLASS_TESTING
LocalProfileInfo.Clazz.Provisioning -> EuiccProfileInfo.PROFILE_CLASS_PROVISIONING ProfileClass.Provisioning -> EuiccProfileInfo.PROFILE_CLASS_PROVISIONING
LocalProfileInfo.Clazz.Operational -> EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL ProfileClass.Operational -> EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL
} }
) )
}.build() }.build()

View file

@ -2,42 +2,14 @@ package net.typeblog.lpac_jni
data class LocalProfileInfo( data class LocalProfileInfo(
val iccid: String, val iccid: String,
val state: State, val state: ProfileState,
val name: String, val name: String,
val nickName: String, val nickName: String,
val providerName: String, val providerName: String,
val isdpAID: String, val isdpAID: String,
val profileClass: Clazz val profileClass: ProfileClass
) { )
enum class State {
Enabled,
Disabled;
companion object { enum class ProfileState { Enabled, Disabled }
@JvmStatic
fun fromString(str: String?) =
when (str?.lowercase()) {
"enabled" -> Enabled
"disabled" -> Disabled
else -> Disabled
}
}
}
enum class Clazz { enum class ProfileClass { Testing, Provisioning, Operational }
Testing,
Provisioning,
Operational;
companion object {
@JvmStatic
fun fromString(str: String?) =
when (str?.lowercase()) {
"test" -> Testing
"provisioning" -> Provisioning
"operational" -> Operational
else -> Operational
}
}
}
}

View file

@ -19,7 +19,7 @@ internal object LpacJni {
// es10c // es10c
// null returns signify errors // null returns signify errors
external fun es10cGetEid(handle: Long): String? external fun es10cGetEid(handle: Long): String?
external fun es10cGetProfilesInfo(handle: Long): Long external fun es10cGetProfilesInfo(handle: Long, profiles: List<LocalProfileInfo>): Long
external fun es10cEnableProfile(handle: Long, iccid: String, refresh: Boolean): Int external fun es10cEnableProfile(handle: Long, iccid: String, refresh: Boolean): Int
external fun es10cDisableProfile(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 es10cDeleteProfile(handle: Long, iccid: String): Int
@ -47,16 +47,6 @@ internal object LpacJni {
// C String arrays // C String arrays
external fun stringArrNext(curr: Long): Long external fun stringArrNext(curr: Long): Long
external fun stringDeref(curr: Long): String 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 // Notifications
external fun notificationsNext(curr: Long): Long external fun notificationsNext(curr: Long): Long
external fun notificationGetSeq(curr: Long): Long external fun notificationGetSeq(curr: Long): Long

View file

@ -107,26 +107,10 @@ class LocalProfileAssistantImpl(
override val profiles: List<LocalProfileInfo> override val profiles: List<LocalProfileInfo>
@Synchronized @Synchronized
get() { get() {
val head = LpacJni.es10cGetProfilesInfo(contextHandle) val profiles = mutableListOf<LocalProfileInfo>()
var curr = head val ret = LpacJni.es10cGetProfilesInfo(contextHandle, profiles)
val ret = mutableListOf<LocalProfileInfo>() if (ret < 0) throw IllegalStateException("Failed to get profiles")
while (curr != 0L) { return profiles
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
} }
override val notifications: List<LocalProfileNotification> override val notifications: List<LocalProfileNotification>

View file

@ -0,0 +1,57 @@
#include "lpac-convertor.h"
static jobject profile_state_enabled;
static jobject profile_state_disabled;
static jobject profile_class_operational;
static jobject profile_class_provisioning;
static jobject profile_class_testing;
static jobject bind_static_field(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
jfieldID field = (*env)->GetStaticFieldID(env, clazz, name, sig);
jobject bound = (*env)->GetStaticObjectField(env, clazz, field);
return (*env)->NewGlobalRef(env, bound);
}
#define BIND_PROFILE_STATE_STATIC_FIELD(NAME, FIELD) \
profile_state_##NAME = bind_static_field(env, profile_state_class, FIELD, "L" PROFILE_STATE_CLASS ";")
#define BIND_PROFILE_CLASS_STATIC_FIELD(NAME, FIELD) \
profile_class_##NAME = bind_static_field(env, profile_class_class, FIELD, "L" PROFILE_CLASS_CLASS ";")
void lpac_convertor_init(JNIEnv *env) {
jclass profile_state_class = (*env)->FindClass(env, PROFILE_STATE_CLASS);
BIND_PROFILE_STATE_STATIC_FIELD(enabled, "Enabled");
BIND_PROFILE_STATE_STATIC_FIELD(disabled, "Disabled");
jclass profile_class_class = (*env)->FindClass(env, PROFILE_CLASS_CLASS);
BIND_PROFILE_CLASS_STATIC_FIELD(operational, "Operational");
BIND_PROFILE_CLASS_STATIC_FIELD(provisioning, "Provisioning");
BIND_PROFILE_CLASS_STATIC_FIELD(testing, "Testing");
}
#undef BIND_PROFILE_STATE_STATIC_FIELD
#undef BIND_PROFILE_CLASS_STATIC_FIELD
jobject to_profile_state(enum es10c_profile_state profile_state) {
switch (profile_state) {
case ES10C_PROFILE_STATE_ENABLED:
return profile_state_enabled;
case ES10C_PROFILE_STATE_DISABLED:
return profile_state_disabled;
default:
return NULL;
}
}
jobject to_profile_class(enum es10c_profile_class profile_class) {
switch (profile_class) {
case ES10C_PROFILE_CLASS_OPERATIONAL:
return profile_class_operational;
case ES10C_PROFILE_CLASS_PROVISIONING:
return profile_class_provisioning;
case ES10C_PROFILE_CLASS_TEST:
return profile_class_testing;
default:
return NULL;
}
}

View file

@ -0,0 +1,13 @@
#pragma once
#include <jni.h>
#include <euicc/es10c.h>
#define PROFILE_STATE_CLASS "net/typeblog/lpac_jni/ProfileState"
#define PROFILE_CLASS_CLASS "net/typeblog/lpac_jni/ProfileClass"
void lpac_convertor_init(JNIEnv *env);
jobject to_profile_state(enum es10c_profile_state profile_state);
jobject to_profile_class(enum es10c_profile_class profile_class);

View file

@ -9,6 +9,7 @@
#include "lpac-download.h" #include "lpac-download.h"
#include "lpac-notifications.h" #include "lpac-notifications.h"
#include "interface-wrapper.h" #include "interface-wrapper.h"
#include "lpac-convertor.h"
JavaVM *jvm = NULL; JavaVM *jvm = NULL;
@ -17,12 +18,16 @@ jstring empty_string;
jclass string_class; jclass string_class;
jmethodID string_constructor; jmethodID string_constructor;
#define LOCAL_PROFILE_INFO_CLASS "net/typeblog/lpac_jni/LocalProfileInfo"
jint JNI_OnLoad(JavaVM *vm, void *reserved) { jint JNI_OnLoad(JavaVM *vm, void *reserved) {
jvm = vm; jvm = vm;
LPAC_JNI_SETUP_ENV;
interface_wrapper_init(); interface_wrapper_init();
lpac_convertor_init(env);
lpac_download_init(); lpac_download_init();
LPAC_JNI_SETUP_ENV;
string_class = (*env)->FindClass(env, "java/lang/String"); string_class = (*env)->FindClass(env, "java/lang/String");
string_class = (*env)->NewGlobalRef(env, string_class); string_class = (*env)->NewGlobalRef(env, string_class);
string_constructor = (*env)->GetMethodID(env, string_class, "<init>", string_constructor = (*env)->GetMethodID(env, string_class, "<init>",
@ -100,12 +105,12 @@ jstring toJString(JNIEnv *env, const char *pat) {
jbyteArray bytes = NULL; jbyteArray bytes = NULL;
jstring encoding = NULL; jstring encoding = NULL;
jstring jstr = NULL; jstring jstr = NULL;
int len; jsize len;
if (pat == NULL) if (pat == NULL)
return (*env)->NewLocalRef(env, empty_string); return (*env)->NewLocalRef(env, empty_string);
len = strlen(pat); len = (jsize) strlen(pat);
bytes = (*env)->NewByteArray(env, len); bytes = (*env)->NewByteArray(env, len);
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *) pat); (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *) pat);
encoding = (*env)->NewStringUTF(env, "utf-8"); encoding = (*env)->NewStringUTF(env, "utf-8");
@ -130,67 +135,56 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10cGetEid(JNIEnv *env, jobject thiz, jlong
} }
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_net_typeblog_lpac_1jni_LpacJni_es10cGetProfilesInfo(JNIEnv *env, jobject thiz, jlong handle) { Java_net_typeblog_lpac_1jni_LpacJni_es10cGetProfilesInfo(
JNIEnv *env,
__attribute__((unused)) jobject thiz,
jlong handle,
jobject profiles
) {
struct euicc_ctx *ctx = (struct euicc_ctx *) handle; struct euicc_ctx *ctx = (struct euicc_ctx *) handle;
struct es10c_profile_info_list *info = NULL; struct es10c_profile_info_list *info = NULL;
int ret = es10c_get_profiles_info(ctx, &info);
if (ret < 0) return ret;
if (es10c_get_profiles_info(ctx, &info) < 0) { jclass profile_list_class = (*env)->GetObjectClass(env, profiles);
return 0; 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(
env, profile_info_class, "<init>",
"("
"Ljava/lang/String;" // iccid
"Lnet/typeblog/lpac_jni/ProfileState;"
"Ljava/lang/String;" // name
"Ljava/lang/String;" // nickname
"Ljava/lang/String;" // provider name
"Ljava/lang/String;" // ISD-P AID
"Lnet/typeblog/lpac_jni/ProfileClass;"
")"
"V" // (returns) void
);
jobject element = NULL;
while (info) {
element = (*env)->NewObject(
env, profile_info_class, profile_info_class_constructor,
toJString(env, info->iccid),
to_profile_state(info->profileState),
toJString(env, info->profileName),
toJString(env, info->profileNickname),
toJString(env, info->serviceProviderName),
toJString(env, info->isdpAid),
to_profile_class(info->profileClass)
);
(*env)->CallBooleanMethod(env, profiles, add_profile, element);
info = info->next;
} }
return (jlong) info; es10c_profile_info_list_free_all(info);
return ret;
} }
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;
const char *profileStateStr = NULL;
switch (info->profileState) {
case ES10C_PROFILE_STATE_ENABLED:
profileStateStr = "enabled";
break;
case ES10C_PROFILE_STATE_DISABLED:
profileStateStr = "disabled";
break;
default:
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;
switch (info->profileClass) {
case ES10C_PROFILE_CLASS_TEST:
profileClassStr = "test";
break;
case ES10C_PROFILE_CLASS_PROVISIONING:
profileClassStr = "provisioning";
break;
case ES10C_PROFILE_CLASS_OPERATIONAL:
profileClassStr = "operational";
break;
default:
profileClassStr = "unknown";
break;
}
return toJString(env, profileClassStr);
}
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 jint JNICALL JNIEXPORT jint JNICALL
Java_net_typeblog_lpac_1jni_LpacJni_es10cEnableProfile(JNIEnv *env, jobject thiz, jlong handle, Java_net_typeblog_lpac_1jni_LpacJni_es10cEnableProfile(JNIEnv *env, jobject thiz, jlong handle,
jstring iccid, jboolean refresh) { jstring iccid, jboolean refresh) {
@ -259,7 +253,6 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10cexGetEuiccInfo2(JNIEnv *env, jobject th
return (jlong) info; return (jlong) info;
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_net_typeblog_lpac_1jni_LpacJni_es10cEuiccMemoryReset(JNIEnv *env, jobject thiz, jlong handle) { Java_net_typeblog_lpac_1jni_LpacJni_es10cEuiccMemoryReset(JNIEnv *env, jobject thiz, jlong handle) {
struct euicc_ctx *ctx = (struct euicc_ctx *) handle; struct euicc_ctx *ctx = (struct euicc_ctx *) handle;