[IOT-931] Added send logic to check write/notify in BLE
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / android / caleserver.c
1 /******************************************************************
2  *
3  * Copyright 2014 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
21 #include <jni.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <android/log.h>
25 #include <unistd.h>
26 #include "caleserver.h"
27 #include "caleutils.h"
28 #include "caleinterface.h"
29 #include "caadapterutils.h"
30
31 #include "logger.h"
32 #include "oic_malloc.h"
33 #include "cathreadpool.h"
34 #include "camutex.h"
35 #include "uarraylist.h"
36 #include "org_iotivity_ca_CaLeServerInterface.h"
37
38 #define TAG PCF("OIC_CA_LE_SERVER")
39
40 #define WAIT_TIME_WRITE_CHARACTERISTIC 10000000
41
42 static JavaVM *g_jvm = NULL;
43 static jobject g_context = NULL;
44 static jobject g_bluetoothGattServer = NULL;
45 static jobject g_bluetoothGattServerCallback = NULL;
46 static jobject g_leAdvertiseCallback = NULL;
47
48 static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
49 static CABLEErrorHandleCallback g_serverErrorCallback;
50
51 static u_arraylist_t *g_connectedDeviceList = NULL;
52
53 static bool g_isStartServer = false;
54 static bool g_isInitializedServer = false;
55
56 static jbyteArray g_sendBuffer = NULL;
57
58 static CABLEDataReceivedCallback g_CABLEServerDataReceivedCallback = NULL;
59 static ca_mutex g_bleReqRespCbMutex = NULL;
60 static ca_mutex g_bleClientBDAddressMutex = NULL;
61 static ca_mutex g_connectedDeviceListMutex = NULL;
62
63 static ca_mutex g_threadSendMutex = NULL;
64 static ca_mutex g_threadSendNotifyMutex = NULL;
65 static ca_cond g_threadSendNotifyCond = NULL;
66 static bool g_isSignalSetFlag = false;
67
68 void CALEServerJNISetContext()
69 {
70     OIC_LOG(DEBUG, TAG, "CALEServerJNISetContext");
71     g_context = (jobject) CANativeJNIGetContext();
72 }
73
74 void CALeServerJniInit()
75 {
76     OIC_LOG(DEBUG, TAG, "CALeServerJniInit");
77     g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
78 }
79
80 CAResult_t CALEServerCreateJniInterfaceObject()
81 {
82     OIC_LOG(DEBUG, TAG, "CALEServerCreateJniInterfaceObject");
83
84     if (!g_context)
85     {
86         OIC_LOG(ERROR, TAG, "g_context is null");
87         return CA_STATUS_FAILED;
88     }
89
90     if (!g_jvm)
91     {
92         OIC_LOG(ERROR, TAG, "g_jvm is null");
93         return CA_STATUS_FAILED;
94     }
95
96     bool isAttached = false;
97     JNIEnv* env;
98     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
99     if (JNI_OK != res)
100     {
101         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
102         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
103
104         if (JNI_OK != res)
105         {
106             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
107             return CA_STATUS_FAILED;
108         }
109         isAttached = true;
110     }
111
112     jclass jni_LEInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeServerInterface");
113     if (!jni_LEInterface)
114     {
115         OIC_LOG(ERROR, TAG, "Could not get CaLeServerInterface class");
116         goto exit;
117     }
118
119     jmethodID LeInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_LEInterface, "<init>",
120                                                                  "()V");
121     if (!LeInterfaceConstructorMethod)
122     {
123         OIC_LOG(ERROR, TAG, "Could not get CaLeServerInterface constructor method");
124         goto exit;
125     }
126
127     (*env)->NewObject(env, jni_LEInterface, LeInterfaceConstructorMethod, g_context);
128     OIC_LOG(DEBUG, TAG, "Create instance for CaLeServerInterface");
129
130     if (isAttached)
131     {
132         (*g_jvm)->DetachCurrentThread(g_jvm);
133     }
134
135     return CA_STATUS_OK;
136
137     exit:
138
139     if (isAttached)
140     {
141         (*g_jvm)->DetachCurrentThread(g_jvm);
142     }
143
144     return CA_STATUS_FAILED;
145 }
146
147 jobject CALEServerSetResponseData(JNIEnv *env, jbyteArray responseData)
148 {
149     OIC_LOG(DEBUG, TAG, "IN - CALEServerSetResponseData");
150     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
151     VERIFY_NON_NULL_RET(responseData, TAG, "responseData is null", NULL);
152
153     if (!g_bluetoothGattServer)
154     {
155         OIC_LOG(ERROR, TAG, "Check BluetoothGattServer status");
156         return NULL;
157     }
158
159     if (!CALEIsEnableBTAdapter(env))
160     {
161         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
162         return NULL;
163     }
164
165     OIC_LOG(DEBUG, TAG, "CALEServerSetResponseData");
166
167     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
168                                                            "android/bluetooth/BluetoothGattServer");
169     if (!jni_cid_bluetoothGattServer)
170     {
171         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
172         return NULL;
173     }
174
175     jclass jni_cid_bluetoothGattService = (*env)->FindClass(env, "android/bluetooth/"
176                                                             "BluetoothGattService");
177     if (!jni_cid_bluetoothGattService)
178     {
179         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattService is null");
180         return NULL;
181     }
182
183     jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/"
184                                                                    "BluetoothGattCharacteristic");
185     if (!jni_cid_bluetoothGattCharacteristic)
186     {
187         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattCharacteristic is null");
188         return NULL;
189     }
190
191     jmethodID jni_mid_getService = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
192                                                        "getService",
193                                                        "(Ljava/util/UUID;)Landroid/bluetooth/"
194                                                        "BluetoothGattService;");
195     if (!jni_mid_getService)
196     {
197         OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
198         return NULL;
199     }
200
201     jobject jni_obj_serviceUUID = CALEGetUuidFromString(env, OIC_GATT_SERVICE_UUID);
202     if (!jni_obj_serviceUUID)
203     {
204         OIC_LOG(ERROR, TAG, "jni_obj_serviceUUID is null");
205         return NULL;
206     }
207
208     jobject jni_obj_bluetoothGattService = (*env)->CallObjectMethod(env, g_bluetoothGattServer,
209                                                                     jni_mid_getService,
210                                                                     jni_obj_serviceUUID);
211     if (!jni_obj_bluetoothGattService)
212     {
213         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattService is null");
214         return NULL;
215     }
216
217     jmethodID jni_mid_getCharacteristic = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
218                                                               "getCharacteristic",
219                                                               "(Ljava/util/UUID;)"
220                                                               "Landroid/bluetooth/"
221                                                               "BluetoothGattCharacteristic;");
222     if (!jni_mid_getCharacteristic)
223     {
224         OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null");
225         return NULL;
226     }
227
228     jobject jni_obj_responseUUID = CALEGetUuidFromString(env,
229                                                          OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
230     if (!jni_obj_responseUUID)
231     {
232         OIC_LOG(ERROR, TAG, "jni_obj_responseUUID is null");
233         return NULL;
234     }
235
236     jobject jni_obj_bluetoothGattCharacteristic = (*env)->CallObjectMethod(
237             env, jni_obj_bluetoothGattService, jni_mid_getCharacteristic, jni_obj_responseUUID);
238     if (!jni_obj_bluetoothGattCharacteristic)
239     {
240         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattCharacteristic is null");
241         return NULL;
242     }
243
244     jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_bluetoothGattCharacteristic,
245                                                      "setValue", "([B)Z");
246     if (!jni_mid_setValue)
247     {
248         OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
249         return NULL;
250     }
251
252     jboolean jni_boolean_setValue = (*env)->CallBooleanMethod(env,
253                                                               jni_obj_bluetoothGattCharacteristic,
254                                                               jni_mid_setValue, responseData);
255     if (JNI_FALSE == jni_boolean_setValue)
256     {
257         OIC_LOG(ERROR, TAG, "Fail to set response data");
258     }
259
260     OIC_LOG(DEBUG, TAG, "OUT - CALEServerSetResponseData");
261     return jni_obj_bluetoothGattCharacteristic;
262 }
263
264 CAResult_t CALEServerSendResponseData(JNIEnv *env, jobject device, jobject responseData)
265 {
266     OIC_LOG(DEBUG, TAG, "CALEServerSendResponseData");
267     VERIFY_NON_NULL(responseData, TAG, "responseData is null");
268     VERIFY_NON_NULL(device, TAG, "device is null");
269     VERIFY_NON_NULL(env, TAG, "env is null");
270
271     if (!CALEIsEnableBTAdapter(env))
272     {
273         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
274         return CA_ADAPTER_NOT_ENABLED;
275     }
276
277     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
278                                                            "android/bluetooth/BluetoothGattServer");
279     if (!jni_cid_bluetoothGattServer)
280     {
281         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
282         return CA_STATUS_FAILED;
283     }
284
285     jmethodID jni_mid_notifyCharacteristicChanged = (*env)->GetMethodID(
286             env, jni_cid_bluetoothGattServer, "notifyCharacteristicChanged",
287             "(Landroid/bluetooth/BluetoothDevice;"
288             "Landroid/bluetooth/BluetoothGattCharacteristic;Z)Z");
289     if (!jni_mid_notifyCharacteristicChanged)
290     {
291         OIC_LOG(ERROR, TAG, "jni_mid_notifyCharacteristicChanged is null");
292         return CA_STATUS_FAILED;
293     }
294
295     jboolean jni_boolean_notifyCharacteristicChanged = (*env)->CallBooleanMethod(
296             env, g_bluetoothGattServer, jni_mid_notifyCharacteristicChanged, device, responseData,
297             JNI_FALSE);
298     if (JNI_FALSE == jni_boolean_notifyCharacteristicChanged)
299     {
300         OIC_LOG(ERROR, TAG, "Fail to notify characteristic");
301         return CA_SEND_FAILED;
302     }
303
304     OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
305     ca_mutex_lock(g_threadSendNotifyMutex);
306     if (!g_isSignalSetFlag)
307     {
308         OIC_LOG(DEBUG, TAG, "wait for callback to notify notifyCharacteristic is success");
309         if (0 != ca_cond_wait_for(g_threadSendNotifyCond, g_threadSendNotifyMutex,
310                                   WAIT_TIME_WRITE_CHARACTERISTIC))
311         {
312             OIC_LOG(ERROR, TAG, "there is no response. notifyCharacteristic has failed");
313             ca_mutex_unlock(g_threadSendNotifyMutex);
314             return CA_STATUS_FAILED;
315         }
316     }
317     // reset flag set by writeCharacteristic Callback
318     g_isSignalSetFlag = false;
319     ca_mutex_unlock(g_threadSendNotifyMutex);
320     OIC_LOG(INFO, TAG, "notifyCharacteristic success");
321     return CA_STATUS_OK;
322 }
323
324 CAResult_t CALEServerSendResponse(JNIEnv *env, jobject device, jint requestId, jint status,
325                                         jint offset, jbyteArray value)
326 {
327     OIC_LOG(DEBUG, TAG, "IN - CALEServerSendResponse");
328     VERIFY_NON_NULL(env, TAG, "env is null");
329     VERIFY_NON_NULL(device, TAG, "device is null");
330     VERIFY_NON_NULL(value, TAG, "value is null");
331
332     OIC_LOG(DEBUG, TAG, "CALEServerSendResponse");
333
334     if (!CALEIsEnableBTAdapter(env))
335     {
336         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
337         return CA_ADAPTER_NOT_ENABLED;
338     }
339
340     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
341                                                            "android/bluetooth/BluetoothGattServer");
342     if (!jni_cid_bluetoothGattServer)
343     {
344         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
345         return CA_STATUS_FAILED;
346     }
347
348     jmethodID jni_mid_sendResponse = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
349                                                          "sendResponse",
350                                                          "(Landroid/bluetooth/BluetoothDevice;"
351                                                          "III[B)Z");
352     if (!jni_mid_sendResponse)
353     {
354         OIC_LOG(ERROR, TAG, "jni_mid_sendResponse is null");
355         return CA_STATUS_FAILED;
356     }
357
358     jboolean jni_boolean_sendResponse = (*env)->CallBooleanMethod(env, g_bluetoothGattServer,
359                                                                   jni_mid_sendResponse, device,
360                                                                   requestId, status, offset,
361                                                                   value);
362     if (JNI_FALSE == jni_boolean_sendResponse)
363     {
364         OIC_LOG(ERROR, TAG, "Fail to send response for gatt characteristic write request");
365         return CA_SEND_FAILED;
366     }
367
368     OIC_LOG(DEBUG, TAG, "OUT - CALEServerSendResponse");
369     return CA_STATUS_OK;
370 }
371
372 CAResult_t CALEStartAdvertise()
373 {
374     if (!g_jvm)
375     {
376         OIC_LOG(ERROR, TAG, "g_jvm is null");
377         return CA_STATUS_FAILED;
378     }
379
380     bool isAttached = false;
381     JNIEnv* env;
382     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
383     if (JNI_OK != res)
384     {
385         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
386         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
387
388         if (JNI_OK != res)
389         {
390             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
391             return CA_STATUS_FAILED;
392         }
393         isAttached = true;
394     }
395
396     // start advertise
397     CAResult_t ret = CALEServerStartAdvertise(env, g_leAdvertiseCallback);
398     if (CA_STATUS_OK != ret)
399     {
400         OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed");
401     }
402
403     if (isAttached)
404     {
405         (*g_jvm)->DetachCurrentThread(g_jvm);
406     }
407     return ret;
408 }
409
410 CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback)
411 {
412     OIC_LOG(DEBUG, TAG, "IN - CALEServerStartAdvertise");
413     VERIFY_NON_NULL(env, TAG, "env is null");
414     VERIFY_NON_NULL(advertiseCallback, TAG, "advertiseCallback is null");
415
416     if (!CALEIsEnableBTAdapter(env))
417     {
418         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
419         return CA_ADAPTER_NOT_ENABLED;
420     }
421
422     jclass jni_cid_AdvertiseSettings = (*env)->FindClass(env,
423                                                          "android/bluetooth/le/"
424                                                          "AdvertiseSettings$Builder");
425     if (!jni_cid_AdvertiseSettings)
426     {
427         OIC_LOG(ERROR, TAG, "jni_cid_AdvertiseSettings is null");
428         return CA_STATUS_FAILED;
429     }
430
431     jmethodID jni_mid_AdvertiseSettings = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings,
432                                                               "<init>", "()V");
433     if (!jni_mid_AdvertiseSettings)
434     {
435         OIC_LOG(ERROR, TAG, "jni_mid_AdvertiseSettings is null");
436         return CA_STATUS_FAILED;
437     }
438
439     jobject jni_AdvertiseSettings = (*env)->NewObject(env, jni_cid_AdvertiseSettings,
440                                                       jni_mid_AdvertiseSettings);
441     if (!jni_AdvertiseSettings)
442     {
443         OIC_LOG(ERROR, TAG, "jni_AdvertiseSettings is null");
444         return CA_STATUS_FAILED;
445     }
446
447     jmethodID jni_mid_setAdvertiseMode = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings,
448                                                              "setAdvertiseMode",
449                                                              "(I)Landroid/bluetooth/le/"
450                                                              "AdvertiseSettings$Builder;");
451     if (!jni_mid_setAdvertiseMode)
452     {
453         OIC_LOG(ERROR, TAG, "jni_mid_setAdvertiseMode is null");
454         return CA_STATUS_FAILED;
455     }
456
457     // 0: Low power, 1: Balanced
458     jobject jni_obj_setAdvertiseMode = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
459                                                                 jni_mid_setAdvertiseMode, 0);
460     if (!jni_obj_setAdvertiseMode)
461     {
462         OIC_LOG(ERROR, TAG, "jni_obj_setAdvertiseMode is null");
463         return CA_STATUS_FAILED;
464     }
465
466     jmethodID jni_mid_setConnectable = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings,
467                                                            "setConnectable",
468                                                            "(Z)Landroid/bluetooth/le/"
469                                                            "AdvertiseSettings$Builder;");
470     if (!jni_mid_setConnectable)
471     {
472         OIC_LOG(ERROR, TAG, "jni_mid_setConnectable is null");
473         return CA_STATUS_FAILED;
474     }
475
476     jobject jni_obj_setConnectable = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
477                                                               jni_mid_setConnectable, JNI_TRUE);
478     if (!jni_obj_setConnectable)
479     {
480         OIC_LOG(ERROR, TAG, "jni_obj_setConnectable is null");
481         return CA_STATUS_FAILED;
482     }
483
484     jmethodID jni_mid_setTimeout = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings, "setTimeout",
485                                                        "(I)Landroid/bluetooth/le/"
486                                                        "AdvertiseSettings$Builder;");
487     if (!jni_mid_setTimeout)
488     {
489         OIC_LOG(ERROR, TAG, "jni_mid_setTimeout is null");
490         return CA_STATUS_FAILED;
491     }
492
493     //A value of 0 will disable the time limit
494     jobject jni_obj_setTimeout = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
495                                                           jni_mid_setTimeout, 0);
496     if (!jni_obj_setTimeout)
497     {
498         OIC_LOG(ERROR, TAG, "jni_obj_setTimeout is null");
499         return CA_STATUS_FAILED;
500     }
501
502     jclass jni_cid_AdvertiseDataBuilder = (*env)->FindClass(env,
503                                                             "android/bluetooth/le/"
504                                                             "AdvertiseData$Builder");
505     if (!jni_cid_AdvertiseDataBuilder)
506     {
507         OIC_LOG(ERROR, TAG, "jni_cid_AdvertiseDataBuilder is null");
508         return CA_STATUS_FAILED;
509     }
510
511     jmethodID jni_mid_AdvertiseDataBuilder = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
512                                                                  "<init>", "()V");
513     if (!jni_mid_AdvertiseDataBuilder)
514     {
515         OIC_LOG(ERROR, TAG, "jni_mid_AdvertiseDataBuilder is null");
516         return CA_STATUS_FAILED;
517     }
518
519     jobject jni_AdvertiseDataBuilder = (*env)->NewObject(env, jni_cid_AdvertiseDataBuilder,
520                                                          jni_mid_AdvertiseDataBuilder);
521     if (!jni_AdvertiseDataBuilder)
522     {
523         OIC_LOG(ERROR, TAG, "jni_AdvertiseDataBuilder is null");
524         return CA_STATUS_FAILED;
525     }
526
527     jobject jni_obj_serviceUUID = CALEGetUuidFromString(env, OIC_GATT_SERVICE_UUID);
528     if (!jni_obj_serviceUUID)
529     {
530         OIC_LOG(ERROR, TAG, "jni_obj_serviceUUID is null");
531         return CA_STATUS_FAILED;
532     }
533
534     jobject jni_ParcelUuid = CALEGetParcelUuid(env, jni_obj_serviceUUID);
535     if (!jni_ParcelUuid)
536     {
537         OIC_LOG(ERROR, TAG, "jni_ParcelUuid is null");
538         return CA_STATUS_FAILED;
539     }
540
541     jmethodID jni_mid_addServiceUuid = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
542                                                            "addServiceUuid",
543                                                            "(Landroid/os/ParcelUuid;)Landroid/"
544                                                            "bluetooth/le/AdvertiseData$Builder;");
545     if (!jni_mid_addServiceUuid)
546     {
547         OIC_LOG(ERROR, TAG, "jni_mid_addServiceUuid is null");
548         return CA_STATUS_FAILED;
549     }
550
551     jobject jni_obj_addServiceUuid = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder,
552                                                               jni_mid_addServiceUuid,
553                                                               jni_ParcelUuid);
554     if (!jni_obj_addServiceUuid)
555     {
556         OIC_LOG(ERROR, TAG, "jni_obj_addServiceUuid is null");
557         return CA_STATUS_FAILED;
558     }
559
560     jclass jni_cid_BTAdapter = (*env)->FindClass(env, "android/bluetooth/BluetoothAdapter");
561     if (!jni_cid_BTAdapter)
562     {
563         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
564         return CA_STATUS_FAILED;
565     }
566
567     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
568                                                                     "getDefaultAdapter",
569                                                                     "()Landroid/bluetooth/"
570                                                                     "BluetoothAdapter;");
571     if (!jni_mid_getDefaultAdapter)
572     {
573         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
574         return CA_STATUS_FAILED;
575     }
576
577     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
578                                                                jni_mid_getDefaultAdapter);
579     if (!jni_obj_BTAdapter)
580     {
581         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
582         return CA_STATUS_FAILED;
583     }
584
585     jmethodID jni_mid_getBluetoothLeAdvertiser = (*env)->GetMethodID(env, jni_cid_BTAdapter,
586                                                                      "getBluetoothLeAdvertiser",
587                                                                      "()Landroid/bluetooth/le/"
588                                                                      "BluetoothLeAdvertiser;");
589     if (!jni_mid_getBluetoothLeAdvertiser)
590     {
591         OIC_LOG(ERROR, TAG, "jni_mid_getBluetoothLeAdvertiser is null");
592         return CA_STATUS_FAILED;
593     }
594
595     jobject jni_obj_getBluetoothLeAdvertiser = (*env)->CallObjectMethod(
596             env, jni_obj_BTAdapter, jni_mid_getBluetoothLeAdvertiser);
597     if (!jni_obj_getBluetoothLeAdvertiser)
598     {
599         OIC_LOG(ERROR, TAG, "jni_obj_getBluetoothLeAdvertiser is null");
600         return CA_STATUS_FAILED;
601     }
602
603     jmethodID jni_mid_build_LeAdvertiseSettings = (*env)->GetMethodID(env,
604                                                                       jni_cid_AdvertiseSettings,
605                                                                       "build",
606                                                                       "()Landroid/bluetooth/le/"
607                                                                       "AdvertiseSettings;");
608     if (!jni_mid_build_LeAdvertiseSettings)
609     {
610         OIC_LOG(ERROR, TAG, "jni_mid_build_LeAdvertiseSettings is null");
611         return CA_STATUS_FAILED;
612     }
613
614     jobject jni_obj_build_LeAdvertiseSettings = (*env)->CallObjectMethod(
615             env, jni_AdvertiseSettings, jni_mid_build_LeAdvertiseSettings);
616     if (!jni_obj_build_LeAdvertiseSettings)
617     {
618         OIC_LOG(ERROR, TAG, "jni_obj_build_LeAdvertiseSettings is null");
619         return CA_STATUS_FAILED;
620     }
621
622     jmethodID jni_mid_build_LeAdvertiseData = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
623                                                                   "build",
624                                                                   "()Landroid/bluetooth/le/"
625                                                                   "AdvertiseData;");
626     if (!jni_mid_build_LeAdvertiseData)
627     {
628         OIC_LOG(ERROR, TAG, "jni_mid_build_LeAdvertiseData is null");
629         return CA_STATUS_FAILED;
630     }
631
632     jobject jni_obj_build_LeAdvertiseData = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder,
633                                                                      jni_mid_build_LeAdvertiseData);
634     if (!jni_obj_build_LeAdvertiseData)
635     {
636         OIC_LOG(ERROR, TAG, "jni_obj_build_LeAdvertiseData is null");
637         return CA_STATUS_FAILED;
638     }
639
640     jclass jni_cid_leAdvertiser = (*env)->FindClass(env,
641                                                     "android/bluetooth/le/BluetoothLeAdvertiser");
642     if (!jni_cid_leAdvertiser)
643     {
644         OIC_LOG(ERROR, TAG, "jni_cid_leAdvertiser is null");
645         return CA_STATUS_FAILED;
646     }
647
648     jmethodID jni_mid_startAdvertising = (*env)->GetMethodID(env, jni_cid_leAdvertiser,
649                                                              "startAdvertising",
650                                                              "(Landroid/bluetooth/le/"
651                                                              "AdvertiseSettings;Landroid/bluetooth/"
652                                                              "le/AdvertiseData;Landroid/bluetooth/"
653                                                              "le/AdvertiseCallback;)V");
654     if (!jni_mid_startAdvertising)
655     {
656         OIC_LOG(ERROR, TAG, "jni_mid_startAdvertising is null");
657         return CA_STATUS_FAILED;
658     }
659
660     (*env)->CallVoidMethod(env, jni_obj_getBluetoothLeAdvertiser, jni_mid_startAdvertising,
661                            jni_obj_build_LeAdvertiseSettings, jni_obj_build_LeAdvertiseData,
662                            advertiseCallback);
663
664     if ((*env)->ExceptionCheck(env))
665     {
666         OIC_LOG(ERROR, TAG, "StartAdvertising has failed");
667         (*env)->ExceptionDescribe(env);
668         (*env)->ExceptionClear(env);
669         return CA_STATUS_FAILED;
670     }
671
672     OIC_LOG(DEBUG, TAG, "Advertising started!!");
673
674     OIC_LOG(DEBUG, TAG, "OUT - CALEServerStartAdvertise");
675     return CA_STATUS_OK;
676 }
677
678 CAResult_t CALEServerStopAdvertise(JNIEnv *env, jobject advertiseCallback)
679 {
680     OIC_LOG(DEBUG, TAG, "LEServerStopAdvertise");
681     VERIFY_NON_NULL(env, TAG, "env is null");
682     VERIFY_NON_NULL(advertiseCallback, TAG, "advertiseCallback is null");
683
684     if (!CALEIsEnableBTAdapter(env))
685     {
686         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
687         return CA_ADAPTER_NOT_ENABLED;
688     }
689
690     jclass jni_cid_BTAdapter = (*env)->FindClass(env, "android/bluetooth/BluetoothAdapter");
691     if (!jni_cid_BTAdapter)
692     {
693         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
694         return CA_STATUS_FAILED;
695     }
696
697     jclass jni_cid_leAdvertiser = (*env)->FindClass(env,
698                                                     "android/bluetooth/le/BluetoothLeAdvertiser");
699     if (!jni_cid_leAdvertiser)
700     {
701         OIC_LOG(ERROR, TAG, "jni_cid_leAdvertiser is null");
702         return CA_STATUS_FAILED;
703     }
704
705     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
706                                                                     "getDefaultAdapter",
707                                                                     "()Landroid/bluetooth/"
708                                                                     "BluetoothAdapter;");
709     if (!jni_mid_getDefaultAdapter)
710     {
711         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
712         return CA_STATUS_FAILED;
713     }
714
715     jmethodID jni_mid_getBTLeAdvertiser = (*env)->GetMethodID(env, jni_cid_BTAdapter,
716                                                                      "getBluetoothLeAdvertiser",
717                                                                      "()Landroid/bluetooth/le/"
718                                                                      "BluetoothLeAdvertiser;");
719     if (!jni_mid_getBTLeAdvertiser)
720     {
721         OIC_LOG(ERROR, TAG, "jni_mid_getBTLeAdvertiser is null");
722         return CA_STATUS_FAILED;
723     }
724
725     jmethodID jni_mid_stopAdvertising = (*env)->GetMethodID(env, jni_cid_leAdvertiser,
726                                                             "stopAdvertising",
727                                                             "(Landroid/bluetooth/le/"
728                                                             "AdvertiseCallback;)V");
729     if (!jni_mid_stopAdvertising)
730     {
731         OIC_LOG(ERROR, TAG, "jni_mid_stopAdvertising is null");
732         return CA_STATUS_FAILED;
733     }
734
735     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
736                                                                jni_mid_getDefaultAdapter);
737     if (!jni_obj_BTAdapter)
738     {
739         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
740         return CA_STATUS_FAILED;
741     }
742
743     jobject jni_obj_getBluetoothLeAdvertiser = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
744                                                                         jni_mid_getBTLeAdvertiser);
745     if (!jni_obj_getBluetoothLeAdvertiser)
746     {
747         OIC_LOG(ERROR, TAG, "jni_obj_getBluetoothLeAdvertiser is null");
748         return CA_STATUS_FAILED;
749     }
750
751     (*env)->CallVoidMethod(env, jni_obj_getBluetoothLeAdvertiser, jni_mid_stopAdvertising,
752                            advertiseCallback);
753     if ((*env)->ExceptionCheck(env))
754     {
755         OIC_LOG(ERROR, TAG, "getBluetoothLeAdvertiser has failed");
756         (*env)->ExceptionDescribe(env);
757         (*env)->ExceptionClear(env);
758         return CA_STATUS_FAILED;
759     }
760
761     OIC_LOG(DEBUG, TAG, "Advertising stopped!!");
762     return CA_STATUS_OK;
763 }
764
765 CAResult_t CALEServerStartGattServer(JNIEnv *env, jobject gattServerCallback)
766 {
767     OIC_LOG(DEBUG, TAG, "IN - CALEServerStartGattServer");
768     VERIFY_NON_NULL(env, TAG, "env is null");
769     VERIFY_NON_NULL(gattServerCallback, TAG, "gattServerCallback is null");
770
771     if (!CALEIsEnableBTAdapter(env))
772     {
773         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
774         return CA_ADAPTER_NOT_ENABLED;
775     }
776
777     if (g_isStartServer)
778     {
779         OIC_LOG(DEBUG, TAG, "Gatt server already started");
780     }
781
782     g_bluetoothGattServerCallback = (*env)->NewGlobalRef(env, gattServerCallback);
783
784     // open gatt server
785     jobject bluetoothGattServer = CALEServerOpenGattServer(env);
786     if (!bluetoothGattServer)
787     {
788         OIC_LOG(ERROR, TAG, "bluetoothGattServer is null");
789         return CA_STATUS_FAILED;
790     }
791
792     g_bluetoothGattServer = (*env)->NewGlobalRef(env, bluetoothGattServer);
793     if (!g_bluetoothGattServer)
794     {
795         OIC_LOG(ERROR, TAG, "g_bluetoothGattServer is null");
796         return CA_STATUS_FAILED;
797     }
798
799     // create gatt service
800     jobject bluetoothGattService = CALEServerCreateGattService(env);
801     if (!bluetoothGattService)
802     {
803         OIC_LOG(ERROR, TAG, "bluetoothGattService is null");
804         return CA_STATUS_FAILED;
805     }
806
807     // add gatt service
808     CAResult_t res = CALEServerAddGattService(env, g_bluetoothGattServer,
809                                               bluetoothGattService);
810     if (CA_STATUS_OK != res)
811     {
812         OIC_LOG(ERROR, TAG, "CALEServerAddGattService has failed");
813     }
814     return res;
815 }
816
817 jobject CALEServerOpenGattServer(JNIEnv *env)
818 {
819     OIC_LOG(DEBUG, TAG, "IN - CALEServerOpenGattServer");
820     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
821
822     if (!CALEIsEnableBTAdapter(env))
823     {
824         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
825         return NULL;
826     }
827
828     jclass jni_cid_context = (*env)->FindClass(env, "android/content/Context");
829     if (!jni_cid_context)
830     {
831         OIC_LOG(ERROR, TAG, "jni_cid_context is null");
832         return NULL;
833     }
834
835     jclass jni_cid_bluetoothManager = (*env)->FindClass(env, "android/bluetooth/BluetoothManager");
836     if (!jni_cid_bluetoothManager)
837     {
838         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothManager is null");
839         return NULL;
840     }
841
842     jfieldID jni_fid_bluetoothService = (*env)->GetStaticFieldID(env, jni_cid_context,
843                                                                  "BLUETOOTH_SERVICE",
844                                                                  "Ljava/lang/String;");
845     if (!jni_fid_bluetoothService)
846     {
847         OIC_LOG(ERROR, TAG, "jni_fid_bluetoothService is null");
848         return NULL;
849     }
850
851     jmethodID jni_mid_getSystemService = (*env)->GetMethodID(env, jni_cid_context,
852                                                              "getSystemService",
853                                                              "(Ljava/lang/String;)"
854                                                              "Ljava/lang/Object;");
855     if (!jni_mid_getSystemService)
856     {
857         OIC_LOG(ERROR, TAG, "jni_mid_getSystemService is null");
858         return NULL;
859     }
860
861     jmethodID jni_mid_openGattServer = (*env)->GetMethodID(env, jni_cid_bluetoothManager,
862                                                            "openGattServer",
863                                                            "(Landroid/content/Context;"
864                                                            "Landroid/bluetooth/"
865                                                            "BluetoothGattServerCallback;)"
866                                                            "Landroid/bluetooth/"
867                                                            "BluetoothGattServer;");
868     if (!jni_mid_openGattServer)
869     {
870         OIC_LOG(ERROR, TAG, "jni_mid_openGattServer is null");
871         return NULL;
872     }
873
874     jobject jni_obj_bluetoothService = (*env)->GetStaticObjectField(env, jni_cid_context,
875                                                                     jni_fid_bluetoothService);
876     if (!jni_obj_bluetoothService)
877     {
878         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothService is null");
879         return NULL;
880     }
881
882     jobject jni_obj_bluetoothManager = (*env)->CallObjectMethod(env, g_context,
883                                                                 jni_mid_getSystemService,
884                                                                 jni_obj_bluetoothService);
885     if (!jni_obj_bluetoothManager)
886     {
887         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothManager is null");
888         return NULL;
889     }
890
891     jobject jni_obj_bluetoothGattServer = (*env)->CallObjectMethod(env, jni_obj_bluetoothManager,
892                                                                    jni_mid_openGattServer,
893                                                                    g_context,
894                                                                    g_bluetoothGattServerCallback);
895     if (!jni_obj_bluetoothGattServer)
896     {
897         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattServer is null");
898         return NULL;
899     }
900
901     OIC_LOG(DEBUG, TAG, "OUT - CALEServerOpenGattServer");
902     return jni_obj_bluetoothGattServer;
903 }
904
905 jobject CALEServerCreateGattService(JNIEnv *env)
906 {
907     OIC_LOG(DEBUG, TAG, "IN - CALEServerCreateGattService");
908     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
909
910     if (!CALEIsEnableBTAdapter(env))
911     {
912         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
913         return NULL;
914     }
915
916     jclass jni_cid_bluetoothGattService = (*env)->FindClass(env, "android/bluetooth/"
917                                                             "BluetoothGattService");
918     if (!jni_cid_bluetoothGattService)
919     {
920         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattService is null");
921         return NULL;
922     }
923
924     jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/"
925                                                                    "BluetoothGattCharacteristic");
926     if (!jni_cid_bluetoothGattCharacteristic)
927     {
928         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattCharacteristic is null");
929         return NULL;
930     }
931
932     jfieldID jni_fid_serviceType = (*env)->GetStaticFieldID(env, jni_cid_bluetoothGattService,
933                                                             "SERVICE_TYPE_PRIMARY", "I");
934     if (!jni_fid_serviceType)
935     {
936         OIC_LOG(ERROR, TAG, "jni_fid_serviceType is null");
937         return NULL;
938     }
939
940     jfieldID jni_fid_readProperties = (*env)->GetStaticFieldID(env,
941                                                                jni_cid_bluetoothGattCharacteristic,
942                                                                "PROPERTY_NOTIFY", "I");
943     if (!jni_fid_readProperties)
944     {
945         OIC_LOG(ERROR, TAG, "jni_fid_readProperties is null");
946         return NULL;
947     }
948
949     jfieldID jni_fid_writeProperties = (*env)->GetStaticFieldID(env,
950                                                                 jni_cid_bluetoothGattCharacteristic,
951                                                                 "PROPERTY_WRITE_NO_RESPONSE", "I");
952     if (!jni_fid_writeProperties)
953     {
954         OIC_LOG(ERROR, TAG, "jni_fid_writeProperties is null");
955         return NULL;
956     }
957
958     jfieldID jni_fid_readPermissions = (*env)->GetStaticFieldID(env,
959                                                                 jni_cid_bluetoothGattCharacteristic,
960                                                                 "PERMISSION_READ", "I");
961     if (!jni_fid_readPermissions)
962     {
963         OIC_LOG(ERROR, TAG, "jni_fid_readPermissions is null");
964         return NULL;
965     }
966
967     jfieldID jni_fid_writePermissions = (*env)->GetStaticFieldID(
968             env, jni_cid_bluetoothGattCharacteristic, "PERMISSION_WRITE", "I");
969     if (!jni_fid_writePermissions)
970     {
971         OIC_LOG(ERROR, TAG, "jni_fid_writePermissions is null");
972         return NULL;
973     }
974
975     jmethodID jni_mid_bluetoothGattService = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
976                                                                  "<init>", "(Ljava/util/UUID;I)V");
977     if (!jni_mid_bluetoothGattService)
978     {
979         OIC_LOG(ERROR, TAG, "jni_mid_bluetoothGattService is null");
980         return NULL;
981     }
982
983     jmethodID jni_mid_addCharacteristic = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
984                                                               "addCharacteristic",
985                                                               "(Landroid/bluetooth/"
986                                                               "BluetoothGattCharacteristic;)Z");
987     if (!jni_mid_addCharacteristic)
988     {
989         OIC_LOG(ERROR, TAG, "jni_mid_addCharacteristic is null");
990         return NULL;
991     }
992
993     jmethodID jni_mid_bluetoothGattCharacteristic = (*env)->GetMethodID(
994             env, jni_cid_bluetoothGattCharacteristic, "<init>", "(Ljava/util/UUID;II)V");
995     if (!jni_mid_bluetoothGattCharacteristic)
996     {
997         OIC_LOG(ERROR, TAG, "jni_mid_bluetoothGattCharacteristic is null");
998         return NULL;
999     }
1000
1001     jobject jni_obj_serviceUUID = CALEGetUuidFromString(env, OIC_GATT_SERVICE_UUID);
1002     if (!jni_obj_serviceUUID)
1003     {
1004         OIC_LOG(ERROR, TAG, "jni_obj_serviceUUID is null");
1005         return NULL;
1006     }
1007
1008     jint jni_int_serviceType = (*env)->GetStaticIntField(env, jni_cid_bluetoothGattService,
1009                                                          jni_fid_serviceType);
1010     jobject jni_bluetoothGattService = (*env)->NewObject(env, jni_cid_bluetoothGattService,
1011                                                          jni_mid_bluetoothGattService,
1012                                                          jni_obj_serviceUUID, jni_int_serviceType);
1013     if (!jni_bluetoothGattService)
1014     {
1015         OIC_LOG(ERROR, TAG, "jni_bluetoothGattService is null");
1016         return NULL;
1017     }
1018
1019     jobject jni_obj_readUuid = CALEGetUuidFromString(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
1020     if (!jni_obj_readUuid)
1021     {
1022         OIC_LOG(ERROR, TAG, "jni_obj_readUuid is null");
1023         return NULL;
1024     }
1025
1026     jint jni_int_readProperties = (*env)->GetStaticIntField(env,
1027                                                             jni_cid_bluetoothGattCharacteristic,
1028                                                             jni_fid_readProperties);
1029
1030     jint jni_int_readPermissions = (*env)->GetStaticIntField(env,
1031                                                              jni_cid_bluetoothGattCharacteristic,
1032                                                              jni_fid_readPermissions);
1033
1034     jint jni_int_writePermissions = (*env)->GetStaticIntField(env,
1035                                                               jni_cid_bluetoothGattCharacteristic,
1036                                                               jni_fid_writePermissions);
1037
1038     jobject jni_readCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic,
1039                                                        jni_mid_bluetoothGattCharacteristic,
1040                                                        jni_obj_readUuid, jni_int_readProperties,
1041                                                        jni_int_readPermissions|
1042                                                        jni_int_writePermissions);
1043     if (!jni_readCharacteristic)
1044     {
1045         OIC_LOG(ERROR, TAG, "jni_readCharacteristic is null");
1046         return NULL;
1047     }
1048
1049     jboolean jni_boolean_addReadCharacteristic = (*env)->CallBooleanMethod(
1050             env, jni_bluetoothGattService, jni_mid_addCharacteristic, jni_readCharacteristic);
1051     if (!jni_boolean_addReadCharacteristic)
1052     {
1053         OIC_LOG(ERROR, TAG, "jni_boolean_addReadCharacteristic is null");
1054         return NULL;
1055     }
1056
1057     jobject jni_obj_writeUuid = CALEGetUuidFromString(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
1058     if (!jni_obj_writeUuid)
1059     {
1060         OIC_LOG(ERROR, TAG, "jni_obj_bluetoothGattServer is null");
1061         return NULL;
1062     }
1063
1064     jint jni_int_writeProperties = (*env)->GetStaticIntField(env,
1065                                                              jni_cid_bluetoothGattCharacteristic,
1066                                                              jni_fid_writeProperties);
1067
1068     jobject jni_writeCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic,
1069                                                         jni_mid_bluetoothGattCharacteristic,
1070                                                         jni_obj_writeUuid, jni_int_writeProperties,
1071                                                         jni_int_writePermissions);
1072     if (!jni_writeCharacteristic)
1073     {
1074         OIC_LOG(ERROR, TAG, "jni_writeCharacteristic is null");
1075         return NULL;
1076     }
1077
1078     jboolean jni_boolean_addWriteCharacteristic = (*env)->CallBooleanMethod(
1079             env, jni_bluetoothGattService, jni_mid_addCharacteristic, jni_writeCharacteristic);
1080     if (JNI_FALSE == jni_boolean_addWriteCharacteristic)
1081     {
1082         OIC_LOG(ERROR, TAG, "Fail to add jni_boolean_addReadCharacteristic");
1083         return NULL;
1084     }
1085
1086     OIC_LOG(DEBUG, TAG, "OUT - CALEServerCreateGattService");
1087     return jni_bluetoothGattService;
1088 }
1089
1090 CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic)
1091 {
1092     OIC_LOG(DEBUG, TAG, "CALEServerAddDescriptor");
1093     VERIFY_NON_NULL(env, TAG, "env is null");
1094     VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
1095
1096     jclass jni_cid_bluetoothGattDescriptor = (*env)->FindClass(env, "android/bluetooth/"
1097                                                                "BluetoothGattDescriptor");
1098     if (!jni_cid_bluetoothGattDescriptor)
1099     {
1100         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattDescriptor is null");
1101         return CA_STATUS_FAILED;
1102     }
1103
1104     jmethodID jni_mid_bluetoothGattDescriptor = (*env)->GetMethodID(env,
1105                                                                     jni_cid_bluetoothGattDescriptor,
1106                                                                     "<init>",
1107                                                                     "(Ljava/util/UUID;I)V");
1108     if (!jni_mid_bluetoothGattDescriptor)
1109     {
1110         OIC_LOG(ERROR, TAG, "jni_mid_bluetoothGattDescriptor is null");
1111         return CA_STATUS_FAILED;
1112     }
1113
1114     jfieldID jni_fid_readPermissions = (*env)->GetStaticFieldID(env,
1115                                                                 jni_cid_bluetoothGattDescriptor,
1116                                                                 "PERMISSION_READ", "I");
1117     if (!jni_fid_readPermissions)
1118     {
1119         OIC_LOG(ERROR, TAG, "jni_fid_readPermissions is null");
1120         return CA_STATUS_FAILED;
1121     }
1122
1123     jobject jni_obj_readUuid = CALEGetUuidFromString(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID);
1124     if (!jni_obj_readUuid)
1125     {
1126         OIC_LOG(ERROR, TAG, "jni_obj_readUuid is null");
1127         return CA_STATUS_FAILED;
1128     }
1129
1130     jint jni_int_readPermissions = (*env)->GetStaticIntField(env, jni_cid_bluetoothGattDescriptor,
1131                                                              jni_fid_readPermissions);
1132
1133     OIC_LOG(DEBUG, TAG, "initialize new Descriptor");
1134
1135     jobject jni_readDescriptor = (*env)->NewObject(env, jni_cid_bluetoothGattDescriptor,
1136                                                    jni_mid_bluetoothGattDescriptor,
1137                                                    jni_obj_readUuid, jni_int_readPermissions);
1138     if (!jni_readDescriptor)
1139     {
1140         OIC_LOG(ERROR, TAG, "jni_readDescriptor is null");
1141         return CA_STATUS_FAILED;
1142     }
1143
1144     jclass jni_cid_GattCharacteristic = (*env)->FindClass(env, "android/bluetooth/"
1145                                                           "BluetoothGattCharacteristic");
1146     if (!jni_cid_GattCharacteristic)
1147     {
1148         OIC_LOG(ERROR, TAG, "jni_cid_GattCharacteristic is null");
1149         return CA_STATUS_FAILED;
1150     }
1151
1152     jmethodID jni_mid_addDescriptor = (*env)->GetMethodID(env, jni_cid_GattCharacteristic,
1153                                                           "addDescriptor",
1154                                                           "(Landroid/bluetooth/"
1155                                                           "BluetoothGattDescriptor;)Z");
1156     if (!jni_mid_addDescriptor)
1157     {
1158         OIC_LOG(ERROR, TAG, "jni_mid_addDescriptor is null");
1159         return CA_STATUS_FAILED;
1160     }
1161
1162     jboolean jni_boolean_addDescriptor = (*env)->CallBooleanMethod(env, characteristic,
1163                                                                    jni_mid_addDescriptor,
1164                                                                    jni_readDescriptor);
1165
1166     if (JNI_FALSE == jni_boolean_addDescriptor)
1167     {
1168         OIC_LOG(ERROR, TAG, "addDescriptor has failed");
1169         return CA_STATUS_FAILED;
1170     }
1171     else
1172     {
1173         OIC_LOG(DEBUG, TAG, "addDescriptor success");
1174     }
1175     return CA_STATUS_OK;
1176 }
1177
1178 CAResult_t CALEServerAddGattService(JNIEnv *env, jobject bluetoothGattServer,
1179                                           jobject bluetoothGattService)
1180 {
1181     OIC_LOG(DEBUG, TAG, "IN - CALEServerAddGattService");
1182     VERIFY_NON_NULL(env, TAG, "env is null");
1183     VERIFY_NON_NULL(bluetoothGattServer, TAG, "bluetoothGattServer is null");
1184     VERIFY_NON_NULL(bluetoothGattService, TAG, "bluetoothGattService is null");
1185
1186     if (!CALEIsEnableBTAdapter(env))
1187     {
1188         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1189         return CA_ADAPTER_NOT_ENABLED;
1190     }
1191
1192     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
1193                                                            "android/bluetooth/BluetoothGattServer");
1194     if (!jni_cid_bluetoothGattServer)
1195     {
1196         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
1197         return CA_STATUS_FAILED;
1198     }
1199
1200     jmethodID jni_mid_addService = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
1201                                                        "addService",
1202                                                        "(Landroid/bluetooth/BluetoothGattService;)"
1203                                                        "Z");
1204     if (!jni_mid_addService)
1205     {
1206         OIC_LOG(ERROR, TAG, "jni_mid_addService is null");
1207         return CA_STATUS_FAILED;
1208     }
1209
1210     jboolean jni_boolean_addService = (*env)->CallBooleanMethod(env, bluetoothGattServer,
1211                                                                 jni_mid_addService,
1212                                                                 bluetoothGattService);
1213
1214     if (JNI_FALSE == jni_boolean_addService)
1215     {
1216         OIC_LOG(ERROR, TAG, "Fail to add GATT service");
1217         return CA_STATUS_FAILED;
1218     }
1219
1220     OIC_LOG(DEBUG, TAG, "OUT - CALEServerAddGattService");
1221     return CA_STATUS_OK;
1222 }
1223
1224 CAResult_t CALEServerConnect(JNIEnv *env, jobject bluetoothDevice)
1225 {
1226     OIC_LOG(DEBUG, TAG, "IN - CALEServerConnect");
1227     VERIFY_NON_NULL(env, TAG, "env is null");
1228     VERIFY_NON_NULL(bluetoothDevice, TAG, "bluetoothDevice is null");
1229
1230     if (!CALEIsEnableBTAdapter(env))
1231     {
1232         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1233         return CA_ADAPTER_NOT_ENABLED;
1234     }
1235
1236     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
1237                                                            "android/bluetooth/BluetoothGattServer");
1238     if (!jni_cid_bluetoothGattServer)
1239     {
1240         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
1241         return CA_STATUS_FAILED;
1242     }
1243
1244     jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, "connect",
1245                                                     "(Landroid/bluetooth/BluetoothDevice;Z)Z");
1246     if (!jni_mid_connect)
1247     {
1248         OIC_LOG(ERROR, TAG, "jni_mid_connect is null");
1249         return CA_STATUS_FAILED;
1250     }
1251
1252     jboolean jni_boolean_connect = (*env)->CallBooleanMethod(env, g_bluetoothGattServer,
1253                                                              jni_mid_connect, bluetoothDevice,
1254                                                              JNI_FALSE);
1255     if (JNI_FALSE == jni_boolean_connect)
1256     {
1257         OIC_LOG(ERROR, TAG, "Fail to connect");
1258         return CA_STATUS_FAILED;
1259     }
1260
1261     OIC_LOG(DEBUG, TAG, "OUT - CALEServerConnect");
1262     return CA_STATUS_OK;
1263 }
1264
1265 CAResult_t CALEServerDisconnectAllDevices(JNIEnv *env)
1266 {
1267     OIC_LOG(DEBUG, TAG, "IN - CALEServerDisconnectAllDevices");
1268     VERIFY_NON_NULL(env, TAG, "env is null");
1269
1270     ca_mutex_lock(g_connectedDeviceListMutex);
1271     if (!g_connectedDeviceList)
1272     {
1273         OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
1274         ca_mutex_unlock(g_connectedDeviceListMutex);
1275         return CA_STATUS_FAILED;
1276     }
1277
1278     uint32_t length = u_arraylist_length(g_connectedDeviceList);
1279     for (uint32_t index = 0; index < length; index++)
1280     {
1281         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
1282         if (!jarrayObj)
1283         {
1284             OIC_LOG_V(ERROR, TAG, "object[%d] is null", index);
1285             continue;
1286         }
1287
1288         // disconnect for device obj
1289         CAResult_t res = CALEServerDisconnect(env, jarrayObj);
1290         if (CA_STATUS_OK != res)
1291         {
1292             OIC_LOG_V(ERROR, TAG, "Disconnect for this device[%d] has failed", index);
1293             continue;
1294         }
1295     }
1296
1297     ca_mutex_unlock(g_connectedDeviceListMutex);
1298     OIC_LOG(DEBUG, TAG, "OUT - CALEServerDisconnectAllDevices");
1299     return CA_STATUS_OK;
1300 }
1301
1302 CAResult_t CALEServerDisconnect(JNIEnv *env, jobject bluetoothDevice)
1303 {
1304     OIC_LOG(DEBUG, TAG, "IN - CALEServerDisconnect");
1305     VERIFY_NON_NULL(env, TAG, "env is null");
1306     VERIFY_NON_NULL(bluetoothDevice, TAG, "bluetoothDevice is null");
1307
1308     if (!CALEIsEnableBTAdapter(env))
1309     {
1310         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1311         return CA_ADAPTER_NOT_ENABLED;
1312     }
1313
1314     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
1315                                                            "android/bluetooth/BluetoothGattServer");
1316     if (!jni_cid_bluetoothGattServer)
1317     {
1318         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattServer is null");
1319         return CA_STATUS_FAILED;
1320     }
1321
1322     jmethodID jni_mid_cancelConnection = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
1323                                                              "cancelConnection",
1324                                                              "(Landroid/bluetooth/BluetoothDevice;)"
1325                                                              "V");
1326     if (!jni_mid_cancelConnection)
1327     {
1328         OIC_LOG(ERROR, TAG, "jni_mid_cancelConnection is null");
1329         return CA_STATUS_FAILED;
1330     }
1331
1332     (*env)->CallVoidMethod(env, g_bluetoothGattServer, jni_mid_cancelConnection, bluetoothDevice);
1333
1334     if ((*env)->ExceptionCheck(env))
1335     {
1336         OIC_LOG(ERROR, TAG, "cancelConnection has failed");
1337         (*env)->ExceptionDescribe(env);
1338         (*env)->ExceptionClear(env);
1339         return CA_STATUS_FAILED;
1340     }
1341
1342     OIC_LOG(DEBUG, TAG, "OUT - CALEServerDisconnect");
1343     return CA_STATUS_OK;
1344 }
1345
1346 CAResult_t CALEServerGattClose(JNIEnv *env, jobject bluetoothGattServer)
1347 {
1348     // GATT CLOSE
1349     OIC_LOG(DEBUG, TAG, "GattServer Close");
1350     VERIFY_NON_NULL(bluetoothGattServer, TAG, "bluetoothGattServer is null");
1351     VERIFY_NON_NULL(env, TAG, "env is null");
1352
1353     // get BluetoothGatt class
1354     OIC_LOG(DEBUG, TAG, "get BluetoothGatt class");
1355     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, "android/bluetooth/BluetoothGattServer");
1356     if (!jni_cid_BluetoothGatt)
1357     {
1358         OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
1359         return CA_STATUS_FAILED;
1360     }
1361
1362     jmethodID jni_mid_closeGatt = (*env)->GetMethodID(env, jni_cid_BluetoothGatt, "close", "()V");
1363     if (!jni_mid_closeGatt)
1364     {
1365         OIC_LOG(ERROR, TAG, "jni_mid_closeGatt is null");
1366         return CA_STATUS_OK;
1367     }
1368
1369     // call disconnect gatt method
1370     OIC_LOG(DEBUG, TAG, "request to close GATT");
1371     (*env)->CallVoidMethod(env, bluetoothGattServer, jni_mid_closeGatt);
1372
1373     if ((*env)->ExceptionCheck(env))
1374     {
1375         OIC_LOG(ERROR, TAG, "closeGATT has failed");
1376         (*env)->ExceptionDescribe(env);
1377         (*env)->ExceptionClear(env);
1378         return CA_STATUS_FAILED;
1379     }
1380
1381     return CA_STATUS_OK;
1382 }
1383
1384 CAResult_t CALEServerSend(JNIEnv *env, jobject bluetoothDevice, jbyteArray responseData)
1385 {
1386     OIC_LOG(DEBUG, TAG, "IN - CALEServerSend");
1387     VERIFY_NON_NULL(env, TAG, "env is null");
1388     VERIFY_NON_NULL(bluetoothDevice, TAG, "bluetoothDevice is null");
1389     VERIFY_NON_NULL(responseData, TAG, "responseData is null");
1390
1391     if (!CALEIsEnableBTAdapter(env))
1392     {
1393         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1394         return CA_ADAPTER_NOT_ENABLED;
1395     }
1396
1397     jobject responseChar = CALEServerSetResponseData(env, responseData);
1398     if (!responseChar)
1399     {
1400         OIC_LOG(ERROR, TAG, "responseChar is null");
1401         return CA_STATUS_FAILED;
1402     }
1403
1404     CAResult_t result = CALEServerSendResponseData(env, bluetoothDevice, responseChar);
1405     if (CA_STATUS_OK != result)
1406     {
1407         OIC_LOG(ERROR, TAG, "Fail to send response data");
1408         return result;
1409     }
1410
1411     OIC_LOG(DEBUG, TAG, "OUT - CALEServerSend");
1412     return result;
1413 }
1414
1415 CAResult_t CALEServerInitialize()
1416 {
1417     OIC_LOG(DEBUG, TAG, "IN - CALEServerInitialize");
1418
1419     CALeServerJniInit();
1420
1421     if (!g_jvm)
1422     {
1423         OIC_LOG(ERROR, TAG, "g_jvm is null");
1424         return CA_STATUS_FAILED;
1425     }
1426
1427     bool isAttached = false;
1428     JNIEnv* env;
1429     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1430     if (JNI_OK != res)
1431     {
1432         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1433         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1434
1435         if (JNI_OK != res)
1436         {
1437             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1438             return CA_STATUS_FAILED;
1439         }
1440         isAttached = true;
1441     }
1442
1443     CAResult_t ret = CALECheckPlatformVersion(env, 21);
1444     if (CA_STATUS_OK != ret)
1445     {
1446         OIC_LOG(ERROR, TAG, "it is not supported");
1447
1448         if (isAttached)
1449         {
1450             (*g_jvm)->DetachCurrentThread(g_jvm);
1451         }
1452         return ret;
1453     }
1454
1455     g_threadSendNotifyCond = ca_cond_new();
1456
1457     ret = CALEServerInitMutexVaraibles();
1458     if (CA_STATUS_OK != ret)
1459     {
1460         OIC_LOG(ERROR, TAG, "CALEServerInitMutexVaraibles has failed");
1461
1462         if (isAttached)
1463         {
1464             (*g_jvm)->DetachCurrentThread(g_jvm);
1465         }
1466         return CA_STATUS_FAILED;
1467     }
1468
1469     CALEServerJNISetContext();
1470     CALEServerCreateCachedDeviceList();
1471
1472     ret = CALEServerCreateJniInterfaceObject();
1473     if (CA_STATUS_OK != ret)
1474     {
1475         OIC_LOG(ERROR, TAG, "CALEServerCreateJniInterfaceObject has failed");
1476
1477         if (isAttached)
1478         {
1479             (*g_jvm)->DetachCurrentThread(g_jvm);
1480         }
1481         return CA_STATUS_FAILED;
1482     }
1483
1484     if (isAttached)
1485     {
1486         (*g_jvm)->DetachCurrentThread(g_jvm);
1487     }
1488
1489     g_isInitializedServer = true;
1490     OIC_LOG(DEBUG, TAG, "OUT - CALEServerInitialize");
1491     return CA_STATUS_OK;
1492 }
1493
1494 void CALEServerTerminate()
1495 {
1496     OIC_LOG(DEBUG, TAG, "IN - CALEServerTerminate");
1497
1498     if (!g_jvm)
1499     {
1500         OIC_LOG(ERROR, TAG, "g_jvm is null");
1501         return;
1502     }
1503
1504     bool isAttached = false;
1505     JNIEnv* env;
1506     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1507     if (JNI_OK != res)
1508     {
1509         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1510         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1511
1512         if (JNI_OK != res)
1513         {
1514             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1515             return;
1516         }
1517         isAttached = true;
1518     }
1519
1520     if (g_sendBuffer)
1521     {
1522         (*env)->DeleteGlobalRef(env, g_sendBuffer);
1523         g_sendBuffer = NULL;
1524     }
1525
1526     ca_cond_free(g_threadSendNotifyCond);
1527     g_threadSendNotifyCond = NULL;
1528
1529     CALEServerTerminateMutexVaraibles();
1530     CALEServerTerminateConditionVaraibles();
1531
1532     g_isInitializedServer = false;
1533
1534     if (isAttached)
1535     {
1536         (*g_jvm)->DetachCurrentThread(g_jvm);
1537     }
1538
1539     OIC_LOG(DEBUG, TAG, "OUT - CALEServerTerminate");
1540 }
1541
1542 CAResult_t CALEServerSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
1543 {
1544     OIC_LOG_V(DEBUG, TAG, "CALEServerSendUnicastMessage(%s, %p)", address, data);
1545     VERIFY_NON_NULL(address, TAG, "address is null");
1546     VERIFY_NON_NULL(data, TAG, "data is null");
1547
1548     if (!g_jvm)
1549     {
1550         OIC_LOG(ERROR, TAG, "g_jvm is null");
1551         return CA_STATUS_FAILED;
1552     }
1553
1554     bool isAttached = false;
1555     JNIEnv* env;
1556     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1557     if (JNI_OK != res)
1558     {
1559         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1560         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1561
1562         if (JNI_OK != res)
1563         {
1564             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1565             return CA_STATUS_FAILED;
1566         }
1567         isAttached = true;
1568     }
1569
1570     CAResult_t ret = CALEServerSendUnicastMessageImpl(env, address, data, dataLen);
1571     if (CA_STATUS_OK != ret)
1572     {
1573         OIC_LOG(ERROR, TAG, "CALEServerSendUnicastMessageImpl has failed");
1574     }
1575
1576     if (isAttached)
1577     {
1578         (*g_jvm)->DetachCurrentThread(g_jvm);
1579     }
1580
1581     return ret;
1582 }
1583
1584 CAResult_t CALEServerSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
1585 {
1586     OIC_LOG_V(DEBUG, TAG, "CALEServerSendMulticastMessage(%p)", data);
1587     VERIFY_NON_NULL(data, TAG, "data is null");
1588
1589     if (!g_jvm)
1590     {
1591         OIC_LOG(ERROR, TAG, "g_jvm is null");
1592         return CA_STATUS_FAILED;
1593     }
1594
1595     bool isAttached = false;
1596     JNIEnv* env;
1597     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1598     if (JNI_OK != res)
1599     {
1600         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1601         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1602
1603         if (JNI_OK != res)
1604         {
1605             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1606             return CA_STATUS_FAILED;
1607         }
1608         isAttached = true;
1609     }
1610
1611     CAResult_t ret = CALEServerSendMulticastMessageImpl(env, data, dataLen);
1612     if (CA_STATUS_OK != ret)
1613     {
1614         OIC_LOG(ERROR, TAG, "CALEServerSendMulticastMessageImpl has failed");
1615     }
1616
1617     if (isAttached)
1618     {
1619         (*g_jvm)->DetachCurrentThread(g_jvm);
1620     }
1621
1622     return ret;
1623 }
1624
1625 CAResult_t CALEServerStartMulticastServer()
1626 {
1627     OIC_LOG(DEBUG, TAG, "IN - CALEServerStartMulticastServer");
1628
1629     if (!g_isInitializedServer)
1630     {
1631         OIC_LOG(INFO, TAG, "server is not initialized");
1632         return CA_STATUS_FAILED;
1633     }
1634
1635     if (g_isStartServer)
1636     {
1637         OIC_LOG(INFO, TAG, "server is already started..it will be skipped");
1638         return CA_STATUS_FAILED;
1639     }
1640
1641     if (!g_jvm)
1642     {
1643         OIC_LOG(ERROR, TAG, "g_jvm is null");
1644         return CA_STATUS_FAILED;
1645     }
1646
1647     bool isAttached = false;
1648     JNIEnv* env;
1649     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1650     if (JNI_OK != res)
1651     {
1652         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1653         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1654
1655         if (JNI_OK != res)
1656         {
1657             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1658             return CA_STATUS_FAILED;
1659         }
1660         isAttached = true;
1661     }
1662
1663     g_isStartServer = true;
1664
1665     // start gatt server
1666     CAResult_t ret = CALEServerStartGattServer(env, g_bluetoothGattServerCallback);
1667     if (CA_STATUS_OK != ret)
1668     {
1669         OIC_LOG(ERROR, TAG, "Fail to start gatt server");
1670         return ret;
1671     }
1672
1673     // start advertise
1674     ret = CALEServerStartAdvertise(env, g_leAdvertiseCallback);
1675     if (CA_STATUS_OK != ret)
1676     {
1677         OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed");
1678     }
1679
1680     if (isAttached)
1681     {
1682         (*g_jvm)->DetachCurrentThread(g_jvm);
1683     }
1684
1685     OIC_LOG(DEBUG, TAG, "OUT - CALEServerStartMulticastServer");
1686     return ret;
1687 }
1688
1689 CAResult_t CALEServerStopMulticastServer()
1690 {
1691     OIC_LOG(DEBUG, TAG, "IN - CALEServerStopMulticastServer");
1692
1693     if (false == g_isStartServer)
1694     {
1695         OIC_LOG(INFO, TAG, "server is already stopped..it will be skipped");
1696         return CA_STATUS_FAILED;
1697     }
1698
1699     if (!g_jvm)
1700     {
1701         OIC_LOG(ERROR, TAG, "g_jvm is null");
1702         return CA_STATUS_FAILED;
1703     }
1704
1705     bool isAttached = false;
1706     JNIEnv* env;
1707     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1708     if (JNI_OK != res)
1709     {
1710         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1711         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1712
1713         if (JNI_OK != res)
1714         {
1715             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1716             return CA_STATUS_FAILED;
1717         }
1718         isAttached = true;
1719     }
1720
1721     CAResult_t ret = CALEServerStopAdvertise(env, g_leAdvertiseCallback);
1722     if (CA_STATUS_OK != ret)
1723     {
1724         OIC_LOG(ERROR, TAG, "CALEServerStopAdvertise has failed");
1725     }
1726
1727     g_isStartServer = false;
1728
1729     if (isAttached)
1730     {
1731         (*g_jvm)->DetachCurrentThread(g_jvm);
1732     }
1733
1734     OIC_LOG(DEBUG, TAG, "OUT - CALEServerStopMulticastServer");
1735     return ret;
1736 }
1737
1738 void CALEServerSetCallback(CAPacketReceiveCallback callback)
1739 {
1740     OIC_LOG(DEBUG, TAG, "CALEServerSetCallback");
1741     g_packetReceiveCallback = callback;
1742 }
1743
1744 CAResult_t CALEServerSendUnicastMessageImpl(JNIEnv *env, const char* address, const uint8_t* data,
1745                                             uint32_t dataLen)
1746 {
1747     OIC_LOG_V(DEBUG, TAG, "CALEServerSendUnicastMessageImpl, address: %s, data: %p",
1748             address, data);
1749     VERIFY_NON_NULL(env, TAG, "env is null");
1750     VERIFY_NON_NULL(address, TAG, "address is null");
1751     VERIFY_NON_NULL(data, TAG, "data is null");
1752
1753     if (!g_connectedDeviceList)
1754     {
1755         OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
1756         return CA_STATUS_FAILED;
1757     }
1758
1759     ca_mutex_lock(g_threadSendMutex);
1760
1761     jobject jni_obj_bluetoothDevice = NULL;
1762     uint32_t length = u_arraylist_length(g_connectedDeviceList);
1763     for (uint32_t index = 0; index < length; index++)
1764     {
1765         OIC_LOG(DEBUG, TAG, "check device address");
1766         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
1767         if (!jarrayObj)
1768         {
1769             OIC_LOG(ERROR, TAG, "jarrayObj is null");
1770             goto error_exit;
1771         }
1772
1773         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
1774         if (!jni_setAddress)
1775         {
1776             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
1777             goto error_exit;
1778         }
1779         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
1780         if (!setAddress)
1781         {
1782             OIC_LOG(ERROR, TAG, "setAddress is null");
1783             goto error_exit;
1784         }
1785
1786         OIC_LOG_V(DEBUG, TAG, "setAddress : %s", setAddress);
1787         OIC_LOG_V(DEBUG, TAG, "address : %s", address);
1788
1789         if (!strcmp(setAddress, address))
1790         {
1791             OIC_LOG(DEBUG, TAG, "found the device");
1792             jni_obj_bluetoothDevice = jarrayObj;
1793             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1794             break;
1795         }
1796         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1797     }
1798
1799     if (jni_obj_bluetoothDevice)
1800     {
1801         jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
1802         (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
1803         g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
1804
1805         CAResult_t res = CALEServerSend(env, jni_obj_bluetoothDevice, g_sendBuffer);
1806         if (CA_STATUS_OK != res)
1807         {
1808             OIC_LOG(ERROR, TAG, "send has failed");
1809             goto error_exit;
1810         }
1811     }
1812     else
1813     {
1814         OIC_LOG(ERROR, TAG, "There are no device to send in the list");
1815         goto error_exit;
1816     }
1817
1818     if (g_sendBuffer)
1819     {
1820         (*env)->DeleteGlobalRef(env, g_sendBuffer);
1821         g_sendBuffer = NULL;
1822     }
1823
1824     ca_mutex_unlock(g_threadSendMutex);
1825     OIC_LOG(INFO, TAG, "unicast - send request is successful");
1826     return CA_STATUS_OK;
1827
1828 error_exit:
1829     if (g_sendBuffer)
1830     {
1831         (*env)->DeleteGlobalRef(env, g_sendBuffer);
1832         g_sendBuffer = NULL;
1833     }
1834
1835     ca_mutex_unlock(g_threadSendMutex);
1836     return CA_SEND_FAILED;
1837 }
1838
1839 CAResult_t CALEServerSendMulticastMessageImpl(JNIEnv *env, const uint8_t *data, uint32_t dataLen)
1840 {
1841     OIC_LOG_V(DEBUG, TAG, "CALEServerSendMulticastMessageImpl, send to, data: %s", data);
1842     VERIFY_NON_NULL(env, TAG, "env is null");
1843     VERIFY_NON_NULL(data, TAG, "data is null");
1844
1845     if (!g_connectedDeviceList)
1846     {
1847         OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
1848         return CA_STATUS_FAILED;
1849     }
1850
1851     ca_mutex_lock(g_threadSendMutex);
1852
1853     OIC_LOG(DEBUG, TAG, "set data into g_sendBuffer for notify");
1854     if (g_sendBuffer)
1855     {
1856         (*env)->DeleteGlobalRef(env, g_sendBuffer);
1857         g_sendBuffer = NULL;
1858     }
1859     jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
1860     (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
1861     g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
1862
1863     uint32_t length = u_arraylist_length(g_connectedDeviceList);
1864     for (uint32_t index = 0; index < length; index++)
1865     {
1866         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
1867         if (!jarrayObj)
1868         {
1869             OIC_LOG(ERROR, TAG, "jarrayObj is null");
1870             continue;
1871         }
1872
1873         // send data for all device
1874         jbyteArray jni_bytearr_data = (*env)->NewByteArray(env, dataLen);
1875         (*env)->SetByteArrayRegion(env, jni_bytearr_data, 0, dataLen, (jbyte*) data);
1876
1877         jstring jni_address = CALEGetAddressFromBTDevice(env, jarrayObj);
1878         if (!jni_address)
1879         {
1880             OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
1881             continue;
1882         }
1883
1884         const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1885         if (!address)
1886         {
1887             OIC_LOG(ERROR, TAG, "address is not available");
1888             continue;
1889         }
1890
1891         CAResult_t res = CALEServerSend(env, jarrayObj, jni_bytearr_data);
1892         if (CA_STATUS_OK != res)
1893         {
1894             OIC_LOG_V(ERROR, TAG, "send has failed for the device[%s]", address);
1895             (*env)->ReleaseStringUTFChars(env, jni_address, address);
1896             continue;
1897         }
1898
1899         OIC_LOG_V(INFO, TAG, "unicast - send request is successful for a device[%s]", address);
1900         (*env)->ReleaseStringUTFChars(env, jni_address, address);
1901     }
1902
1903     if (g_sendBuffer)
1904     {
1905         (*env)->DeleteGlobalRef(env, g_sendBuffer);
1906         g_sendBuffer = NULL;
1907     }
1908
1909     ca_mutex_unlock(g_threadSendMutex);
1910     return CA_STATUS_OK;
1911 }
1912
1913 void CALEServerCreateCachedDeviceList()
1914 {
1915     ca_mutex_lock(g_connectedDeviceListMutex);
1916     // create new object array
1917     if (!g_connectedDeviceList)
1918     {
1919         OIC_LOG(DEBUG, TAG, "Create device list");
1920         g_connectedDeviceList = u_arraylist_create();
1921     }
1922     ca_mutex_unlock(g_connectedDeviceListMutex);
1923 }
1924
1925 bool CALEServerIsDeviceInList(JNIEnv *env, const char* remoteAddress)
1926 {
1927     VERIFY_NON_NULL_RET(env, TAG, "env is null", false);
1928     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
1929
1930     if (!g_connectedDeviceList)
1931     {
1932         OIC_LOG(ERROR, TAG, "list is null");
1933         return false;
1934     }
1935
1936     uint32_t length = u_arraylist_length(g_connectedDeviceList);
1937     for (uint32_t index = 0; index < length; index++)
1938     {
1939         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
1940
1941         if (!jarrayObj)
1942         {
1943             OIC_LOG(ERROR, TAG, "jarrayObj is null");
1944             return false;
1945         }
1946
1947         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
1948         if (!jni_setAddress)
1949         {
1950             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
1951             return false;
1952         }
1953
1954         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
1955         if (!setAddress)
1956         {
1957             OIC_LOG(ERROR, TAG, "setAddress is null");
1958             return false;
1959         }
1960
1961         if (!strcmp(remoteAddress, setAddress))
1962         {
1963             OIC_LOG(ERROR, TAG, "the device is already set");
1964             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1965             return true;
1966         }
1967         else
1968         {
1969             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1970             continue;
1971         }
1972     }
1973
1974     OIC_LOG(DEBUG, TAG, "there are no device in the list");
1975     return false;
1976 }
1977
1978 CAResult_t CALEServerAddDeviceToList(JNIEnv *env, jobject device)
1979 {
1980     OIC_LOG(DEBUG, TAG, "IN - CALEServerAddDeviceToList");
1981     VERIFY_NON_NULL(device, TAG, "device is null");
1982     VERIFY_NON_NULL(env, TAG, "env is null");
1983
1984     ca_mutex_lock(g_connectedDeviceListMutex);
1985
1986     if (!g_connectedDeviceList)
1987     {
1988         OIC_LOG(ERROR, TAG, "list is null");
1989         ca_mutex_unlock(g_connectedDeviceListMutex);
1990         return CA_STATUS_FAILED;
1991     }
1992
1993     jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
1994     if (!jni_remoteAddress)
1995     {
1996         OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
1997         ca_mutex_unlock(g_connectedDeviceListMutex);
1998         return CA_STATUS_FAILED;
1999     }
2000
2001     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2002     if (!remoteAddress)
2003     {
2004         OIC_LOG(ERROR, TAG, "remoteAddress is null");
2005         ca_mutex_unlock(g_connectedDeviceListMutex);
2006         return CA_STATUS_FAILED;
2007     }
2008
2009     if (false == CALEServerIsDeviceInList(env, remoteAddress))
2010     {
2011         jobject jni_obj_device = (*env)->NewGlobalRef(env, device);
2012         u_arraylist_add(g_connectedDeviceList, jni_obj_device);
2013         OIC_LOG_V(DEBUG, TAG, "Set the object to ArrayList as Element : %s", remoteAddress);
2014     }
2015
2016     (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2017     ca_mutex_unlock(g_connectedDeviceListMutex);
2018     OIC_LOG(DEBUG, TAG, "OUT - CALEServerAddDeviceToList");
2019     return CA_STATUS_OK;
2020 }
2021
2022 CAResult_t CALEServerRemoveAllDevices(JNIEnv *env)
2023 {
2024     OIC_LOG(DEBUG, TAG, "IN - CALEServerRemoveAllDevices");
2025     VERIFY_NON_NULL(env, TAG, "env is null");
2026
2027     ca_mutex_lock(g_connectedDeviceListMutex);
2028     if (!g_connectedDeviceList)
2029     {
2030         OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
2031         ca_mutex_unlock(g_connectedDeviceListMutex);
2032         return CA_STATUS_FAILED;
2033     }
2034
2035     uint32_t length = u_arraylist_length(g_connectedDeviceList);
2036     for (uint32_t index = 0; index < length; index++)
2037     {
2038         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
2039         if (jarrayObj)
2040         {
2041             (*env)->DeleteGlobalRef(env, jarrayObj);
2042         }
2043     }
2044
2045     OICFree(g_connectedDeviceList);
2046     g_connectedDeviceList = NULL;
2047     ca_mutex_unlock(g_connectedDeviceListMutex);
2048
2049     OIC_LOG(DEBUG, TAG, "OUT - CALEServerRemoveAllDevices");
2050     return CA_STATUS_OK;
2051 }
2052
2053 CAResult_t CALEServerRemoveDevice(JNIEnv *env, jstring address)
2054 {
2055     OIC_LOG(DEBUG, TAG, "IN CALEServerRemoveDevice");
2056     VERIFY_NON_NULL(env, TAG, "env is null");
2057     VERIFY_NON_NULL(address, TAG, "address is null");
2058
2059     ca_mutex_lock(g_connectedDeviceListMutex);
2060     if (!g_connectedDeviceList)
2061     {
2062         OIC_LOG(ERROR, TAG, "no deviceList");
2063         ca_mutex_unlock(g_connectedDeviceListMutex);
2064         return CA_STATUS_FAILED;
2065     }
2066
2067     uint32_t length = u_arraylist_length(g_connectedDeviceList);
2068     for (uint32_t index = 0; index < length; index++)
2069     {
2070         jobject jarrayObj = (jobject) u_arraylist_get(g_connectedDeviceList, index);
2071
2072         if (jarrayObj)
2073         {
2074             jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2075             if (!jni_setAddress)
2076             {
2077                 OIC_LOG(ERROR, TAG, "wrong device address");
2078                 continue;
2079             }
2080             const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2081             if (!setAddress)
2082             {
2083                 OIC_LOG(ERROR, TAG, "setAddress is null");
2084                 continue;
2085             }
2086
2087             const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
2088             if (!remoteAddress)
2089             {
2090                 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2091                 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2092                 continue;
2093             }
2094
2095             if (!strcmp(setAddress, remoteAddress))
2096             {
2097                 OIC_LOG_V(DEBUG, TAG, "device address : %s", remoteAddress);
2098
2099                 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2100                 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2101                 (*env)->DeleteGlobalRef(env, jarrayObj);
2102
2103                 if (NULL == u_arraylist_remove(g_connectedDeviceList, index))
2104                 {
2105                     OIC_LOG(ERROR, TAG, "List removal failed.");
2106                     ca_mutex_unlock(g_connectedDeviceListMutex);
2107                     return CA_STATUS_FAILED;
2108                 }
2109                 ca_mutex_unlock(g_connectedDeviceListMutex);
2110                 return CA_STATUS_OK;
2111             }
2112             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2113             (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2114         }
2115     }
2116
2117     ca_mutex_unlock(g_connectedDeviceListMutex);
2118
2119     OIC_LOG(DEBUG, TAG, "there are no device in the device list");
2120
2121     OIC_LOG(DEBUG, TAG, "IN CALEServerRemoveDevice");
2122     return CA_STATUS_FAILED;
2123 }
2124
2125 JNIEXPORT void JNICALL
2126 Java_org_iotivity_ca_CaLeServerInterface_caLeRegisterGattServerCallback(JNIEnv *env, jobject obj,
2127                                                                         jobject callback)
2128 {
2129     OIC_LOG(DEBUG, TAG, "Register Le Gatt Server Callback");
2130     VERIFY_NON_NULL_VOID(env, TAG, "env");
2131     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2132     VERIFY_NON_NULL_VOID(callback, TAG, "callback");
2133
2134     g_bluetoothGattServerCallback = (*env)->NewGlobalRef(env, callback);
2135 }
2136
2137 JNIEXPORT void JNICALL
2138 Java_org_iotivity_ca_CaLeServerInterface_caLeRegisterBluetoothLeAdvertiseCallback(JNIEnv *env,
2139                                                                                   jobject obj,
2140                                                                                   jobject callback)
2141 {
2142     OIC_LOG(DEBUG, TAG, "Register Le Advertise Callback");
2143     VERIFY_NON_NULL_VOID(env, TAG, "env");
2144     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2145     VERIFY_NON_NULL_VOID(callback, TAG, "callback");
2146
2147     g_leAdvertiseCallback = (*env)->NewGlobalRef(env, callback);
2148 }
2149
2150 JNIEXPORT void JNICALL
2151 Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerConnectionStateChangeCallback(
2152         JNIEnv *env, jobject obj, jobject device, jint status, jint newState)
2153 {
2154     OIC_LOG(DEBUG, TAG, " Gatt Server ConnectionStateChange Callback");
2155     OIC_LOG_V(DEBUG, TAG, "New connection State: %d", newState);
2156
2157     VERIFY_NON_NULL_VOID(env, TAG, "env");
2158     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2159     VERIFY_NON_NULL_VOID(device, TAG, "device");
2160
2161     jclass jni_cid_bluetoothProfile = (*env)->FindClass(env, "android/bluetooth/BluetoothProfile");
2162     if (!jni_cid_bluetoothProfile)
2163     {
2164         OIC_LOG(ERROR, TAG, "jni_cid_bluetoothProfile is null");
2165         return;
2166     }
2167
2168     jfieldID jni_fid_state_connected = (*env)->GetStaticFieldID(env, jni_cid_bluetoothProfile,
2169                                                                 "STATE_CONNECTED", "I");
2170     if(!jni_fid_state_connected)
2171     {
2172         OIC_LOG(ERROR, TAG, "jni_fid_state_connected is null");
2173         return;
2174     }
2175
2176     jfieldID jni_fid_state_disconnected = (*env)->GetStaticFieldID(env, jni_cid_bluetoothProfile,
2177                                                                    "STATE_DISCONNECTED", "I");
2178     if(!jni_fid_state_disconnected)
2179     {
2180         OIC_LOG(ERROR, TAG, "jni_fid_state_disconnected is null");
2181         return;
2182     }
2183
2184     // STATE_CONNECTED
2185     jint jni_int_state_connected = (*env)->GetStaticIntField(env, jni_cid_bluetoothProfile,
2186                                                              jni_fid_state_connected);
2187
2188     // STATE_DISCONNECTED
2189     jint jni_int_state_disconnected = (*env)->GetStaticIntField(env, jni_cid_bluetoothProfile,
2190                                                                 jni_fid_state_disconnected);
2191
2192     if (newState == jni_int_state_connected)
2193     {
2194
2195         OIC_LOG(DEBUG, TAG, "LE CONNECTED");
2196
2197         jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2198         if (!jni_remoteAddress)
2199         {
2200             OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2201             return;
2202         }
2203
2204         const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2205         if (!remoteAddress)
2206         {
2207             OIC_LOG(ERROR, TAG, "remoteAddress is null");
2208             return;
2209         }
2210
2211         if (false == CALEServerIsDeviceInList(env, remoteAddress))
2212         {
2213             OIC_LOG(DEBUG, TAG, "add connected device to cache");
2214             CALEServerAddDeviceToList(env, device);
2215         }
2216         (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2217     }
2218     else if (newState == jni_int_state_disconnected)
2219     {
2220         OIC_LOG(DEBUG, TAG, "LE DISCONNECTED");
2221
2222         jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2223         CAResult_t ret = CALEServerRemoveDevice(env, jni_remoteAddress);
2224         if (CA_STATUS_OK != ret)
2225         {
2226             OIC_LOG(ERROR, TAG, "CALEServerRemoveDevice has failed");
2227         }
2228
2229         // start advertise
2230         ret = CALEServerStartAdvertise(env, g_leAdvertiseCallback);
2231         if (CA_STATUS_OK != ret)
2232         {
2233             OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed");
2234         }
2235     }
2236     else
2237     {
2238         OIC_LOG_V(DEBUG, TAG, "LE Connection state is [newState : %d, status %d]", newState,
2239                 status);
2240     }
2241 }
2242
2243 JNIEXPORT void JNICALL
2244 Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerServiceAddedCallback(JNIEnv *env,
2245                                                                             jobject obj,
2246                                                                             jint status,
2247                                                                             jobject gattService)
2248 {
2249     VERIFY_NON_NULL_VOID(env, TAG, "env");
2250     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2251     VERIFY_NON_NULL_VOID(gattService, TAG, "gattService");
2252
2253     OIC_LOG_V(DEBUG, TAG, "Gatt Service Added Callback(%d)", status);
2254 }
2255
2256 JNIEXPORT void JNICALL
2257 Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerCharacteristicReadRequestCallback(
2258         JNIEnv *env, jobject obj, jobject device, jbyteArray data)
2259 {
2260     OIC_LOG(DEBUG, TAG, " Gatt Server Characteristic Read Request Callback");
2261     VERIFY_NON_NULL_VOID(env, TAG, "env");
2262     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2263     VERIFY_NON_NULL_VOID(device, TAG, "device");
2264     VERIFY_NON_NULL_VOID(data, TAG, "data");
2265 }
2266
2267 JNIEXPORT void JNICALL
2268 Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerCharacteristicWriteRequestCallback(
2269         JNIEnv *env, jobject obj, jobject device, jbyteArray data)
2270 {
2271     OIC_LOG_V(DEBUG, TAG, "Gatt Server Characteristic Write Request Callback");
2272     VERIFY_NON_NULL_VOID(env, TAG, "env");
2273     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2274     VERIFY_NON_NULL_VOID(device, TAG, "device");
2275     VERIFY_NON_NULL_VOID(data, TAG, "data");
2276
2277     // get Byte Array and covert to uint8_t*
2278     jint length = (*env)->GetArrayLength(env, data);
2279
2280     jboolean isCopy;
2281     jbyte *jni_byte_requestData = (jbyte *) (*env)->GetByteArrayElements(env, data, &isCopy);
2282
2283     uint8_t* requestData = NULL;
2284     requestData = OICMalloc(length);
2285     if (!requestData)
2286     {
2287         OIC_LOG(ERROR, TAG, "requestData is null");
2288         return;
2289     }
2290
2291     memcpy(requestData, jni_byte_requestData, length);
2292     (*env)->ReleaseByteArrayElements(env, data, jni_byte_requestData, JNI_ABORT);
2293
2294     jstring jni_address = CALEGetAddressFromBTDevice(env, device);
2295     if (!jni_address)
2296     {
2297         OIC_LOG(ERROR, TAG, "jni_address is null");
2298         OICFree(requestData);
2299         return;
2300     }
2301
2302     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
2303     if (!address)
2304     {
2305         OIC_LOG(ERROR, TAG, "address is null");
2306         OICFree(requestData);
2307         return;
2308     }
2309
2310     OIC_LOG_V(DEBUG, TAG, "remote device address : %s, %p, %d", address, requestData, length);
2311
2312     ca_mutex_lock(g_bleClientBDAddressMutex);
2313     uint32_t sentLength = 0;
2314     g_CABLEServerDataReceivedCallback(address, requestData, length,
2315                                       &sentLength);
2316     ca_mutex_unlock(g_bleClientBDAddressMutex);
2317
2318     (*env)->ReleaseStringUTFChars(env, jni_address, address);
2319 }
2320
2321 JNIEXPORT void JNICALL
2322 Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerNotificationSentCallback(JNIEnv *env,
2323                                                                                 jobject obj,
2324                                                                                 jobject device,
2325                                                                                 jint status)
2326 {
2327     VERIFY_NON_NULL_VOID(env, TAG, "env");
2328     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2329     VERIFY_NON_NULL_VOID(device, TAG, "device");
2330
2331     OIC_LOG_V(DEBUG, TAG, "Gatt Server Notification Sent Callback (status : %d)",
2332               status);
2333
2334     if (GATT_SUCCESS != status) // error case
2335     {
2336         OIC_LOG(ERROR, TAG, "it will be sent again.");
2337
2338         CAResult_t res = CALEServerSend(env, device, g_sendBuffer);
2339         if (CA_STATUS_OK != res)
2340         {
2341             OIC_LOG(ERROR, TAG, "send has failed");
2342             ca_mutex_lock(g_threadSendNotifyMutex);
2343             g_isSignalSetFlag = true;
2344             ca_cond_signal(g_threadSendNotifyCond);
2345             ca_mutex_unlock(g_threadSendNotifyMutex);
2346             return CA_SEND_FAILED;
2347         }
2348     }
2349     else
2350     {
2351         OIC_LOG(DEBUG, TAG, "notify success");
2352
2353         // next data can be sent
2354         ca_mutex_lock(g_threadSendNotifyMutex);
2355         OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
2356         g_isSignalSetFlag = true;
2357         ca_cond_signal(g_threadSendNotifyCond);
2358         ca_mutex_unlock(g_threadSendNotifyMutex);
2359     }
2360
2361 }
2362
2363 JNIEXPORT void JNICALL
2364 Java_org_iotivity_ca_CaLeServerInterface_caLeAdvertiseStartSuccessCallback(JNIEnv *env,
2365                                                                            jobject obj,
2366                                                                            jobject settingsInEffect)
2367 {
2368     VERIFY_NON_NULL_VOID(env, TAG, "env");
2369     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2370     VERIFY_NON_NULL_VOID(settingsInEffect, TAG, "settingsInEffect");
2371
2372     OIC_LOG(DEBUG, TAG, "LE Advertise Start Success Callback");
2373 }
2374
2375 JNIEXPORT void JNICALL
2376 Java_org_iotivity_ca_CaLeServerInterface_caLeAdvertiseStartFailureCallback(JNIEnv *env,
2377                                                                            jobject obj,
2378                                                                            jint errorCode)
2379 {
2380     VERIFY_NON_NULL_VOID(env, TAG, "env");
2381     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
2382
2383     OIC_LOG_V(INFO, TAG, "LE Advertise Start Failure Callback(%d)", errorCode);
2384 }
2385
2386 /**
2387  * adapter common
2388  */
2389
2390 CAResult_t CAStartLEGattServer()
2391 {
2392     // start gatt service
2393     CALEServerStartMulticastServer();
2394
2395     return CA_STATUS_OK;
2396 }
2397
2398 CAResult_t CAStopLEGattServer()
2399 {
2400     OIC_LOG(DEBUG, TAG, "CAStopLEGattServer");
2401
2402     if (!g_jvm)
2403     {
2404         OIC_LOG(ERROR, TAG, "g_jvm is null");
2405         return CA_STATUS_FAILED;
2406     }
2407
2408     bool isAttached = false;
2409     JNIEnv* env;
2410     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
2411     if (JNI_OK != res)
2412     {
2413         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
2414         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
2415
2416         if (JNI_OK != res)
2417         {
2418             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
2419             return CA_STATUS_FAILED;
2420         }
2421         isAttached = true;
2422     }
2423
2424     CAResult_t ret = CALEServerGattClose(env, g_bluetoothGattServer);
2425     if (CA_STATUS_OK != ret)
2426     {
2427         OIC_LOG(ERROR, TAG, "CALEServerGattClose has failed");
2428         return CA_STATUS_FAILED;
2429     }
2430
2431     ret = CALEServerStopMulticastServer();
2432     if (CA_STATUS_OK != ret)
2433     {
2434         OIC_LOG(ERROR, TAG, "CALEServerStopMulticastServer has failed");
2435         return CA_STATUS_FAILED;
2436     }
2437
2438     ret = CALEServerDisconnectAllDevices(env);
2439     if (CA_STATUS_OK != ret)
2440     {
2441         OIC_LOG(ERROR, TAG, "CALEServerDisconnectAllDevices has failed");
2442         return CA_STATUS_FAILED;
2443     }
2444
2445     ret = CALEServerRemoveAllDevices(env);
2446     if (CA_STATUS_OK != ret)
2447     {
2448         OIC_LOG(ERROR, TAG, "CALEServerRemoveAllDevices has failed");
2449         return CA_STATUS_FAILED;
2450     }
2451
2452     if (g_leAdvertiseCallback)
2453     {
2454         (*env)->DeleteGlobalRef(env, g_leAdvertiseCallback);
2455     }
2456
2457     if (g_bluetoothGattServer)
2458     {
2459         (*env)->DeleteGlobalRef(env, g_bluetoothGattServer);
2460     }
2461
2462     if (g_bluetoothGattServerCallback)
2463     {
2464         (*env)->DeleteGlobalRef(env, g_bluetoothGattServerCallback);
2465     }
2466
2467     ca_mutex_lock(g_threadSendNotifyMutex);
2468     ca_cond_signal(g_threadSendNotifyCond);
2469     ca_mutex_unlock(g_threadSendNotifyMutex);
2470
2471     g_isStartServer = false;
2472
2473     if (isAttached)
2474     {
2475         (*g_jvm)->DetachCurrentThread(g_jvm);
2476     }
2477
2478     return CA_STATUS_OK;
2479 }
2480
2481 CAResult_t CAInitializeLEGattServer()
2482 {
2483     OIC_LOG(DEBUG, TAG, "Initialize Gatt Server");
2484     return CALEServerInitialize();
2485 }
2486
2487 void CATerminateLEGattServer()
2488 {
2489     OIC_LOG(DEBUG, TAG, "Terminate Gatt Server");
2490     CALEServerTerminate();
2491 }
2492
2493 void CASetLEReqRespServerCallback(CABLEDataReceivedCallback callback)
2494 {
2495     ca_mutex_lock(g_bleReqRespCbMutex);
2496     g_CABLEServerDataReceivedCallback = callback;
2497     ca_mutex_unlock(g_bleReqRespCbMutex);
2498 }
2499
2500 void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback)
2501 {
2502     g_serverErrorCallback = callback;
2503 }
2504
2505 CAResult_t CAUpdateCharacteristicsToGattClient(const char *address,
2506                                                const uint8_t *charValue,
2507                                                uint32_t charValueLen)
2508 {
2509     CAResult_t result = CA_SEND_FAILED;
2510     VERIFY_NON_NULL(address, TAG, "env is null");
2511     VERIFY_NON_NULL(charValue, TAG, "device is null");
2512
2513     if (address)
2514     {
2515         result = CALEServerSendUnicastMessage(address, charValue, charValueLen);
2516     }
2517
2518     return result;
2519 }
2520
2521 CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue,
2522                                                    uint32_t charValueLen)
2523 {
2524     VERIFY_NON_NULL(charValue, TAG, "device is null");
2525
2526     CAResult_t result = CALEServerSendMulticastMessage(charValue, charValueLen);
2527
2528     return result;
2529 }
2530
2531 void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle)
2532 {
2533     OIC_LOG(INFO, TAG, "CASetLEServerThreadPoolHandle is not support");
2534 }
2535
2536 CAResult_t CALEServerInitMutexVaraibles()
2537 {
2538     if (NULL == g_bleReqRespCbMutex)
2539     {
2540         g_bleReqRespCbMutex = ca_mutex_new();
2541         if (NULL == g_bleReqRespCbMutex)
2542         {
2543             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2544             return CA_STATUS_FAILED;
2545         }
2546     }
2547
2548     if (NULL == g_bleClientBDAddressMutex)
2549     {
2550         g_bleClientBDAddressMutex = ca_mutex_new();
2551         if (NULL == g_bleClientBDAddressMutex)
2552         {
2553             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2554             return CA_STATUS_FAILED;
2555         }
2556     }
2557
2558     if (NULL == g_connectedDeviceListMutex)
2559     {
2560         g_connectedDeviceListMutex = ca_mutex_new();
2561         if (NULL == g_connectedDeviceListMutex)
2562         {
2563             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2564             return CA_STATUS_FAILED;
2565         }
2566     }
2567
2568     if (NULL == g_threadSendMutex)
2569     {
2570         g_threadSendMutex = ca_mutex_new();
2571         if (NULL == g_threadSendMutex)
2572         {
2573             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2574             return CA_STATUS_FAILED;
2575         }
2576     }
2577
2578     if (NULL == g_threadSendNotifyMutex)
2579     {
2580         g_threadSendNotifyMutex = ca_mutex_new();
2581         if (NULL == g_threadSendNotifyMutex)
2582         {
2583             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2584             return CA_STATUS_FAILED;
2585         }
2586     }
2587
2588     return CA_STATUS_OK;
2589 }
2590
2591 void CALEServerTerminateMutexVaraibles()
2592 {
2593     ca_mutex_free(g_bleReqRespCbMutex);
2594     g_bleReqRespCbMutex = NULL;
2595
2596     ca_mutex_free(g_bleClientBDAddressMutex);
2597     g_bleClientBDAddressMutex = NULL;
2598
2599     ca_mutex_free(g_connectedDeviceListMutex);
2600     g_connectedDeviceListMutex = NULL;
2601
2602     ca_mutex_free(g_threadSendMutex);
2603     g_threadSendMutex = NULL;
2604
2605     ca_mutex_free(g_threadSendNotifyMutex);
2606     g_threadSendNotifyMutex = NULL;
2607 }
2608
2609 void CALEServerTerminateConditionVaraibles()
2610 {
2611     OIC_LOG(DEBUG, TAG, "this method is not supported");
2612 }