Imported Upstream version 1.0.1
[platform/upstream/iotivity.git] / service / easy-setup / sdk / mediator / android / jni / jniutil / src / jni_easy_setup_jvm.cpp
1 /******************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20 #include "jni_easy_setup_jvm.h"
21 #include <string>
22 #include "jni_easy_setup.h"
23
24 /**
25  * @class   JClassMap
26  * @brief   This class provides functions for initializing the Java class path and Java class.
27  *
28  */
29 class JClassMap {
30 public:
31     /**
32      *  Java Class
33      */
34     jclass classRef;
35     /**
36      *  Java Class Path
37      */
38     const char *szClassPath;
39
40     /**
41      * @brief constructor
42      */
43     JClassMap(const char *path) :
44             classRef(NULL) {
45         szClassPath = path;
46     }
47 };
48
49 /**
50  * @class   JObjectMap
51  * @brief   This class provides functins for initializing the Java Class path and Java Class
52  * Object.
53  *
54  */
55 class JObjectMap {
56 public:
57     /**
58      *  Java Object
59      */
60     jobject object;
61     /**
62      *  Java Class Path
63      */
64     const char *szClassPath;
65
66     /**
67      * @brief constructor
68      */
69     JObjectMap(const char *path) :
70             object(NULL) {
71         szClassPath = path;
72     }
73 };
74
75 static JClassMap gJClassMapArray[] = { JClassMap(
76         EASY_SETUP_SERVICE_NATIVE_API_CLASS_PATH), JClassMap(
77         EASY_SETUP_SERVICE_CALLBACK_NATIVE_API_CLASS_PATH) };
78
79 static JObjectMap gJObjectMapArray[] = { JObjectMap(
80         EASY_SETUP_SERVICE_CALLBACK_NATIVE_API_CLASS_PATH) };
81
82 static JNINativeMethod gEasySetupMethodTable[] = {
83     { "InitEasySetup", "()V", (void *) JNIInitEasySetup },
84     { "TerminateEasySetup", "()V", (void *) JNITerminateEasySetup },
85     { "ProvisionEnrollee", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V",
86                                 (void *) JNIProvisionEnrollee },
87     { "StopEnrolleeProvisioning", "(I)V", (void *) JNIStopEnrolleeProvisioning }, };
88
89 static int gEasySetupMethodTableSize = sizeof(gEasySetupMethodTable)
90         / sizeof(gEasySetupMethodTable[0]);
91
92 int InitializeJClassMapArray(JNIEnv *env) {
93     LOGI("InitializeJClassMapArray: Enter");
94
95     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
96
97     for (unsigned int i = 0; i < nLen; i++) {
98         jclass classRef = env->FindClass(gJClassMapArray[i].szClassPath);
99         if (NULL == classRef) {
100             LOGE("FindClass failed for [%s]", gJClassMapArray[i].szClassPath);
101             return -1;
102         }
103         gJClassMapArray[i].classRef = (jclass) env->NewGlobalRef(classRef);
104         env->DeleteLocalRef(classRef);
105     }
106
107     LOGI("InitializeJClassMapArray: Exit");
108     return 0;
109 }
110
111 jclass GetJClass(const char *szClassPath) {
112     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
113
114     jclass classRef = NULL;
115
116     for (unsigned int i = 0; i < nLen; i++) {
117         if (0 == strcmp(gJClassMapArray[i].szClassPath, szClassPath)) {
118             classRef = gJClassMapArray[i].classRef;
119             break;
120         }
121     }
122
123     return classRef;
124 }
125
126 void DeleteClassMapArray(JNIEnv *env) {
127     LOGI("DeleteClassMapArray: Enter");
128
129     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
130     for (unsigned int i = 0; i < nLen; i++) {
131         if (NULL != gJClassMapArray[i].classRef) {
132             env->DeleteGlobalRef(gJClassMapArray[i].classRef);
133             gJClassMapArray[i].classRef = NULL;
134         }
135     }
136
137     LOGI("DeleteClassMapArray: Exit");
138 }
139
140 int InitializeJObjectMapArray(JNIEnv *env) {
141     LOGI("InitializeJObjectMapArray: Enter");
142
143     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
144
145     for (unsigned int i = 0; i < nLen; i++) {
146         jclass classRef = env->FindClass(gJObjectMapArray[i].szClassPath);
147         if (NULL == classRef) {
148             LOGE("InitializeJObjectMapArray: FindClass failed for [%s]",
149                     gJObjectMapArray[i].szClassPath);
150             return -1;
151         }
152
153         std::string methodSignature = "()L";
154         methodSignature.append(gJObjectMapArray[i].szClassPath);
155         methodSignature.append(";");
156
157         // Get the object form "getInstance"
158         jmethodID methodid = env->GetStaticMethodID(classRef, "getInstance",
159                 methodSignature.c_str());
160         if (NULL == methodid) {
161             LOGE("InitializeJObjectMapArray: GetStaticMethodID failed for [%s]",
162                     gJObjectMapArray[i].szClassPath);
163             return -1;
164         }
165
166         // Get the singleton object
167         jobject objectRef = (jobject) env->CallStaticObjectMethod(classRef,
168                 methodid);
169         if (NULL == objectRef) {
170             LOGE(
171                     "InitializeJObjectMapArray: CallStaticObjectMethod failed for [%s]",
172                     gJObjectMapArray[i].szClassPath);
173             return -1;
174         }
175
176         gJObjectMapArray[i].object = (jobject) env->NewGlobalRef(objectRef);
177         env->DeleteLocalRef(classRef);
178     }
179
180     LOGI("InitializeJObjectMapArray: Exit");
181     return 0;
182 }
183
184 jobject GetJObjectInstance(const char *szClassPath) {
185     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
186
187     jobject object = NULL;
188
189     for (unsigned int i = 0; i < nLen; i++) {
190         if (0 == strcmp(gJObjectMapArray[i].szClassPath, szClassPath)) {
191             object = gJObjectMapArray[i].object;
192             break;
193         }
194     }
195
196     return object;
197 }
198
199 void DeleteObjectMapArray(JNIEnv *env) {
200     LOGI("DeleteObjectMapArray: Enter");
201
202     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
203     for (unsigned int i = 0; i < nLen; i++) {
204         if (NULL != gJObjectMapArray[i].object) {
205             env->DeleteGlobalRef(gJObjectMapArray[i].object);
206             gJObjectMapArray[i].object = NULL;
207         }
208     }
209
210     LOGI("DeleteObjectMapArray: Exit");
211 }
212
213 JavaVM *EasySetupJVM::m_jvm = NULL;
214 std::mutex EasySetupJVM::m_currentThreadMutex;
215 JNIEnv *EasySetupJVM::getEnv() {
216     std::unique_lock < std::mutex > scoped_lock(m_currentThreadMutex);
217
218     if (NULL == m_jvm) {
219         LOGE("Failed to get JVM");
220         return NULL;
221     }
222
223     JNIEnv *env = NULL;
224     jint ret = m_jvm->GetEnv((void **) &env, JNI_CURRENT_VERSION);
225     switch (ret) {
226     case JNI_OK:
227         return env;
228     case JNI_EDETACHED:
229         if (0 > m_jvm->AttachCurrentThread(&env, NULL)) {
230             LOGE("Failed to attach current thread to env");
231             return NULL;
232         }
233         return env;
234     case JNI_EVERSION:
235         LOGE("JNI version not supported");
236         return NULL;
237     default:
238         LOGE("Failed to get the environment");
239         return NULL;
240     }
241 }
242
243 void EasySetupJVM::releaseEnv() {
244     std::unique_lock < std::mutex > scoped_lock(m_currentThreadMutex);
245
246     if (0 == m_jvm) {
247         LOGE("Failed to release JVM");
248         return;
249     }
250
251     m_jvm->DetachCurrentThread();
252 }
253
254 #ifdef __cplusplus
255 extern "C" {
256 #endif
257 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
258     LOGD("JNI_OnLoad: Enter");
259
260     if (!vm) {
261         LOGE("JNI_OnLoad: vm is invalid");
262         return JNI_ERR;
263     }
264
265     JNIEnv *env = NULL;
266     if (JNI_OK != vm->GetEnv((void **) &env, JNI_CURRENT_VERSION)) {
267         LOGE("JNI_OnLoad: Version check is failed!");
268         return JNI_ERR;
269     }
270
271     if (0 != InitializeJClassMapArray(env)) {
272         LOGE("JNI_OnLoad: Initialize JClass Array failed!");
273         return JNI_ERR;
274     }
275
276     if (0 != InitializeJObjectMapArray(env)) {
277         LOGE("JNI_OnLoad: Initialize JObject Array failed!");
278         return JNI_ERR;
279     }
280
281     jclass easySetupClassRef = GetJClass(
282             EASY_SETUP_SERVICE_NATIVE_API_CLASS_PATH);
283     if (NULL == easySetupClassRef) {
284         LOGE("JNI_OnLoad: GetJClass gEasySetupClass failed !");
285         return JNI_ERR;
286     }
287     env->RegisterNatives(easySetupClassRef, gEasySetupMethodTable,
288             gEasySetupMethodTableSize);
289
290     EasySetupJVM::m_jvm = vm;
291
292     LOGI("JNI_OnLoad: Exit");
293     return JNI_CURRENT_VERSION;
294 }
295
296 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
297 {
298     LOGD("JNI_OnUnload: Enter");
299
300     JNIEnv *env = NULL;
301     if (JNI_OK != vm->GetEnv((void **)&env, JNI_CURRENT_VERSION))
302     {
303         LOGE("JNI_OnLoad: Version check is failed!");
304         return;
305     }
306
307     // delete all class references
308     DeleteClassMapArray(env);
309
310     // delete all jobject
311     DeleteObjectMapArray(env);
312
313     LOGD("JNI_OnUnload: Exit");
314 }
315
316 #ifdef __cplusplus
317 }
318 #endif
319