From 6fd7cc99e3346d00a04750eb795d719ee8d17c05 Mon Sep 17 00:00:00 2001 From: George Nash Date: Tue, 9 Jul 2019 16:51:20 -0700 Subject: [PATCH] Work on oc_iotivity_lite_jni.h Break oc_iotivity_lite_jni.h into header and code file, this helps solve many build issues that resulted from not doing this. Moved the JNI_onload function from the storage code to this new location. This makes it possible to store pointer to the JavaVM as soon as the library is loaded. This helps remove many of the workarounds that were added to the code to grab the JavaVM pointer. All of the Java jclass varaible are now loaded in the JNI_onload function. This insures that the classes are avalible to the jni code instantly. No need to make sure the OCMain.init function is called before using a Java class in the jni code. Added some functions to manage the jni_callbacks list. Insuring all jni_callback_data is managed and stored in this central location. Change-Id: I426cb39e9a233cbddd754011b3a3939a72df3257 Signed-off-by: George Nash --- .../iotivity-lite-jni.vcxproj | 3 + .../iotivity-lite-jni.vcxproj.filters | 15 +- swig/Makefile | 6 + swig/java_lang/.gitignore | 4 - swig/java_lang/build_swig.sh | 3 +- swig/java_lang/oc_iotivity_lite_jni.c | 352 ++++++++++++++++++ swig/java_lang/oc_iotivity_lite_jni.h | 146 +++++--- swig/swig_interfaces/iotivity.swg | 31 +- swig/swig_interfaces/oc_api.i | 203 ++-------- swig/swig_interfaces/oc_cloud.i | 10 +- swig/swig_interfaces/oc_core_res.i | 7 +- swig/swig_interfaces/oc_endpoint.i | 1 + swig/swig_interfaces/oc_obt.i | 38 +- swig/swig_interfaces/oc_storage.i | 91 ----- 14 files changed, 507 insertions(+), 403 deletions(-) delete mode 100644 swig/java_lang/.gitignore create mode 100644 swig/java_lang/oc_iotivity_lite_jni.c diff --git a/port/windows/vs2015/iotivity-lite-jni/iotivity-lite-jni.vcxproj b/port/windows/vs2015/iotivity-lite-jni/iotivity-lite-jni.vcxproj index c822b56f5..cb69f7f49 100644 --- a/port/windows/vs2015/iotivity-lite-jni/iotivity-lite-jni.vcxproj +++ b/port/windows/vs2015/iotivity-lite-jni/iotivity-lite-jni.vcxproj @@ -118,6 +118,7 @@ xcopy /s /y /d /q $(SolutionDir)..\..\..\swig\java_lang\*.h $(SolutionDir)..\..\..\swig\iotivity-lite-java\jni\ +xcopy /s /y /d /q $(SolutionDir)..\..\..\swig\java_lang\*.c $(SolutionDir)..\..\..\swig\iotivity-lite-java\jni\ xcopy /s /y /d /q $(SolutionDir)..\..\..\swig\oc_java\*.java $(SolutionDir)..\..\..\swig\iotivity-lite-java\src\org\iotivity xcopy /s /y /d /q $(SolutionDir)..\..\..\swig\oc_java\oc\*.java $(SolutionDir)..\..\..\swig\iotivity-lite-java\src\org\iotivity\oc Copying dependency files into project. @@ -153,6 +154,7 @@ del $(SolutionDir)..\..\..\swig\iotivity-lite-java\src\org\iotivity\oc\*.java xcopy /s /y /d /q $(SolutionDir)..\..\..\swig\java_lang\*.h $(SolutionDir)..\..\..\swig\iotivity-lite-java\jni\ +xcopy /s /y /d /q $(SolutionDir)..\..\..\swig\java_lang\*.c $(SolutionDir)..\..\..\swig\iotivity-lite-java\jni\ xcopy /s /y /d /q $(SolutionDir)..\..\..\swig\oc_java\*.java $(SolutionDir)..\..\..\swig\iotivity-lite-java\src\org\iotivity xcopy /s /y /d /q $(SolutionDir)..\..\..\swig\oc_java\oc\*.java $(SolutionDir)..\..\..\swig\iotivity-lite-java\src\org\iotivity\oc Copying dependency files into project. @@ -264,6 +266,7 @@ del $(SolutionDir)..\..\..\swig\iotivity-lite-java\src\org\iotivity\oc\*.java + diff --git a/port/windows/vs2015/iotivity-lite-jni/iotivity-lite-jni.vcxproj.filters b/port/windows/vs2015/iotivity-lite-jni/iotivity-lite-jni.vcxproj.filters index 83da2a768..ab79761db 100644 --- a/port/windows/vs2015/iotivity-lite-jni/iotivity-lite-jni.vcxproj.filters +++ b/port/windows/vs2015/iotivity-lite-jni/iotivity-lite-jni.vcxproj.filters @@ -43,6 +43,9 @@ c_wrap + + c_wrap + @@ -62,12 +65,6 @@ swig_interfaces - - swig_interfaces - - - swig_interfaces - @@ -106,6 +103,12 @@ swig_interfaces + + swig_interfaces + + + swig_interfaces + diff --git a/swig/Makefile b/swig/Makefile index c4822df50..74d0724a7 100644 --- a/swig/Makefile +++ b/swig/Makefile @@ -81,6 +81,7 @@ SRC = oc_uuid oc_endpoint oc_rep oc_collection oc_clock oc_storage \ # Swig interfaces source SWIG_INTERFACE_SRC = $(addsuffix .i, $(SRC)) JNI_SRC = $(addsuffix _wrap.c, $(SRC)) +JNI_SRC += oc_iotivity_lite_jni.c ifeq ($(OS),linux) EXTRA_HEADER_FILE = -I"$(JAVA_HOME)/include/" -I"$(JAVA_HOME)/include/linux/" @@ -117,6 +118,7 @@ build_swig: $(SWIG_INTERFACE_SRC) copy_java copy_java: cp $(JAVA_LANG_DIR)*.h $(IOTIVITY_LITE_JAVA_JNI_DIR) + cp $(JAVA_LANG_DIR)*.c $(IOTIVITY_LITE_JAVA_JNI_DIR) cp $(OC_JAVA_DIR)*.java $(IOTIVITY_LITE_JAVA_SRC_DIR)$(PACKAGE_DIR) mkdir -p $(IOTIVITY_LITE_JAVA_SRC_DIR)$(PACKAGE_DIR)oc/ cp $(OC_JAVA_DIR)oc/*.java $(IOTIVITY_LITE_JAVA_SRC_DIR)$(PACKAGE_DIR)oc/ @@ -148,6 +150,10 @@ install_android_libs: build_swig build_jar build_jni_so mkdir -p $(JAVA_LANG_OBJ_DIR) $(CC) -c -o $(JAVA_LANG_OBJ_DIR)$(addsuffix .o, $(basename $@)) $(IOTIVITY_LITE_JAVA_JNI_DIR)$@ $(JNIFLAG) $(EXTRA_HEADER_FILE) $(HEADER_FILE) $(EXTRA_FLAG) $(DTLSFLAGS) +oc_iotivity_lite_jni.c: + mkdir -p $(JAVA_LANG_OBJ_DIR) + $(CC) -c -o $(JAVA_LANG_OBJ_DIR)$(addsuffix .o, $(basename $@)) $(IOTIVITY_LITE_JAVA_JNI_DIR)$@ $(JNIFLAG) $(EXTRA_HEADER_FILE) $(HEADER_FILE) $(EXTRA_FLAG) $(DTLSFLAGS) + clean: rm -f $(IOTIVITY_LITE_JAVA_LIBS_DIR)$(JAR_NAME) rm -f $(IOTIVITY_LITE_JAVA_LIBS_DIR)$(JNI_SO_NAME) diff --git a/swig/java_lang/.gitignore b/swig/java_lang/.gitignore deleted file mode 100644 index 915cf3c48..000000000 --- a/swig/java_lang/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.c -*.cxx -*.jar -*.so diff --git a/swig/java_lang/build_swig.sh b/swig/java_lang/build_swig.sh index df921563c..138f58239 100755 --- a/swig/java_lang/build_swig.sh +++ b/swig/java_lang/build_swig.sh @@ -48,7 +48,8 @@ fi #swig -java -package org.iotivity -outdir ../iotivity-lite-java/src/org/iotivity/ -o ../iotivity-lite-java/jni/oc_ri_wrap.c ../swig_interfaces/oc_ri.i swig -java -package org.iotivity -outdir ../iotivity-lite-java/src/org/iotivity/ -I../../port/ -o ../iotivity-lite-java/jni/oc_storage_wrap.c ../swig_interfaces/oc_storage.i -cp *.h ../iotivity-lite-java/jni/ +cp *.h ../iotivity-lite-java/jni/ +cp *.c ../iotivity-lite-java/jni/ cp ../oc_java/*.java ../iotivity-lite-java/src/org/iotivity/ mkdir -p ../iotivity-lite-java/src/org/iotivity/oc/ cp ../oc_java/oc/*.java ../iotivity-lite-java/src/org/iotivity/oc/ diff --git a/swig/java_lang/oc_iotivity_lite_jni.c b/swig/java_lang/oc_iotivity_lite_jni.c new file mode 100644 index 000000000..dc83aa59c --- /dev/null +++ b/swig/java_lang/oc_iotivity_lite_jni.c @@ -0,0 +1,352 @@ +/* +// Copyright (c) 2019 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + */ + +#include "oc_iotivity_lite_jni.h" +#include "port/oc_log.h" +#include "port/oc_storage.h" +#include + +#define JNI_CURRENT_VERSION JNI_VERSION_1_6 + +static JavaVM *jvm; + +JNIEXPORT jint JNICALL +JNI_OnLoad(JavaVM *vm, void *reserved) +{ + OC_DBG("JNI: %s\n", __func__); + OC_DBG("JNI: %s - Setting global JavaVM variable", __func__); + jvm = vm; + + JNIEnv *jenv = NULL; + jint getEnvResult = 0; + jenv = get_jni_env(&getEnvResult); + + assert(jenv); + if (jenv == NULL) { + return -1; + } + + jclass ocAddDeviceHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCAddDeviceHandler"); + assert(ocAddDeviceHandlerClass); + cls_OCAddDeviceHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocAddDeviceHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocAddDeviceHandlerClass); + + jclass ocClientResponseClass = JCALL1(FindClass, jenv, "org/iotivity/OCClientResponse"); + assert(ocClientResponseClass); + cls_OCClientResponse = (jclass)(JCALL1(NewGlobalRef, jenv, ocClientResponseClass)); + JCALL1(DeleteLocalRef, jenv, ocClientResponseClass); + + jclass ocCoreAddDeviceHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCCoreAddDeviceHandler"); + assert(ocCoreAddDeviceHandlerClass); + cls_OCCoreAddDeviceHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocCoreAddDeviceHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocCoreAddDeviceHandlerClass); + + jclass ocCoreInitPlatformHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCCoreInitPlatformHandler"); + assert(ocCoreInitPlatformHandlerClass); + cls_OCCoreInitPlatformHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocCoreInitPlatformHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocCoreInitPlatformHandlerClass); + + jclass ocConWriteHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCConWriteHandler"); + assert(ocConWriteHandlerClass); + cls_OCConWriteHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocConWriteHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocConWriteHandlerClass); + + jclass ocDiscoveryHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCDiscoveryHandler"); + assert(ocDiscoveryHandlerClass); + cls_OCDiscoveryHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocDiscoveryHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocDiscoveryHandlerClass); + + jclass ocEndpointClass = JCALL1(FindClass, jenv, "org/iotivity/OCEndpoint"); + assert(ocEndpointClass); + cls_OCEndpoint = (jclass)(JCALL1(NewGlobalRef, jenv, ocEndpointClass)); + JCALL1(DeleteLocalRef, jenv, ocEndpointClass); + + jclass ocFactoryPresetsHandler = JCALL1(FindClass, jenv, "org/iotivity/OCFactoryPresetsHandler"); + assert(ocFactoryPresetsHandler); + cls_OCFactoryPresetsHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocFactoryPresetsHandler)); + JCALL1(DeleteLocalRef, jenv, ocFactoryPresetsHandler); + + jclass ocInitPlatformHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCInitPlatformHandler"); + assert(ocInitPlatformHandlerClass); + cls_OCInitPlatformHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocInitPlatformHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocInitPlatformHandlerClass); + + jclass ocQueryValueClass = JCALL1(FindClass, jenv, "org/iotivity/OCQueryValue"); + assert(ocQueryValueClass); + cls_OCQueryValue = (jclass)(JCALL1(NewGlobalRef, jenv, ocQueryValueClass)); + JCALL1(DeleteLocalRef, jenv, ocQueryValueClass); + + jclass ocRandomPinHandler = JCALL1(FindClass, jenv, "org/iotivity/OCRandomPinHandler"); + assert(ocRandomPinHandler); + cls_OCRandomPinHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocRandomPinHandler)); + JCALL1(DeleteLocalRef, jenv, ocRandomPinHandler); + + + jclass ocRepresentationClass = JCALL1(FindClass, jenv, "org/iotivity/OCRepresentation"); + assert(ocRepresentationClass); + cls_OCRepresentation = (jclass)(JCALL1(NewGlobalRef, jenv, ocRepresentationClass)); + JCALL1(DeleteLocalRef, jenv, ocRepresentationClass); + + jclass ocRequestClass = JCALL1(FindClass, jenv, "org/iotivity/OCRequest"); + assert(ocRequestClass); + cls_OCRequest = (jclass)(JCALL1(NewGlobalRef, jenv, ocRequestClass)); + JCALL1(DeleteLocalRef, jenv, ocRequestClass); + + jclass ocRequestHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCRequestHandler"); + assert(ocRequestHandlerClass); + cls_OCRequestHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocRequestHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocRequestHandlerClass); + + jclass ocResponseHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCResponseHandler"); + assert(ocResponseHandlerClass); + cls_OCResponseHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocResponseHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocResponseHandlerClass); + + jclass ocTriggerHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCTriggerHandler"); + assert(ocTriggerHandlerClass); + cls_OCTriggerHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocTriggerHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocTriggerHandlerClass); + + jclass ocUuidClass = JCALL1(FindClass, jenv, "org/iotivity/OCUuid"); + assert(ocUuidClass); + cls_OCUuid = (jclass)(JCALL1(NewGlobalRef, jenv, ocUuidClass)); + JCALL1(DeleteLocalRef, jenv, ocUuidClass); + + jclass ocObtDiscoveryHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCObtDiscoveryHandler"); + assert(ocObtDiscoveryHandlerClass); + cls_OCObtDiscoveryHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocObtDiscoveryHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocObtDiscoveryHandlerClass); + + jclass ocObtDeviceStatusHandlerClass = + JCALL1(FindClass, jenv, "org/iotivity/OCObtDeviceStatusHandler"); + assert(ocObtDeviceStatusHandlerClass); + cls_OCObtDeviceStatusHandler = + (jclass)(JCALL1(NewGlobalRef, jenv, ocObtDeviceStatusHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocObtDeviceStatusHandlerClass); + + jclass ocObtStatusHandlerClass = + JCALL1(FindClass, jenv, "org/iotivity/OCObtStatusHandler"); + assert(ocObtStatusHandlerClass); + cls_OCObtStatusHandler = + (jclass)(JCALL1(NewGlobalRef, jenv, ocObtStatusHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocObtStatusHandlerClass); + + jclass ocCloudHandlerClass = + JCALL1(FindClass, jenv, "org/iotivity/OCCloudHandler"); + assert(ocCloudHandlerClass); + cls_OCCloudHandler = + (jclass)(JCALL1(NewGlobalRef, jenv, ocCloudHandlerClass)); + JCALL1(DeleteLocalRef, jenv, ocCloudHandlerClass); + + jclass utilArrayListClass = JCALL1(FindClass, jenv, "java/util/ArrayList"); + assert(utilArrayListClass); + cls_ArrayList = (jclass)(JCALL1(NewGlobalRef, jenv, utilArrayListClass)); + JCALL1(DeleteLocalRef, jenv, utilArrayListClass); + +#ifdef __ANDROID__ + // Get the Android Context + const jclass activityThreadClass = + JCALL1(FindClass, jenv, "android/app/ActivityThread"); + const jmethodID currentActivityThreadMethod = + JCALL3(GetStaticMethodID, jenv, activityThreadClass, + "currentActivityThread", "()Landroid/app/ActivityThread;"); + jobject activityThread = + JCALL2(CallStaticObjectMethod, jenv, activityThreadClass, + currentActivityThreadMethod); + + const jmethodID getApplicationMethod = + JCALL3(GetMethodID, jenv, activityThreadClass, "getApplication", + "()Landroid/app/Application;"); + jobject context = + JCALL2(CallObjectMethod, jenv, activityThread, getApplicationMethod); + JCALL1(DeleteLocalRef, jenv, activityThreadClass); + JCALL1(DeleteLocalRef, jenv, activityThread); + + // Get the FilesDir + const jclass activityClass = + JCALL1(FindClass, jenv, "android/app/Activity"); + const jmethodID getFileDirsMethod = JCALL3( + GetMethodID, jenv, activityClass, "getFilesDir", "()Ljava/io/File;"); + jobject filesDir = + JCALL2(CallObjectMethod, jenv, context, getFileDirsMethod); + JCALL1(DeleteLocalRef, jenv, activityClass); + JCALL1(DeleteLocalRef, jenv, context); + + // Create a file object for the credentials directory + const jclass fileClass = JCALL1(FindClass, jenv, "java/io/File"); + const jmethodID fileCtorMethod = + JCALL3(GetMethodID, jenv, fileClass, "", + "(Ljava/io/File;Ljava/lang/String;)V"); + jstring credentials = JCALL1(NewStringUTF, jenv, "credentials"); + jobject credsDir = + JCALL4(NewObject, jenv, fileClass, fileCtorMethod, filesDir, credentials); + JCALL1(DeleteLocalRef, jenv, filesDir); + JCALL1(DeleteLocalRef, jenv, credentials); + + // Test if the credentials directory already exists + const jmethodID fileExistsMethod = + JCALL3(GetMethodID, jenv, fileClass, "exists", "()Z"); + jboolean exists = + JCALL2(CallBooleanMethod, jenv, credsDir, fileExistsMethod); + + if (!exists) { + // Create credentials directory + const jmethodID mkdirMethod = + JCALL3(GetMethodID, jenv, fileClass, "mkdir", "()Z"); + jboolean mkDirCreated = + JCALL2(CallBooleanMethod, jenv, credsDir, mkdirMethod); + if (!mkDirCreated) { + OC_DBG("Failed to create credentials directory"); + return -1; + } + } + + // Get the credentials directory absolute path as a C string + const jmethodID getAbsPathMethod = JCALL3( + GetMethodID, jenv, fileClass, "getAbsolutePath", "()Ljava/lang/String;"); + jstring credsDirPath = + JCALL2(CallObjectMethod, jenv, credsDir, getAbsPathMethod); + const char *path = JCALL2(GetStringUTFChars, jenv, credsDirPath, 0); + OC_DBG("JNI: %s, %s\n", __func__, path); + JCALL1(DeleteLocalRef, jenv, fileClass); + JCALL1(DeleteLocalRef, jenv, credsDir); + + // Initialize credential storage +#ifdef OC_SECURITY + OC_DBG("JNI: %s with path %s\n", __func__, path); + oc_storage_config(path); +#else + OC_DBG( + "JNI: OC_SECURITY disabled ignore call to oc_storage_config with path %s\n", + path); +#endif /* OC_SECURITY */ + + // Cleanup + JCALL2(ReleaseStringUTFChars, jenv, credsDirPath, path); + JCALL1(DeleteLocalRef, jenv, credsDirPath); +#endif + + release_jni_env(getEnvResult); + + return JNI_CURRENT_VERSION; +} + +JavaVM * +get_jvm() +{ + return jvm; +} + +/* + * Container used to hold all `jni_callback_data` that is + * allocated dynamically. This can be used to find the + * memory allocated for the `jni_callback_data` if the callback + * is removed or unregistered. This can all so be used to clean + * up the allocated memory when shutting down the stack. + */ +OC_LIST(jni_callbacks); + +jni_callback_data * +jni_list_get_head() +{ + return (jni_callback_data *)oc_list_head(jni_callbacks); +} + +void +jni_list_add(jni_callback_data *item) +{ + OC_DBG("JNI: - lock %s\n", __func__); + jni_mutex_lock(jni_sync_lock); + oc_list_add(jni_callbacks, item); + jni_mutex_unlock(jni_sync_lock); + OC_DBG("JNI: - unlock %s\n", __func__); +} + +void +jni_list_remove(jni_callback_data *item) +{ + OC_DBG("JNI: - lock %s\n", __func__); + jni_mutex_lock(jni_sync_lock); + if (item) { + JCALL1(DeleteGlobalRef, item->jenv, item->jcb_obj); + oc_list_remove(jni_callbacks, item); + free(item); + } + jni_mutex_unlock(jni_sync_lock); + OC_DBG("JNI: - unlock %s\n", __func__); +} + +jni_callback_data * +jni_list_get_item_by_java_callback(jobject callback) +{ + OC_DBG("JNI: - lock %s\n", __func__); + jni_mutex_lock(jni_sync_lock); + jni_callback_data *item = jni_list_get_head(); + while (item) { + if (JCALL2(IsSameObject, (item->jenv), callback, item->jcb_obj)) { + break; + } + item = (jni_callback_data *)oc_list_item_next(item); + } + jni_mutex_unlock(jni_sync_lock); + OC_DBG("JNI: - unlock %s\n", __func__); + return item; +} + +//void jni_list_remove_by_java_callback(jobject callback) +//{ +// +// jni_callback_data *item = jni_list_get_item_by_java_callback(callback); +// jni_list_remove(item); +//} + +JNIEnv * +get_jni_env(jint *getEnvResult) +{ + JNIEnv *env = NULL; + *getEnvResult = JCALL2(GetEnv, jvm, (void **)&env, JNI_CURRENT_VERSION); + switch (*getEnvResult) { + case JNI_OK: + return env; + case JNI_EDETACHED: +#ifdef __ANDROID__ + if (JCALL2(AttachCurrentThread, jvm, &env, NULL) < 0) +#else + if (JCALL2(AttachCurrentThread, jvm, (void **)&env, NULL) < 0) +#endif + { + OC_DBG("Failed to get the environment"); + return NULL; + } else { + return env; + } + case JNI_EVERSION: + OC_DBG("JNI version not supported"); + break; + default: + OC_DBG("Failed to get the environment"); + return NULL; + } + return NULL; +} + +void +release_jni_env(jint getEnvResult) +{ + if (JNI_EDETACHED == getEnvResult) { + JCALL0(DetachCurrentThread, jvm); + } +} diff --git a/swig/java_lang/oc_iotivity_lite_jni.h b/swig/java_lang/oc_iotivity_lite_jni.h index a1cf23a41..37c69dab0 100644 --- a/swig/java_lang/oc_iotivity_lite_jni.h +++ b/swig/java_lang/oc_iotivity_lite_jni.h @@ -53,6 +53,83 @@ int jni_quit __attribute__((unused)); #define jni_mutex_unlock(m) pthread_mutex_unlock(&m) #endif +/* + * JNI function calls require different calling conventions for C and C++. These + * JCALL macros are used so that the same typemaps can be used for generating + * code for both C and C++. These macros are originally from the SWIG + * javahead.swg. They placed here because the SWIG preprocessor does not expand + * macros that are within the SWIG header code insertion blocks. + */ +#ifdef __cplusplus +#define JCALL0(func, jenv) jenv->func() +#define JCALL1(func, jenv, ar1) jenv->func(ar1) +#define JCALL2(func, jenv, ar1, ar2) jenv->func(ar1, ar2) +#define JCALL3(func, jenv, ar1, ar2, ar3) jenv->func(ar1, ar2, ar3) +#define JCALL4(func, jenv, ar1, ar2, ar3, ar4) jenv->func(ar1, ar2, ar3, ar4) +#define JCALL5(func, jenv, ar1, ar2, ar3, ar4, ar5) \ + jenv->func(ar1, ar2, ar3, ar4, ar5) +#define JCALL6(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6) \ + jenv->func(ar1, ar2, ar3, ar4, ar5, ar6) +#define JCALL7(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) \ + jenv->func(ar1, ar2, ar3, ar4, ar5, ar6, ar7) +#define JCALL8(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8) \ + jenv->func(ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8) +#define JCALL9(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8, ar9) \ + jenv->func(ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8, ar9) +#else +#define JCALL0(func, jenv) (*jenv)->func(jenv) +#define JCALL1(func, jenv, ar1) (*jenv)->func(jenv, ar1) +#define JCALL2(func, jenv, ar1, ar2) (*jenv)->func(jenv, ar1, ar2) +#define JCALL3(func, jenv, ar1, ar2, ar3) (*jenv)->func(jenv, ar1, ar2, ar3) +#define JCALL4(func, jenv, ar1, ar2, ar3, ar4) \ + (*jenv)->func(jenv, ar1, ar2, ar3, ar4) +#define JCALL5(func, jenv, ar1, ar2, ar3, ar4, ar5) \ + (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5) +#define JCALL6(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6) \ + (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6) +#define JCALL7(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) \ + (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) +#define JCALL8(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8) \ + (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8) +#define JCALL9(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8, ar9) \ + (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8, ar9) +#endif + +/* + * org/iotivity classes are pre-loaded as part of the JNI_OnLoad event. + * + * This is important for any code originating from the native code. If that + * code is not running in a thread started by the JavaVM then the jni code + * can not obtain a pointer to JavaVM or the JNIEnv. It can be really hard to + * find bugs that result from a thread not being started by the JavaVM. + * For this reason we pre-load most Java classes that are called from the jni + * code. + */ +jclass cls_ArrayList; +jclass cls_OCMainInitHandler; +jclass cls_OCAddDeviceHandler; +jclass cls_OCClientResponse; +jclass cls_OCConWriteHandler; +jclass cls_OCDiscoveryHandler; +jclass cls_OCFactoryPresetsHandler; +jclass cls_OCInitPlatformHandler; +jclass cls_OCQueryValue; +jclass cls_OCRandomPinHandler; +jclass cls_OCRepresentation; +jclass cls_OCRequest; +jclass cls_OCRequestHandler; +jclass cls_OCResponseHandler; +jclass cls_OCTriggerHandler; + +jclass cls_OCCoreAddDeviceHandler; +jclass cls_OCCoreInitPlatformHandler; +jclass cls_OCEndpoint; +jclass cls_OCUuid; +jclass cls_OCObtDiscoveryHandler; +jclass cls_OCObtDeviceStatusHandler; +jclass cls_OCObtStatusHandler; +jclass cls_OCCloudHandler; + /* * This struct used to hold information needed for java callbacks. * When registering a callback handler from java the `JNIEnv` @@ -76,63 +153,16 @@ typedef struct jni_callback_data_s { jobject jcb_obj; } jni_callback_data; -/* - * Container used to hold all `jni_callback_data` that is - * allocated dynamically. This can be used to find the - * memory allocated for the `jni_callback_data` if the callback - * is removed or unregistered. This can all so be used to clean - * up the allocated memory when shutting down the stack. - */ -OC_LIST(jni_callbacks); - -static void jni_list_add(oc_list_t list, void *item) { - OC_DBG("JNI: - lock %s\n", __func__); - jni_mutex_lock(jni_sync_lock); - oc_list_add(list, item); - jni_mutex_unlock(jni_sync_lock); - OC_DBG("JNI: - unlock %s\n", __func__); -} - -#define JNI_CURRENT_VERSION JNI_VERSION_1_6 - -static JavaVM *jvm; - -static JNIEnv* GetJNIEnv(jint* getEnvResult) -{ - JNIEnv *env = NULL; - *getEnvResult = JCALL2(GetEnv, jvm, (void**)&env, JNI_CURRENT_VERSION); - switch (*getEnvResult) - { - case JNI_OK: - return env; - case JNI_EDETACHED: -# ifdef __ANDROID__ - if(JCALL2(AttachCurrentThread, jvm, &env, NULL) < 0) -# else - if(JCALL2(AttachCurrentThread, jvm, (void**)&env, NULL) < 0) -# endif - { - OC_DBG("Failed to get the environment"); - return NULL; - } - else - { - return env; - } - case JNI_EVERSION: - OC_DBG("JNI version not supported"); - break; - default: - OC_DBG("Failed to get the environment"); - return NULL; - } - return NULL; -} - -static void ReleaseJNIEnv(jint getEnvResult) { - if (JNI_EDETACHED == getEnvResult) { - JCALL0(DetachCurrentThread, jvm); - } -} +jni_callback_data * jni_list_get_head(); +void jni_list_add(jni_callback_data *item); +void jni_list_remove(jni_callback_data *item); +jni_callback_data * jni_list_get_item_by_java_callback(jobject callback); +//void jni_list_remove_by_java_callback(jobject callback); + +JavaVM *get_jvm(); + +JNIEnv *get_jni_env(jint *getEnvResult); + +void release_jni_env(jint getEnvResult); #endif /* OC_IOTIVITY_LITE_H */ diff --git a/swig/swig_interfaces/iotivity.swg b/swig/swig_interfaces/iotivity.swg index cffb37aec..08ebc8685 100644 --- a/swig/swig_interfaces/iotivity.swg +++ b/swig/swig_interfaces/iotivity.swg @@ -8,38 +8,9 @@ * collection of code need across the project *********************************************************************/ %{ +#include "oc_iotivity_lite_jni.h" #include "oc_collection.h" #include "port/oc_log.h" - -/* - * JNI function calls require different calling conventions for C and C++. These JCALL macros are used so - * that the same typemaps can be used for generating code for both C and C++. These macros are originaly from - * the SWIG javahead.swg. They placed here because the SWIG preprocessor does not expand macros that are - * within the SWIG header code insertion blocks. - */ -#ifdef __cplusplus -# define JCALL0(func, jenv) jenv->func() -# define JCALL1(func, jenv, ar1) jenv->func(ar1) -# define JCALL2(func, jenv, ar1, ar2) jenv->func(ar1, ar2) -# define JCALL3(func, jenv, ar1, ar2, ar3) jenv->func(ar1, ar2, ar3) -# define JCALL4(func, jenv, ar1, ar2, ar3, ar4) jenv->func(ar1, ar2, ar3, ar4) -# define JCALL5(func, jenv, ar1, ar2, ar3, ar4, ar5) jenv->func(ar1, ar2, ar3, ar4, ar5) -# define JCALL6(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6) jenv->func(ar1, ar2, ar3, ar4, ar5, ar6) -# define JCALL7(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) jenv->func(ar1, ar2, ar3, ar4, ar5, ar6, ar7) -# define JCALL8(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8) jenv->func(ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8) -# define JCALL9(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8, ar9) jenv->func(ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8, ar9) -#else -# define JCALL0(func, jenv) (*jenv)->func(jenv) -# define JCALL1(func, jenv, ar1) (*jenv)->func(jenv, ar1) -# define JCALL2(func, jenv, ar1, ar2) (*jenv)->func(jenv, ar1, ar2) -# define JCALL3(func, jenv, ar1, ar2, ar3) (*jenv)->func(jenv, ar1, ar2, ar3) -# define JCALL4(func, jenv, ar1, ar2, ar3, ar4) (*jenv)->func(jenv, ar1, ar2, ar3, ar4) -# define JCALL5(func, jenv, ar1, ar2, ar3, ar4, ar5) (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5) -# define JCALL6(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6) (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6) -# define JCALL7(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) -# define JCALL8(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8) (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8) -# define JCALL9(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8, ar9) (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8, ar9) -#endif %} diff --git a/swig/swig_interfaces/oc_api.i b/swig/swig_interfaces/oc_api.i index 1b4b3b768..9fc502916 100644 --- a/swig/swig_interfaces/oc_api.i +++ b/swig/swig_interfaces/oc_api.i @@ -38,38 +38,13 @@ /* Code and typemaps for mapping the oc_main_init to the java OCMainInitHandler */ %{ static jobject jinit_obj; -static jclass cls_ArrayList; -static jclass cls_OCMainInitHandler; -static jclass cls_OCAddDeviceHandler; -static jclass cls_OCClientResponse; -static jclass cls_OCConWriteHandler; -static jclass cls_OCDiscoveryHandler; -static jclass cls_OCFactoryPresetsHandler; -static jclass cls_OCInitPlatformHandler; -static jclass cls_OCQueryValue; -static jclass cls_OCRandomPinHandler; -static jclass cls_OCRepresentation; -static jclass cls_OCRequest; -static jclass cls_OCRequestHandler; -static jclass cls_OCResponseHandler; -static jclass cls_OCTriggerHandler; - - -jclass cls_OCCoreAddDeviceHandler; -jclass cls_OCCoreInitPlatformHandler; -jclass cls_OCEndpoint; -jclass cls_OCUuid; -jclass cls_OCObtDiscoveryHandler; -jclass cls_OCObtDeviceStatusHandler; -jclass cls_OCObtStatusHandler; -jclass cls_OCCloudHandler; /* Callback handlers for oc_main_init */ int jni_oc_handler_init_callback(void) { OC_DBG("JNI: %s\n", __func__); jint getEnvResult = 0; - JNIEnv *jenv = GetJNIEnv(&getEnvResult); + JNIEnv *jenv = get_jni_env(&getEnvResult); assert(jenv); assert(cls_OCMainInitHandler); @@ -77,7 +52,7 @@ int jni_oc_handler_init_callback(void) assert(mid_initialize); jint ret_value = JCALL2(CallIntMethod, jenv, jinit_obj, mid_initialize); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); return (int)ret_value; } @@ -97,7 +72,7 @@ void jni_oc_handler_register_resource_callback(void) { OC_DBG("JNI: %s\n", __func__); jint getEnvResult = 0; - JNIEnv *jenv = GetJNIEnv(&getEnvResult); + JNIEnv *jenv = get_jni_env(&getEnvResult); assert(jenv); assert(cls_OCMainInitHandler); @@ -105,14 +80,14 @@ void jni_oc_handler_register_resource_callback(void) assert(mid_registerResources); JCALL2(CallVoidMethod, jenv, jinit_obj, mid_registerResources); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); } void jni_oc_handler_requests_entry_callback(void) { OC_DBG("JNI: %s\n", __func__); jint getEnvResult = 0; - JNIEnv *jenv = GetJNIEnv(&getEnvResult); + JNIEnv *jenv = get_jni_env(&getEnvResult); assert(jenv); assert(cls_OCMainInitHandler); @@ -120,7 +95,7 @@ void jni_oc_handler_requests_entry_callback(void) assert(mid_requestEntry_method); JCALL2(CallVoidMethod, jenv, jinit_obj, mid_requestEntry_method); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); } static oc_handler_t jni_handler = { @@ -137,7 +112,6 @@ static oc_handler_t jni_handler = { %typemap(jstype) const oc_handler_t *handler "OCMainInitHandler"; %typemap(javain) const oc_handler_t *handler "$javainput"; %typemap(in) const oc_handler_t *handler { - JCALL1(GetJavaVM, jenv, &jvm); jinit_obj = JCALL1(NewGlobalRef, jenv, $input); $1 = &jni_handler; @@ -219,121 +193,10 @@ int jni_main_init(const oc_handler_t *handler) jni_quit = 0; jint getEnvResult = 0; - JNIEnv *jenv = GetJNIEnv(&getEnvResult); + JNIEnv *jenv = get_jni_env(&getEnvResult); assert(jenv); - jclass ocAddDeviceHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCAddDeviceHandler"); - assert(ocAddDeviceHandlerClass); - cls_OCAddDeviceHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocAddDeviceHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocAddDeviceHandlerClass); - - jclass ocClientResponseClass = JCALL1(FindClass, jenv, "org/iotivity/OCClientResponse"); - assert(ocClientResponseClass); - cls_OCClientResponse = (jclass)(JCALL1(NewGlobalRef, jenv, ocClientResponseClass)); - JCALL1(DeleteLocalRef, jenv, ocClientResponseClass); - - jclass ocCoreAddDeviceHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCCoreAddDeviceHandler"); - assert(ocCoreAddDeviceHandlerClass); - cls_OCCoreAddDeviceHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocCoreAddDeviceHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocCoreAddDeviceHandlerClass); - - jclass ocCoreInitPlatformHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCCoreInitPlatformHandler"); - assert(ocCoreInitPlatformHandlerClass); - cls_OCCoreInitPlatformHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocCoreInitPlatformHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocCoreInitPlatformHandlerClass); - - jclass ocConWriteHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCConWriteHandler"); - assert(ocConWriteHandlerClass); - cls_OCConWriteHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocConWriteHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocConWriteHandlerClass); - - jclass ocDiscoveryHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCDiscoveryHandler"); - assert(ocDiscoveryHandlerClass); - cls_OCDiscoveryHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocDiscoveryHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocDiscoveryHandlerClass); - - jclass ocEndpointClass = JCALL1(FindClass, jenv, "org/iotivity/OCEndpoint"); - assert(ocEndpointClass); - cls_OCEndpoint = (jclass)(JCALL1(NewGlobalRef, jenv, ocEndpointClass)); - JCALL1(DeleteLocalRef, jenv, ocEndpointClass); - - jclass ocFactoryPresetsHandler = JCALL1(FindClass, jenv, "org/iotivity/OCFactoryPresetsHandler"); - assert(ocFactoryPresetsHandler); - cls_OCFactoryPresetsHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocFactoryPresetsHandler)); - JCALL1(DeleteLocalRef, jenv, ocFactoryPresetsHandler); - - jclass ocInitPlatformHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCInitPlatformHandler"); - assert(ocInitPlatformHandlerClass); - cls_OCInitPlatformHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocInitPlatformHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocInitPlatformHandlerClass); - - jclass ocQueryValueClass = JCALL1(FindClass, jenv, "org/iotivity/OCQueryValue"); - assert(ocQueryValueClass); - cls_OCQueryValue = (jclass)(JCALL1(NewGlobalRef, jenv, ocQueryValueClass)); - JCALL1(DeleteLocalRef, jenv, ocQueryValueClass); - - jclass ocRandomPinHandler = JCALL1(FindClass, jenv, "org/iotivity/OCRandomPinHandler"); - assert(ocRandomPinHandler); - cls_OCRandomPinHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocRandomPinHandler)); - JCALL1(DeleteLocalRef, jenv, ocRandomPinHandler); - - - jclass ocRepresentationClass = JCALL1(FindClass, jenv, "org/iotivity/OCRepresentation"); - assert(ocRepresentationClass); - cls_OCRepresentation = (jclass)(JCALL1(NewGlobalRef, jenv, ocRepresentationClass)); - JCALL1(DeleteLocalRef, jenv, ocRepresentationClass); - - jclass ocRequestClass = JCALL1(FindClass, jenv, "org/iotivity/OCRequest"); - assert(ocRequestClass); - cls_OCRequest = (jclass)(JCALL1(NewGlobalRef, jenv, ocRequestClass)); - JCALL1(DeleteLocalRef, jenv, ocRequestClass); - - jclass ocRequestHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCRequestHandler"); - assert(ocRequestHandlerClass); - cls_OCRequestHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocRequestHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocRequestHandlerClass); - - jclass ocResponseHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCResponseHandler"); - assert(ocResponseHandlerClass); - cls_OCResponseHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocResponseHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocResponseHandlerClass); - - jclass ocTriggerHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCTriggerHandler"); - assert(ocTriggerHandlerClass); - cls_OCTriggerHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocTriggerHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocTriggerHandlerClass); - - jclass ocUuidClass = JCALL1(FindClass, jenv, "org/iotivity/OCUuid"); - assert(ocUuidClass); - cls_OCUuid = (jclass)(JCALL1(NewGlobalRef, jenv, ocUuidClass)); - JCALL1(DeleteLocalRef, jenv, ocUuidClass); - - jclass ocObtDiscoveryHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCObtDiscoveryHandler"); - assert(ocObtDiscoveryHandlerClass); - cls_OCObtDiscoveryHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocObtDiscoveryHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocObtDiscoveryHandlerClass); - - jclass ocObtDeviceStatusHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCObtDeviceStatusHandler"); - assert(ocObtDeviceStatusHandlerClass); - cls_OCObtDeviceStatusHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocObtDeviceStatusHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocObtDeviceStatusHandlerClass); - - jclass ocObtStatusHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCObtStatusHandler"); - assert(ocObtStatusHandlerClass); - cls_OCObtStatusHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocObtStatusHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocObtStatusHandlerClass); - - jclass ocCloudHandlerClass = JCALL1(FindClass, jenv, "org/iotivity/OCCloudHandler"); - assert(ocCloudHandlerClass); - cls_OCCloudHandler = (jclass)(JCALL1(NewGlobalRef, jenv, ocCloudHandlerClass)); - JCALL1(DeleteLocalRef, jenv, ocCloudHandlerClass); - - jclass utilArrayListClass = JCALL1(FindClass, jenv, "java/util/ArrayList"); - assert(utilArrayListClass); - cls_ArrayList = (jclass)(JCALL1(NewGlobalRef, jenv, utilArrayListClass)); - JCALL1(DeleteLocalRef, jenv, utilArrayListClass); - - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); // initialize threads #if defined(_WIN32) @@ -390,7 +253,7 @@ void jni_oc_factory_presets_callback(size_t device, void *user_data) OC_DBG("JNI: %s\n", __func__); jni_callback_data *data = (jni_callback_data *)user_data; jint getEnvResult = 0; - data->jenv = GetJNIEnv(&getEnvResult); + data->jenv = get_jni_env(&getEnvResult); assert(cls_OCFactoryPresetsHandler); const jmethodID mid_handler = JCALL3(GetMethodID, @@ -402,7 +265,7 @@ void jni_oc_factory_presets_callback(size_t device, void *user_data) assert(mid_handler); JCALL3(CallVoidMethod, (data->jenv), data->jcb_obj, mid_handler, (jlong)device); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); } %} @@ -452,7 +315,7 @@ void jni_oc_add_device_callback(void *user_data) jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_oc_add_device_callback; $2 = user_data; } @@ -502,7 +365,7 @@ void jni_oc_init_platform_callback(void *user_data) jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_oc_init_platform_callback; $2 = user_data; } @@ -530,7 +393,7 @@ void jni_oc_random_pin_callback(const unsigned char *pin, size_t pin_len, void * OC_DBG("JNI: %s\n", __func__); jni_callback_data *data = (jni_callback_data *)user_data; jint getEnvResult = 0; - data->jenv = GetJNIEnv(&getEnvResult); + data->jenv = get_jni_env(&getEnvResult); assert(cls_OCRandomPinHandler); const jmethodID mid_handler = JCALL3(GetMethodID, @@ -543,7 +406,7 @@ void jni_oc_random_pin_callback(const unsigned char *pin, size_t pin_len, void * jstring jpin = JCALL1(NewStringUTF, (data->jenv), (const char *)pin); JCALL3(CallVoidMethod, (data->jenv), data->jcb_obj, mid_handler, jpin); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); } %} @@ -555,7 +418,7 @@ void jni_oc_random_pin_callback(const unsigned char *pin, size_t pin_len, void * jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_oc_random_pin_callback; $2 = user_data; } @@ -614,7 +477,7 @@ void jni_oc_request_callback(oc_request_t *request, oc_interface_mask_t interfac OC_DBG("JNI: %s\n", __func__); jni_callback_data *data = (jni_callback_data *)user_data; jint getEnvResult = 0; - data->jenv = GetJNIEnv(&getEnvResult); + data->jenv = get_jni_env(&getEnvResult); assert(data->jenv); assert(cls_OCRequestHandler); @@ -635,7 +498,7 @@ void jni_oc_request_callback(oc_request_t *request, oc_interface_mask_t interfac JCALL4(NewObject, (data->jenv), cls_OCRequest, mid_OCRequest_init, (jlong)request, false), (jint)interfaces); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); } %} %typemap(jni) oc_request_callback_t callback "jobject"; @@ -647,7 +510,7 @@ void jni_oc_request_callback(oc_request_t *request, oc_interface_mask_t interfac jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_oc_request_callback; $2 = user_data; } @@ -831,7 +694,7 @@ oc_discovery_flags_t jni_oc_discovery_handler_callback(const char *anchor, jni_callback_data *data = (jni_callback_data *)user_data; jint getEnvResult = 0; - data->jenv = GetJNIEnv(&getEnvResult); + data->jenv = get_jni_env(&getEnvResult); assert(data->jenv); jstring janchor = JCALL1(NewStringUTF, (data->jenv), anchor); @@ -893,7 +756,7 @@ oc_discovery_flags_t jni_oc_discovery_handler_callback(const char *anchor, jDiscoveryFlag, mid_OCDiscoveryFlags_swigValue); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); return (oc_discovery_flags_t) return_value; } @@ -906,7 +769,7 @@ oc_discovery_flags_t jni_oc_discovery_handler_callback(const char *anchor, jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_oc_discovery_handler_callback; $2 = user_data; } @@ -986,7 +849,7 @@ void jni_oc_response_handler(oc_client_response_t *response) jni_callback_data *data = (jni_callback_data *)response->user_data; jint getEnvResult = 0; - data->jenv = GetJNIEnv(&getEnvResult); + data->jenv = get_jni_env(&getEnvResult); assert(data->jenv); assert(cls_OCClientResponse); @@ -1012,7 +875,7 @@ void jni_oc_response_handler(oc_client_response_t *response) assert(mid_handler); JCALL3(CallVoidMethod, (data->jenv), data->jcb_obj, mid_handler, jresponse); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); } %} %typemap(jni) oc_response_handler_t handler "jobject"; @@ -1023,7 +886,7 @@ void jni_oc_response_handler(oc_client_response_t *response) jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_oc_response_handler; $2 = user_data; } @@ -1267,7 +1130,7 @@ oc_event_callback_retval_t jni_oc_trigger_handler(void* cb_data) { jni_callback_data *data = (jni_callback_data *)cb_data; assert(data); jint getEnvResult = 0; - data->jenv = GetJNIEnv(&getEnvResult); + data->jenv = get_jni_env(&getEnvResult); assert(data->jenv); assert(cls_OCTriggerHandler); @@ -1305,7 +1168,7 @@ oc_event_callback_retval_t jni_oc_trigger_handler(void* cb_data) { jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_oc_trigger_handler; $2 = user_data; } @@ -1334,19 +1197,11 @@ void jni_oc_set_delayed_callback(oc_trigger_t callback, jni_callback_data *jcb, %inline %{ void jni_oc_remove_delayed_callback(jobject callback) { OC_DBG("JNI: %s\n", __func__); - jni_callback_data *item = (jni_callback_data *)oc_list_head(jni_callbacks); - while (item) { - if (JCALL2(IsSameObject, (item->jenv), callback, item->jcb_obj)) { - oc_remove_delayed_callback(item, jni_oc_trigger_handler); - JCALL1(DeleteGlobalRef, (item->jenv), item->jcb_obj); - break; - } - item = (jni_callback_data *)oc_list_item_next(item); - } + jni_callback_data *item = jni_list_get_item_by_java_callback(callback); if (item) { - oc_list_remove(jni_callbacks, item); - free(item); + oc_remove_delayed_callback(item, jni_oc_trigger_handler); } + jni_list_remove(item); } %} %include "oc_api.h" diff --git a/swig/swig_interfaces/oc_cloud.i b/swig/swig_interfaces/oc_cloud.i index fd7df74e7..f788fd232 100644 --- a/swig/swig_interfaces/oc_cloud.i +++ b/swig/swig_interfaces/oc_cloud.i @@ -26,16 +26,14 @@ #include "oc_cloud.h" %} -/* code and typemaps for mappinc the oc_cloud_cb_t to the java OCCloudHandler */ +/* code and typemaps for mapping the oc_cloud_cb_t to the java OCCloudHandler */ %{ -extern jclass cls_OCCloudHandler; - static void jni_cloud_cb(oc_cloud_status_t status, void *user_data) { OC_DBG("JNI: %s\n", __func__); jni_callback_data *data = (jni_callback_data *)user_data; jint getEnvResult = 0; - data->jenv = GetJNIEnv(&getEnvResult); + data->jenv = get_jni_env(&getEnvResult); assert(data->jenv); assert(cls_OCCloudHandler); @@ -52,7 +50,7 @@ static void jni_cloud_cb(oc_cloud_status_t status, void *user_data) mid_handler, (jint) status); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); } %} @@ -67,7 +65,7 @@ static void jni_cloud_cb(oc_cloud_status_t status, void *user_data) jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_cloud_cb; $2 = user_data; } diff --git a/swig/swig_interfaces/oc_core_res.i b/swig/swig_interfaces/oc_core_res.i index 91394f660..cc47dd9c8 100644 --- a/swig/swig_interfaces/oc_core_res.i +++ b/swig/swig_interfaces/oc_core_res.i @@ -22,9 +22,6 @@ #include "oc_iotivity_lite_jni.h" #include "oc_core_res.h" - -extern jclass cls_OCCoreAddDeviceHandler; -extern jclass cls_OCCoreInitPlatformHandler; %} %rename (OCPlatformInfo) oc_platform_info_t; @@ -64,7 +61,7 @@ void jni_oc_core_init_platform_callback(void *user_data) jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_oc_core_init_platform_callback; $2 = user_data; } @@ -110,7 +107,7 @@ void jni_oc_core_add_device_callback(void *user_data) jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_oc_core_add_device_callback; $2 = user_data; } diff --git a/swig/swig_interfaces/oc_endpoint.i b/swig/swig_interfaces/oc_endpoint.i index 07389863a..5acdc4a0a 100644 --- a/swig/swig_interfaces/oc_endpoint.i +++ b/swig/swig_interfaces/oc_endpoint.i @@ -20,6 +20,7 @@ %{ #include "oc_endpoint.h" +#include "oc_iotivity_lite_jni.h" %} /*******************Begin oc_endpoint.h*********************/ diff --git a/swig/swig_interfaces/oc_obt.i b/swig/swig_interfaces/oc_obt.i index 31117e85e..609a36e41 100644 --- a/swig/swig_interfaces/oc_obt.i +++ b/swig/swig_interfaces/oc_obt.i @@ -22,12 +22,6 @@ #include "oc_obt.h" %} - -/* a little remapping trick to force saving a pointer to the JavaVM */ -%typemap(in, numinputs=0) void* dummy { - JCALL1(GetJavaVM, jenv, &jvm); -} - %rename(OCSecurityAce) oc_sec_ace_s; /* We are relying on the iotivity-lite library to create and destry instances of oc_sec_ace_s */ %nodefaultctor oc_sec_ace_s; @@ -46,30 +40,18 @@ struct oc_ace_res_s{ }; %rename(OCAceWildcard) oc_ace_wildcard_t; %ignore oc_ace_permissions_t; -%ignore oc_obt_init; -%rename(init) jni_obt_init; -%inline %{ -void jni_obt_init(void* dummy) { - oc_obt_init(); -} -%} +%rename(init) oc_obt_init; %rename(shutdown) oc_obt_shutdown; /* code and typemaps for mapping the oc_obt_discover_cb to the java OCObtDiscoveryHandler */ %{ -extern jclass cls_OCObtDiscoveryHandler; -extern jclass cls_OCObtDeviceStatusHandler; -extern jclass cls_OCObtStatusHandler; -extern jclass cls_OCEndpoint; -extern jclass cls_OCUuid; - static void jni_obt_discovery_cb(oc_uuid_t *uuid, oc_endpoint_t *eps, void *user_data) { OC_DBG("JNI: %s\n", __func__); assert(user_data); jni_callback_data *data = (jni_callback_data *)user_data; jint getEnvResult = 0; - data->jenv = GetJNIEnv(&getEnvResult); + data->jenv = get_jni_env(&getEnvResult); assert(data->jenv); assert(cls_OCObtDiscoveryHandler); @@ -103,7 +85,7 @@ static void jni_obt_discovery_cb(oc_uuid_t *uuid, oc_endpoint_t *eps, void *user JCALL4(NewObject, (data->jenv), cls_OCUuid, mid_OCUuid_init, (jlong)juuid, true), JCALL4(NewObject, (data->jenv), cls_OCEndpoint, mid_OCEndpoint_init, (jlong)eps, false)); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); } %} @@ -117,7 +99,7 @@ static void jni_obt_discovery_cb(oc_uuid_t *uuid, oc_endpoint_t *eps, void *user jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_obt_discovery_cb; $2 = user_data; } @@ -219,7 +201,7 @@ static void jni_obt_device_status_cb(oc_uuid_t *uuid, int status, void *user_dat OC_DBG("JNI: %s\n", __func__); jni_callback_data *data = (jni_callback_data *)user_data; jint getEnvResult = 0; - data->jenv = GetJNIEnv(&getEnvResult); + data->jenv = get_jni_env(&getEnvResult); assert(data->jenv); assert(cls_OCObtDeviceStatusHandler); @@ -245,7 +227,7 @@ static void jni_obt_device_status_cb(oc_uuid_t *uuid, int status, void *user_dat JCALL4(NewObject, (data->jenv), cls_OCUuid, mid_OCUuid_init, (jlong)juuid, true), (jint) status); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); } %} @@ -259,7 +241,7 @@ static void jni_obt_device_status_cb(oc_uuid_t *uuid, int status, void *user_dat jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_obt_device_status_cb; $2 = user_data; } @@ -346,7 +328,7 @@ static void jni_obt_status_cb(int status, void *user_data) OC_DBG("JNI: %s\n", __func__); jni_callback_data *data = (jni_callback_data *)user_data; jint getEnvResult = 0; - data->jenv = GetJNIEnv(&getEnvResult); + data->jenv = get_jni_env(&getEnvResult); assert(data->jenv); assert(cls_OCObtStatusHandler); @@ -363,7 +345,7 @@ static void jni_obt_status_cb(int status, void *user_data) mid_handler, (jint) status); - ReleaseJNIEnv(getEnvResult); + release_jni_env(getEnvResult); } %} @@ -377,7 +359,7 @@ static void jni_obt_status_cb(int status, void *user_data) jni_callback_data *user_data = (jni_callback_data *)malloc(sizeof *user_data); user_data->jenv = jenv; user_data->jcb_obj = JCALL1(NewGlobalRef, jenv, $input); - jni_list_add(jni_callbacks, user_data); + jni_list_add(user_data); $1 = jni_obt_status_cb; $2 = user_data; } diff --git a/swig/swig_interfaces/oc_storage.i b/swig/swig_interfaces/oc_storage.i index 50ac18d40..158d53164 100644 --- a/swig/swig_interfaces/oc_storage.i +++ b/swig/swig_interfaces/oc_storage.i @@ -19,97 +19,6 @@ #include "port/oc_log.h" #include -#ifdef __ANDROID__ - -#include "oc_iotivity_lite_jni.h" - -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) -{ - OC_DBG("JNI: %s\n", __func__); - JNIEnv *jenv = NULL; - jint getEnvResult = JCALL2(GetEnv, vm, (void**)&jenv, JNI_CURRENT_VERSION); - OC_DBG("JNI: %s, %d, %p\n", __func__, getEnvResult, jenv); - - if (getEnvResult == JNI_EDETACHED) - { -#ifdef __ANDROID__ - if(JCALL2(AttachCurrentThread, vm, &jenv, NULL) < 0) -#else - if(JCALL2(AttachCurrentThread, vm, (void**)&jenv, NULL) < 0) -#endif - { - OC_DBG("Failed to get the environment"); - return -1; - } - } - - assert(jenv); - - // Get the Android Context - const jclass activityThreadClass = JCALL1(FindClass, jenv, "android/app/ActivityThread"); - const jmethodID currentActivityThreadMethod = JCALL3(GetStaticMethodID, jenv, activityThreadClass, "currentActivityThread", "()Landroid/app/ActivityThread;"); - jobject activityThread = JCALL2(CallStaticObjectMethod, jenv, activityThreadClass, currentActivityThreadMethod); - - const jmethodID getApplicationMethod = JCALL3(GetMethodID, jenv, activityThreadClass, "getApplication", "()Landroid/app/Application;"); - jobject context = JCALL2(CallObjectMethod, jenv, activityThread, getApplicationMethod); - JCALL1(DeleteLocalRef, jenv, activityThreadClass); - JCALL1(DeleteLocalRef, jenv, activityThread); - - // Get the FilesDir - const jclass activityClass = JCALL1(FindClass, jenv, "android/app/Activity"); - const jmethodID getFileDirsMethod = JCALL3(GetMethodID, jenv, activityClass, "getFilesDir", "()Ljava/io/File;"); - jobject filesDir = JCALL2(CallObjectMethod, jenv, context, getFileDirsMethod); - JCALL1(DeleteLocalRef, jenv, activityClass); - JCALL1(DeleteLocalRef, jenv, context); - - // Create a file object for the credentials directory - const jclass fileClass = JCALL1(FindClass, jenv, "java/io/File"); - const jmethodID fileCtorMethod = JCALL3(GetMethodID, jenv, fileClass, "", "(Ljava/io/File;Ljava/lang/String;)V"); - jstring credentials = JCALL1(NewStringUTF, jenv, "credentials"); - jobject credsDir = JCALL4(NewObject, jenv, fileClass, fileCtorMethod, filesDir, credentials); - JCALL1(DeleteLocalRef, jenv, filesDir); - JCALL1(DeleteLocalRef, jenv, credentials); - - // Test if the credentials directory already exists - const jmethodID fileExistsMethod = JCALL3(GetMethodID, jenv, fileClass, "exists", "()Z"); - jboolean exists = JCALL2(CallBooleanMethod, jenv, credsDir, fileExistsMethod); - - if (!exists) - { - // Create credentials directory - const jmethodID mkdirMethod = JCALL3(GetMethodID, jenv, fileClass, "mkdir", "()Z"); - jboolean mkDirCreated = JCALL2(CallBooleanMethod, jenv, credsDir, mkdirMethod); - if (!mkDirCreated) - { - OC_DBG("Failed to create credentials directory"); - return -1; - } - } - - // Get the credentials directory absolute path as a C string - const jmethodID getAbsPathMethod = JCALL3(GetMethodID, jenv, fileClass, "getAbsolutePath", "()Ljava/lang/String;"); - jstring credsDirPath = JCALL2(CallObjectMethod, jenv, credsDir, getAbsPathMethod); - const char *path = JCALL2(GetStringUTFChars, jenv, credsDirPath, 0); - OC_DBG("JNI: %s, %s\n", __func__, path); - JCALL1(DeleteLocalRef, jenv, fileClass); - JCALL1(DeleteLocalRef, jenv, credsDir); - - // Initialize credential storage - jni_storage_config(path); - - // Cleanup - JCALL2(ReleaseStringUTFChars, jenv, credsDirPath, path); - JCALL1(DeleteLocalRef, jenv, credsDirPath); - - if (JNI_EDETACHED == getEnvResult) { - JCALL0(DetachCurrentThread, vm); - OC_DBG("JNI: Detach"); - } - - return JNI_VERSION_1_6; -} -#endif - %} #if defined(SWIGJAVA) -- GitLab