Commit 6fd7cc99 authored by George Nash's avatar George Nash Committed by Rick Bell

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's avatarGeorge Nash <george.nash@intel.com>
parent 08edc8c8
......@@ -118,6 +118,7 @@
</Link>
<PreBuildEvent>
<Command>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</Command>
<Message>Copying dependency files into project.</Message>
......@@ -153,6 +154,7 @@ del $(SolutionDir)..\..\..\swig\iotivity-lite-java\src\org\iotivity\oc\*.java</C
</Link>
<PreBuildEvent>
<Command>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</Command>
<Message>Copying dependency files into project.</Message>
......@@ -264,6 +266,7 @@ del $(SolutionDir)..\..\..\swig\iotivity-lite-java\src\org\iotivity\oc\*.java</C
<ClCompile Include="..\..\..\..\swig\iotivity-lite-java\jni\oc_core_res_wrap.c" />
<ClCompile Include="..\..\..\..\swig\iotivity-lite-java\jni\oc_endpoint_wrap.c" />
<ClCompile Include="..\..\..\..\swig\iotivity-lite-java\jni\oc_introspection_wrap.c" />
<ClCompile Include="..\..\..\..\swig\iotivity-lite-java\jni\oc_iotivity_lite_jni.c" />
<ClCompile Include="..\..\..\..\swig\iotivity-lite-java\jni\oc_obt_wrap.c" />
<ClCompile Include="..\..\..\..\swig\iotivity-lite-java\jni\oc_pki_wrap.c" />
<ClCompile Include="..\..\..\..\swig\iotivity-lite-java\jni\oc_rep_wrap.c" />
......
......@@ -43,6 +43,9 @@
<ClCompile Include="..\..\..\..\swig\iotivity-lite-java\jni\oc_session_events_wrap.c">
<Filter>c_wrap</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\swig\iotivity-lite-java\jni\oc_iotivity_lite_jni.c">
<Filter>c_wrap</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
......@@ -62,12 +65,6 @@
<None Include="..\..\..\..\swig\swig_interfaces\oc_ri.i">
<Filter>swig_interfaces</Filter>
</None>
<None Include="..\..\..\..\swig\swig_interfaces\oc_cloud.i">
<Filter>swig_interfaces</Filter>
</None>
<None Include="..\..\..\..\swig\swig_interfaces\oc_session_events.i">
<Filter>swig_interfaces</Filter>
</None>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\..\..\swig\swig_interfaces\oc_api.i">
......@@ -106,6 +103,12 @@
<CustomBuild Include="..\..\..\..\swig\swig_interfaces\oc_uuid.i">
<Filter>swig_interfaces</Filter>
</CustomBuild>
<CustomBuild Include="..\..\..\..\swig\swig_interfaces\oc_cloud.i">
<Filter>swig_interfaces</Filter>
</CustomBuild>
<CustomBuild Include="..\..\..\..\swig\swig_interfaces\oc_session_events.i">
<Filter>swig_interfaces</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\..\swig\iotivity-lite-java\jni\oc_iotivity_lite_jni.h">
......
......@@ -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)
......
......@@ -49,6 +49,7 @@ fi
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 *.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/
/*
// 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 <assert.h>
#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, "<init>",
"(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);
}
}
......@@ -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 */
......@@ -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)