refactor: notification list (lpac-jni) #170

Closed
septs wants to merge 1 commit from septs:refactor-notification-jni into master
7 changed files with 126 additions and 89 deletions

View file

@ -26,6 +26,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import net.typeblog.lpac_jni.LocalProfileNotification
import net.typeblog.lpac_jni.ProfileManagementOperation
class NotificationsActivity: BaseEuiccAccessActivity(), OpenEuiccContextMarker {
private lateinit var swipeRefresh: SwipeRefreshLayout
@ -163,14 +164,14 @@ class NotificationsActivity: BaseEuiccAccessActivity(), OpenEuiccContextMarker {
}
private fun operationToLocalizedText(operation: LocalProfileNotification.Operation) =
root.context.getText(
when (operation) {
LocalProfileNotification.Operation.Install -> R.string.profile_notification_operation_download
LocalProfileNotification.Operation.Delete -> R.string.profile_notification_operation_delete
LocalProfileNotification.Operation.Enable -> R.string.profile_notification_operation_enable
LocalProfileNotification.Operation.Disable -> R.string.profile_notification_operation_disable
})
private fun operationToLocalizedText(operation: ProfileManagementOperation) =
root.context.getText(when (operation) {
ProfileManagementOperation.Install -> R.string.profile_notification_operation_download
ProfileManagementOperation.Delete -> R.string.profile_notification_operation_delete
ProfileManagementOperation.Enable -> R.string.profile_notification_operation_enable
ProfileManagementOperation.Disable -> R.string.profile_notification_operation_disable
else -> throw IllegalStateException("Unknown operation")
})
fun updateNotification(value: LocalProfileNotificationWrapper) {
notification = value

View file

@ -2,26 +2,15 @@ package net.typeblog.lpac_jni
data class LocalProfileNotification(
val seqNumber: Long,
val profileManagementOperation: Operation,
val profileManagementOperation: ProfileManagementOperation,
val notificationAddress: String,
val iccid: String,
) {
enum class Operation {
Install,
Enable,
Disable,
Delete;
)
companion object {
@JvmStatic
fun fromString(str: String?) =
when (str?.lowercase()) {
"install" -> Install
"enable" -> Enable
"disable" -> Disable
"delete" -> Delete
else -> throw IllegalArgumentException("Unknown operation $str")
}
}
}
}
enum class ProfileManagementOperation {
Install,
Enable,
Disable,
Delete,
Unknown,
}

View file

@ -26,7 +26,7 @@ internal object LpacJni {
external fun es10cSetNickname(handle: Long, iccid: String, nickNullTerminated: ByteArray): 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, elements: List<LocalProfileNotification>): Int
external fun es10bDeleteNotification(handle: Long, seqNumber: Long): Int
// es9p + es10b
@ -57,13 +57,6 @@ internal object LpacJni {
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 euiccInfo2GetSGP22Version(info: Long): String

View file

@ -132,20 +132,10 @@ class LocalProfileAssistantImpl(
override val notifications: List<LocalProfileNotification>
@Synchronized
get() {
val head = LpacJni.es10bListNotification(contextHandle)
var curr = head
val ret = mutableListOf<LocalProfileNotification>()
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()
val notifications = mutableListOf<LocalProfileNotification>()
val ret = LpacJni.es10bListNotification(contextHandle, notifications)
if (ret < 0) throw IllegalStateException("Failed to list notifications")
return notifications.sortedBy(LocalProfileNotification::seqNumber).reversed()
}
override val eID: String

View file

@ -19,10 +19,12 @@ jmethodID string_constructor;
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
jvm = vm;
LPAC_JNI_SETUP_ENV;
interface_wrapper_init();
lpac_download_init();
lpac_notifications_init(env);
LPAC_JNI_SETUP_ENV;
string_class = (*env)->FindClass(env, "java/lang/String");
string_class = (*env)->NewGlobalRef(env, string_class);
string_constructor = (*env)->GetMethodID(env, string_class, "<init>",

View file

@ -4,15 +4,107 @@
#include <malloc.h>
#include <syslog.h>
JNIEXPORT jlong JNICALL
Java_net_typeblog_lpac_1jni_LpacJni_es10bListNotification(JNIEnv *env, jobject thiz, jlong handle) {
jclass local_profile_notification_class;
jobject profile_management_operation_install;
jobject profile_management_operation_enable;
jobject profile_management_operation_disable;
jobject profile_management_operation_delete;
jobject profile_management_operation_unknown;
jmethodID local_profile_notification_constructor;
#define LOCAL_PROFILE_NOTIFICATION_CLASS "net/typeblog/lpac_jni/LocalProfileNotification"
#define PROFILE_MANAGEMENT_OPERATION_CLASS "net/typeblog/lpac_jni/ProfileManagementOperation"
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_NOTIFICATION_OPERATION_FIELD(NAME, FIELD) \
profile_management_operation_##NAME = bind_static_field( \
env, profile_management_operation_class, FIELD, "L" PROFILE_MANAGEMENT_OPERATION_CLASS ";")
void lpac_notifications_init(JNIEnv *env) {
local_profile_notification_class = (*env)->FindClass(env, LOCAL_PROFILE_NOTIFICATION_CLASS);
local_profile_notification_class = (*env)->NewGlobalRef(env, local_profile_notification_class);
local_profile_notification_constructor = (*env)->GetMethodID(
env, local_profile_notification_class, "<init>",
"("
"J" // seqNumber
"L" PROFILE_MANAGEMENT_OPERATION_CLASS ";" // profileManagementOperation
"Ljava/lang/String;" // notificationAddress
"Ljava/lang/String;" // iccid
")"
"V" // (returns) void
);
jclass profile_management_operation_class = (*env)->FindClass(
env, PROFILE_MANAGEMENT_OPERATION_CLASS);
profile_management_operation_class = (*env)->NewGlobalRef(
env, profile_management_operation_class);
BIND_NOTIFICATION_OPERATION_FIELD(install, "Install");
BIND_NOTIFICATION_OPERATION_FIELD(delete, "Delete");
BIND_NOTIFICATION_OPERATION_FIELD(enable, "Enable");
BIND_NOTIFICATION_OPERATION_FIELD(disable, "Disable");
BIND_NOTIFICATION_OPERATION_FIELD(unknown, "Unknown");
}
#undef BIND_NOTIFICATION_OPERATION_FIELD
static jobject to_profile_management_operation(enum es10b_profile_management_operation operation) {
switch (operation) {
case ES10B_PROFILE_MANAGEMENT_OPERATION_INSTALL:
return profile_management_operation_install;
case ES10B_PROFILE_MANAGEMENT_OPERATION_DELETE:
return profile_management_operation_delete;
case ES10B_PROFILE_MANAGEMENT_OPERATION_ENABLE:
return profile_management_operation_enable;
case ES10B_PROFILE_MANAGEMENT_OPERATION_DISABLE:
return profile_management_operation_disable;
default:
return profile_management_operation_unknown;
}
}
JNIEXPORT jint JNICALL
Java_net_typeblog_lpac_1jni_LpacJni_es10bListNotification(
JNIEnv *env,
__attribute__((unused)) jobject thiz,
jlong handle,
jobject notifications
) {
struct euicc_ctx *ctx = (struct euicc_ctx *) handle;
struct es10b_notification_metadata_list *info = NULL;
struct es10b_notification_metadata_list *metadata = NULL;
int ret = es10b_list_notification(ctx, &metadata);
if (ret < 0) {
goto out;
}
if (es10b_list_notification(ctx, &info) < 0)
return 0;
jmethodID add_notification = (*env)->GetMethodID(
env,
(*env)->GetObjectClass(env, notifications),
"add", "(Ljava/lang/Object;)Z"
);
return (jlong) info;
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,
sequence_number, operation, address, iccid);
(*env)->CallBooleanMethod(env, notifications, add_notification, element);
metadata = metadata->next;
}
out:
es10b_notification_metadata_list_free_all(metadata);
return ret;
}
JNIEXPORT jint JNICALL
@ -45,35 +137,3 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10bDeleteNotification(JNIEnv *env, jobject
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)

View file

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