refactor: [1/n] Introduce the lpac project and lpac_jni
This commit is contained in:
parent
87cdb24579
commit
85af3bcfc0
24 changed files with 429 additions and 18 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "libs/lpac-jni/src/main/jni/lpac"]
|
||||
path = libs/lpac-jni/src/main/jni/lpac
|
||||
url = https://github.com/estkme/lpac
|
7
.idea/compiler.xml
generated
7
.idea/compiler.xml
generated
|
@ -4,9 +4,10 @@
|
|||
<bytecodeTargetLevel target="1.7">
|
||||
<module name="OpenEUICC.app" target="17" />
|
||||
<module name="OpenEUICC.libs.hidden-apis-shim" target="17" />
|
||||
<module name="OpenEUICC.libs.lpad-sm-dp-plus-connector" target="1.8" />
|
||||
<module name="OpenEUICC.libs.lpad-sm-dp-plus-connector.main" target="1.8" />
|
||||
<module name="OpenEUICC.libs.lpad-sm-dp-plus-connector.test" target="1.8" />
|
||||
<module name="OpenEUICC.libs.lpac-jni" target="17" />
|
||||
<module name="OpenEUICC.libs.lpad-sm-dp-plus-connector" target="17" />
|
||||
<module name="OpenEUICC.libs.lpad-sm-dp-plus-connector.main" target="17" />
|
||||
<module name="OpenEUICC.libs.lpad-sm-dp-plus-connector.test" target="17" />
|
||||
</bytecodeTargetLevel>
|
||||
</component>
|
||||
</project>
|
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
|
@ -16,6 +16,7 @@
|
|||
<option value="$PROJECT_DIR$/libs" />
|
||||
<option value="$PROJECT_DIR$/libs/hidden-apis-shim" />
|
||||
<option value="$PROJECT_DIR$/libs/hidden-apis-stub" />
|
||||
<option value="$PROJECT_DIR$/libs/lpac-jni" />
|
||||
<option value="$PROJECT_DIR$/libs/lpad-sm-dp-plus-connector" />
|
||||
</set>
|
||||
</option>
|
||||
|
|
2
.idea/kotlinc.xml
generated
2
.idea/kotlinc.xml
generated
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.6.21" />
|
||||
<option name="version" value="1.9.20" />
|
||||
</component>
|
||||
</project>
|
|
@ -37,7 +37,7 @@ def keystoreProperties = new Properties()
|
|||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
|
||||
android {
|
||||
compileSdk 31
|
||||
compileSdk 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId "im.angry.openeuicc"
|
||||
|
@ -81,11 +81,12 @@ dependencies {
|
|||
compileOnly project(':libs:hidden-apis-stub')
|
||||
implementation project(':libs:hidden-apis-shim')
|
||||
implementation project(":libs:lpad-sm-dp-plus-connector")
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'com.google.android.material:material:1.6.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
|
||||
implementation project(":libs:lpac-jni")
|
||||
implementation 'androidx.core:core-ktx:1.12.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.10.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||
implementation "androidx.cardview:cardview:1.0.0"
|
||||
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
plugins {
|
||||
id 'com.android.application' version '8.1.2' apply false
|
||||
id 'com.android.library' version '8.1.2' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
|
||||
id 'org.jetbrains.kotlin.multiplatform' version '1.6.21' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.9.20' apply false
|
||||
id 'org.jetbrains.kotlin.multiplatform' version '1.9.20' apply false
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
|
|
46
libs/lpac-jni/build.gradle
Normal file
46
libs/lpac-jni/build.gradle
Normal file
|
@ -0,0 +1,46 @@
|
|||
plugins {
|
||||
id 'com.android.library'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'net.typeblog.lpac_jni'
|
||||
compileSdk 33
|
||||
|
||||
defaultConfig {
|
||||
minSdk 27
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
path "src/main/jni/Android.mk"
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation 'androidx.core:core-ktx:1.12.0'
|
||||
implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.10.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
}
|
0
libs/lpac-jni/consumer-rules.pro
Normal file
0
libs/lpac-jni/consumer-rules.pro
Normal file
21
libs/lpac-jni/proguard-rules.pro
vendored
Normal file
21
libs/lpac-jni/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,24 @@
|
|||
package net.typeblog.lpac_jni
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("net.typeblog.lpac_jni.test", appContext.packageName)
|
||||
}
|
||||
}
|
4
libs/lpac-jni/src/main/AndroidManifest.xml
Normal file
4
libs/lpac-jni/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,12 @@
|
|||
package net.typeblog.lpac_jni
|
||||
|
||||
/*
|
||||
* Should reflect euicc_apdu_interface in lpac/euicc/interface.h
|
||||
*/
|
||||
sealed interface ApduInterface {
|
||||
fun connect()
|
||||
fun disconnect()
|
||||
fun logicalChannelOpen(aid: ByteArray): Int
|
||||
fun logicalChannelClose(handle: Int)
|
||||
fun transmit(tx: ByteArray): ByteArray
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package net.typeblog.lpac_jni
|
||||
|
||||
/*
|
||||
* Should reflect euicc_http_interface in lpac/euicc/interface.h
|
||||
*/
|
||||
sealed interface HttpInterface {
|
||||
data class HttpResponse(val rcode: Int, val data: ByteArray) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as HttpResponse
|
||||
|
||||
if (rcode != other.rcode) return false
|
||||
if (!data.contentEquals(other.data)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = rcode
|
||||
result = 31 * result + data.contentHashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
fun transmit(url: String, tx: ByteArray): HttpResponse
|
||||
}
|
11
libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LpacJni.kt
Normal file
11
libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/LpacJni.kt
Normal file
|
@ -0,0 +1,11 @@
|
|||
package net.typeblog.lpac_jni
|
||||
|
||||
private class LpacJni {
|
||||
init {
|
||||
System.loadLibrary("lpac-jni")
|
||||
}
|
||||
|
||||
external fun createContext(apduInterface: ApduInterface, httpInterface: HttpInterface): Long
|
||||
external fun destroyContext(handle: Long)
|
||||
external fun setCurrentContext(handle: Long)
|
||||
}
|
46
libs/lpac-jni/src/main/jni/Android.mk
Normal file
46
libs/lpac-jni/src/main/jni/Android.mk
Normal file
|
@ -0,0 +1,46 @@
|
|||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# function to find all *.c files under a directory
|
||||
define all-c-files-under
|
||||
$(patsubst ./%,%, \
|
||||
$(shell cd $(LOCAL_PATH) ; \
|
||||
find $(1) -name "*.c" -and -not -name ".*" -maxdepth 1) \
|
||||
)
|
||||
endef
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
# libcjson
|
||||
LOCAL_MODULE := lpac-cjson
|
||||
LOCAL_SRC_FILES := \
|
||||
$(call all-c-files-under, lpac/cjson)
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
# libasn1c, the ASN parser component from lpac
|
||||
LOCAL_MODULE := lpac-asn1c
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/lpac/euicc/asn1c
|
||||
LOCAL_SRC_FILES := \
|
||||
$(call all-c-files-under, lpac/euicc/asn1c/asn1)
|
||||
LOCAL_CFLAGS := -DHAVE_CONFIG_H
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
# libeuicc component from lpac, which contains the actual implementation
|
||||
LOCAL_MODULE := lpac-euicc
|
||||
LOCAL_STATIC_LIBRARIES := lpac-asn1c lpac-cjson
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/lpac
|
||||
LOCAL_SRC_FILES := \
|
||||
$(call all-c-files-under, lpac/euicc)
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := lpac-jni
|
||||
LOCAL_STATIC_LIBRARIES := lpac-euicc
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/lpac
|
||||
LOCAL_SRC_FILES := \
|
||||
lpac-jni/lpac-jni.c \
|
||||
lpac-jni/interface-wrapper.c
|
||||
include $(BUILD_SHARED_LIBRARY)
|
1
libs/lpac-jni/src/main/jni/Application.mk
Normal file
1
libs/lpac-jni/src/main/jni/Application.mk
Normal file
|
@ -0,0 +1 @@
|
|||
APP_ABI := all
|
1
libs/lpac-jni/src/main/jni/lpac
Submodule
1
libs/lpac-jni/src/main/jni/lpac
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 2eaefa6f8d79f68eff6a8c03932b861425767330
|
117
libs/lpac-jni/src/main/jni/lpac-jni/interface-wrapper.c
Normal file
117
libs/lpac-jni/src/main/jni/lpac-jni/interface-wrapper.c
Normal file
|
@ -0,0 +1,117 @@
|
|||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include "interface-wrapper.h"
|
||||
#include "lpac-jni.h"
|
||||
|
||||
jmethodID method_apdu_connect;
|
||||
jmethodID method_apdu_disconnect;
|
||||
jmethodID method_apdu_logical_channel_open;
|
||||
jmethodID method_apdu_logical_channel_close;
|
||||
jmethodID method_apdu_transmit;
|
||||
|
||||
jmethodID method_http_transmit;
|
||||
|
||||
jfieldID field_resp_rcode;
|
||||
jfieldID field_resp_data;
|
||||
|
||||
void interface_wrapper_init() {
|
||||
LPAC_JNI_SETUP_ENV;
|
||||
jclass apdu_class = (*env)->FindClass(env, "net/typeblog/lpac_jni/ApduInterface");
|
||||
method_apdu_connect = (*env)->GetMethodID(env, apdu_class, "connect", "()V");
|
||||
method_apdu_disconnect = (*env)->GetMethodID(env, apdu_class, "disconnect", "()V");
|
||||
method_apdu_logical_channel_open = (*env)->GetMethodID(env, apdu_class, "logicalChannelOpen", "([B)I");
|
||||
method_apdu_logical_channel_close = (*env)->GetMethodID(env, apdu_class, "logicalChannelClose", "(I)V");
|
||||
method_apdu_transmit = (*env)->GetMethodID(env, apdu_class, "transmit", "([B)[B");
|
||||
|
||||
jclass http_class = (*env)->FindClass(env, "net/typeblog/lpac_jni/HttpInterface");
|
||||
method_http_transmit = (*env)->GetMethodID(env, http_class, "transmit",
|
||||
"(Ljava/lang/String;[B)Lnet/typeblog/lpac_jni/HttpInterface$HttpResponse;");
|
||||
|
||||
jclass resp_class = (*env)->FindClass(env, "net/typeblog/lpac_jni/HttpInterface$HttpResponse");
|
||||
field_resp_rcode = (*env)->GetFieldID(env, resp_class, "rcode", "I");
|
||||
field_resp_data = (*env)->GetFieldID(env, resp_class, "data", "[B");
|
||||
}
|
||||
|
||||
static int apdu_interface_connect(void) {
|
||||
LPAC_JNI_BEGIN;
|
||||
LPAC_JNI_ASSERT_CTX;
|
||||
LPAC_JNI_SETUP_ENV;
|
||||
(*env)->CallVoidMethod(env, jni_ctx->apdu_interface, method_apdu_connect);
|
||||
LPAC_JNI_END(!((*env)->ExceptionCheck(env) == JNI_FALSE));
|
||||
}
|
||||
|
||||
static void apdu_interface_disconnect(void) {
|
||||
LPAC_JNI_BEGIN;
|
||||
LPAC_JNI_ASSERT_CTX;
|
||||
LPAC_JNI_SETUP_ENV;
|
||||
(*env)->CallVoidMethod(env, jni_ctx->apdu_interface, method_apdu_disconnect);
|
||||
LPAC_JNI_END0;
|
||||
}
|
||||
|
||||
static int apdu_interface_logical_channel_open(const uint8_t *aid, uint8_t aid_len) {
|
||||
LPAC_JNI_BEGIN;
|
||||
LPAC_JNI_ASSERT_CTX;
|
||||
LPAC_JNI_SETUP_ENV;
|
||||
jbyteArray jbarr = (*env)->NewByteArray(env, aid_len);
|
||||
(*env)->SetByteArrayRegion(env, jbarr, 0, aid_len, (const jbyte *) aid);
|
||||
jint ret = (*env)->CallIntMethod(env, jni_ctx->apdu_interface, method_apdu_logical_channel_open, jbarr);
|
||||
if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
|
||||
LPAC_JNI_END(-1);
|
||||
} else {
|
||||
LPAC_JNI_END(ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void apdu_interface_logical_channel_close(uint8_t channel) {
|
||||
LPAC_JNI_BEGIN;
|
||||
LPAC_JNI_ASSERT_CTX;
|
||||
LPAC_JNI_SETUP_ENV;
|
||||
(*env)->CallVoidMethod(env, jni_ctx->apdu_interface, method_apdu_logical_channel_close, channel);
|
||||
LPAC_JNI_END0;
|
||||
}
|
||||
|
||||
static int apdu_interface_transmit(uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len) {
|
||||
LPAC_JNI_BEGIN;
|
||||
LPAC_JNI_ASSERT_CTX;
|
||||
LPAC_JNI_SETUP_ENV;
|
||||
jbyteArray txArr = (*env)->NewByteArray(env, tx_len);
|
||||
(*env)->SetByteArrayRegion(env, txArr, 0, tx_len, (const jbyte *) tx);
|
||||
jbyteArray ret = (jbyteArray) (*env)->CallObjectMethod(env, jni_ctx->apdu_interface, method_apdu_transmit, txArr);
|
||||
if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
|
||||
LPAC_JNI_END(-1);
|
||||
}
|
||||
*rx_len = (*env)->GetArrayLength(env, ret);
|
||||
*rx = malloc(*rx_len * sizeof(uint8_t));
|
||||
(*env)->GetByteArrayRegion(env, ret, 0, *rx_len, *rx);
|
||||
LPAC_JNI_END(0);
|
||||
}
|
||||
|
||||
static int http_interface_transmit(const char *url, uint32_t *rcode, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len) {
|
||||
LPAC_JNI_BEGIN;
|
||||
LPAC_JNI_ASSERT_CTX;
|
||||
LPAC_JNI_SETUP_ENV;
|
||||
jstring jurl = (*env)->NewString(env, url, strlen(url));
|
||||
jbyteArray txArr = (*env)->NewByteArray(env, tx_len);
|
||||
(*env)->SetByteArrayRegion(env, txArr, 0, tx_len, (const jbyte *) tx);
|
||||
jobject ret = (*env)->CallObjectMethod(env, jni_ctx->http_interface, method_http_transmit, jurl, txArr);
|
||||
if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
|
||||
LPAC_JNI_END(-1);
|
||||
}
|
||||
*rcode = (*env)->GetIntField(env, ret, field_resp_rcode);
|
||||
jbyteArray rxArr = (jbyteArray) (*env)->GetObjectField(env, ret, field_resp_data);
|
||||
*rx_len = (*env)->GetArrayLength(env, rxArr);
|
||||
*rx = malloc(*rx_len * sizeof(uint8_t));
|
||||
(*env)->GetByteArrayRegion(env, rxArr, 0, *rx_len, *rx);
|
||||
LPAC_JNI_END(0);
|
||||
}
|
||||
|
||||
struct euicc_apdu_interface apdu_interface_wrapper = {
|
||||
.connect = apdu_interface_connect,
|
||||
.disconnect = apdu_interface_disconnect,
|
||||
.logic_channel_open = apdu_interface_logical_channel_open,
|
||||
.logic_channel_close = apdu_interface_logical_channel_close,
|
||||
.transmit = apdu_interface_transmit
|
||||
};
|
||||
struct euicc_http_interface http_interface_wrapper = {
|
||||
.transmit = http_interface_transmit
|
||||
};
|
14
libs/lpac-jni/src/main/jni/lpac-jni/interface-wrapper.h
Normal file
14
libs/lpac-jni/src/main/jni/lpac-jni/interface-wrapper.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
#undef NDEBUG
|
||||
#include <assert.h>
|
||||
#include <euicc/interface.h>
|
||||
|
||||
extern struct euicc_apdu_interface apdu_interface_wrapper;
|
||||
extern struct euicc_http_interface http_interface_wrapper;
|
||||
|
||||
void interface_wrapper_init();
|
||||
|
||||
#define LPAC_JNI_ASSERT_CTX assert(jni_ctx != NULL)
|
||||
#define LPAC_JNI_SETUP_ENV \
|
||||
JNIEnv *env; \
|
||||
(*jvm)->AttachCurrentThread(jvm, &env, NULL)
|
49
libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c
Normal file
49
libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include <euicc/interface.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include "lpac-jni.h"
|
||||
#include "interface-wrapper.h"
|
||||
|
||||
pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
struct lpac_jni_ctx *jni_ctx = NULL;
|
||||
JavaVM *jvm = NULL;
|
||||
|
||||
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
jvm = vm;
|
||||
interface_wrapper_init();
|
||||
return 1;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_net_typeblog_lpac_1jni_LpacJni_createContext(JNIEnv *env, jobject thiz,
|
||||
jobject apdu_interface,
|
||||
jobject http_interface) {
|
||||
LPAC_JNI_BEGIN;
|
||||
struct lpac_jni_ctx *_ctx = malloc(sizeof(struct lpac_jni_ctx));
|
||||
memset(_ctx, 0, sizeof(struct lpac_jni_ctx));
|
||||
_ctx->ctx.interface.apdu = &apdu_interface_wrapper;
|
||||
_ctx->ctx.interface.http = &http_interface_wrapper;
|
||||
_ctx->apdu_interface = (*env)->NewGlobalRef(env, apdu_interface);
|
||||
_ctx->http_interface = (*env)->NewGlobalRef(env, http_interface);
|
||||
LPAC_JNI_END((jlong) _ctx);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_typeblog_lpac_1jni_LpacJni_destroyContext(JNIEnv *env, jobject thiz, jlong handle) {
|
||||
LPAC_JNI_BEGIN;
|
||||
struct lpac_jni_ctx *_ctx = (struct lpac_jni_ctx *) handle;
|
||||
(*env)->DeleteGlobalRef(env, _ctx->apdu_interface);
|
||||
(*env)->DeleteGlobalRef(env, _ctx->http_interface);
|
||||
if (jni_ctx == _ctx) {
|
||||
jni_ctx = NULL;
|
||||
}
|
||||
free(_ctx);
|
||||
LPAC_JNI_END0;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_typeblog_lpac_1jni_LpacJni_setCurrentContext(JNIEnv *env, jobject thiz, jlong handle) {
|
||||
LPAC_JNI_BEGIN;
|
||||
jni_ctx = (struct lpac_jni_ctx *) handle;
|
||||
LPAC_JNI_END0;
|
||||
}
|
18
libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.h
Normal file
18
libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
#include <euicc/euicc.h>
|
||||
#include <pthread.h>
|
||||
#include <jni.h>
|
||||
|
||||
struct lpac_jni_ctx {
|
||||
struct euicc_ctx ctx;
|
||||
jobject apdu_interface;
|
||||
jobject http_interface;
|
||||
};
|
||||
|
||||
extern JavaVM *jvm;
|
||||
extern pthread_mutex_t global_lock;
|
||||
extern struct lpac_jni_ctx *jni_ctx;
|
||||
|
||||
#define LPAC_JNI_BEGIN pthread_mutex_lock(&global_lock)
|
||||
#define LPAC_JNI_END0 pthread_mutex_unlock(&global_lock)
|
||||
#define LPAC_JNI_END(ret) LPAC_JNI_END0; return ret
|
|
@ -0,0 +1,17 @@
|
|||
package net.typeblog.lpac_jni
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
|
@ -26,9 +26,4 @@ task genAsn1(type: JavaExec) {
|
|||
compileJava.dependsOn genAsn1
|
||||
compileKotlin.dependsOn genAsn1
|
||||
|
||||
description = 'LPAd SM-DP+ Connector'
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
description = 'LPAd SM-DP+ Connector'
|
|
@ -16,3 +16,4 @@ rootProject.name = "OpenEUICC"
|
|||
include ':app', ':libs:lpad-sm-dp-plus-connector'
|
||||
include ':libs:hidden-apis-stub'
|
||||
include ':libs:hidden-apis-shim'
|
||||
include ':libs:lpac-jni'
|
||||
|
|
Loading…
Add table
Reference in a new issue