Merge branch 'master' into resource-manipulation
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / android / caleclient.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 <stdio.h>
22 #include <string.h>
23 #include <jni.h>
24 #include <unistd.h>
25
26 #include "caleclient.h"
27 #include "caleserver.h"
28 #include "caleutils.h"
29 #include "caleinterface.h"
30 #include "caadapterutils.h"
31
32 #include "logger.h"
33 #include "oic_malloc.h"
34 #include "cathreadpool.h" /* for thread pool */
35 #include "camutex.h"
36 #include "uarraylist.h"
37 #include "org_iotivity_ca_CaLeClientInterface.h"
38
39 #define TAG PCF("CA_LE_CLIENT")
40
41 static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;";
42 static const char CLASSPATH_BT_ADAPTER[] = "android/bluetooth/BluetoothAdapter";
43 static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
44 static const char CLASSPATH_BT_GATT[] = "android/bluetooth/BluetoothGatt";
45
46 JavaVM *g_jvm;
47 static u_arraylist_t *g_deviceList = NULL; // device list to have same UUID
48 static u_arraylist_t *g_gattObjectList = NULL;
49 static u_arraylist_t *g_deviceStateList = NULL;
50
51 static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
52 static CABLEErrorHandleCallback g_clientErrorCallback;
53 static ca_thread_pool_t g_threadPoolHandle = NULL;
54 static jobject g_leScanCallback = NULL;
55 static jobject g_leGattCallback = NULL;
56 static jobject g_context = NULL;
57 static jobjectArray g_uuidList = NULL;
58
59 // it will be prevent to start send logic when adapter has stopped.
60 static bool g_isStartedLEClient = false;
61 static bool g_isStartedMulticastServer = false;
62 static bool g_isStartedScan = false;
63
64 static jbyteArray g_sendBuffer = NULL;
65 static uint32_t g_targetCnt = 0;
66 static uint32_t g_currentSentCnt = 0;
67 static bool g_isFinishedSendData = false;
68 static ca_mutex g_SendFinishMutex = false;
69 static ca_mutex g_threadMutex = NULL;
70 static ca_cond g_threadCond = NULL;
71
72 static bool g_isRequestedSend = false;
73 static bool g_isReceivedWriteCB = false;
74 static ca_mutex g_writeCharacteristicCBMutex = false;
75 static ca_mutex g_theSendRequestMutex = false;
76 static ca_mutex g_threadSendCBMutex = NULL;
77 static ca_cond g_threadSendCBCond = NULL;
78
79 static ca_mutex g_threadSendMutex = NULL;
80 static ca_cond g_threadSendCond = NULL;
81
82 static ca_mutex g_bleReqRespClientCbMutex = NULL;
83 static ca_mutex g_bleServerBDAddressMutex = NULL;
84
85 static ca_mutex g_deviceListMutex = NULL;
86 static ca_mutex g_gattObjectMutex = NULL;
87 static ca_mutex g_deviceStateListMutex = NULL;
88
89 static CABLEClientDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
90
91 //getting jvm
92 void CALEClientJniInit()
93 {
94     OIC_LOG(DEBUG, TAG, "CALEClientJniInit");
95     g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
96 }
97
98 void CALEClientJNISetContext()
99 {
100     OIC_LOG(DEBUG, TAG, "CALEClientJNISetContext");
101     g_context = (jobject) CANativeJNIGetContext();
102 }
103
104 CAResult_t CALECreateJniInterfaceObject()
105 {
106     OIC_LOG(DEBUG, TAG, "CALECreateJniInterfaceObject");
107
108     if (!g_context)
109     {
110         OIC_LOG(ERROR, TAG, "g_context is null");
111         return CA_STATUS_FAILED;
112     }
113
114     if (!g_jvm)
115     {
116         OIC_LOG(ERROR, TAG, "g_jvm is null");
117         return CA_STATUS_FAILED;
118     }
119
120     bool isAttached = false;
121     JNIEnv* env;
122     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
123     if (JNI_OK != res)
124     {
125         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
126         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
127
128         if (JNI_OK != res)
129         {
130             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
131             return CA_STATUS_FAILED;
132         }
133         isAttached = true;
134     }
135
136     jclass jni_LEInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
137     if (!jni_LEInterface)
138     {
139         OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
140         goto error_exit;
141     }
142
143     jmethodID LeInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_LEInterface, "<init>",
144                                                                  "(Landroid/content/Context;)V");
145     if (!LeInterfaceConstructorMethod)
146     {
147         OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface constructor method");
148         goto error_exit;
149     }
150
151     (*env)->NewObject(env, jni_LEInterface, LeInterfaceConstructorMethod, g_context);
152     OIC_LOG(DEBUG, TAG, "Create instance for CaLeClientInterface");
153
154     if (isAttached)
155     {
156         (*g_jvm)->DetachCurrentThread(g_jvm);
157     }
158
159     return CA_STATUS_OK;
160
161 error_exit:
162
163     if (isAttached)
164     {
165         (*g_jvm)->DetachCurrentThread(g_jvm);
166     }
167
168     return CA_STATUS_FAILED;
169 }
170
171 CAResult_t CALEClientInitialize(ca_thread_pool_t handle)
172 {
173     OIC_LOG(DEBUG, TAG, "CALEClientInitialize");
174
175     CALEClientJniInit();
176
177     if (!g_jvm)
178     {
179         OIC_LOG(ERROR, TAG, "g_jvm is null");
180         return CA_STATUS_FAILED;
181     }
182
183     bool isAttached = false;
184     JNIEnv* env;
185     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
186     if (JNI_OK != res)
187     {
188         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
189         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
190
191         if (JNI_OK != res)
192         {
193             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
194             return CA_STATUS_FAILED;
195         }
196         isAttached = true;
197     }
198
199     CAResult_t ret = CALECheckPlatformVersion(env, 18);
200     if (CA_STATUS_OK != ret)
201     {
202         OIC_LOG(ERROR, TAG, "it is not supported");
203
204         if (isAttached)
205         {
206             (*g_jvm)->DetachCurrentThread(g_jvm);
207         }
208
209         return ret;
210     }
211
212     g_threadPoolHandle = handle;
213
214     ret = CALEClientInitGattMutexVaraibles();
215     if (CA_STATUS_OK != ret)
216     {
217         OIC_LOG(ERROR, TAG, "CALEClientInitGattMutexVaraibles has failed!");
218         CALEClientTerminateGattMutexVariables();
219
220         if (isAttached)
221         {
222             (*g_jvm)->DetachCurrentThread(g_jvm);
223         }
224
225         return ret;
226     }
227
228     // init mutex for send logic
229     g_threadCond = ca_cond_new();
230     g_threadSendCond = ca_cond_new();
231     g_threadSendCBCond = ca_cond_new();
232
233     CALEClientCreateDeviceList();
234     CALEClientJNISetContext();
235
236     ret = CALEClientCreateUUIDList();
237     if (CA_STATUS_OK != ret)
238     {
239         OIC_LOG(ERROR, TAG, "CALEClientCreateUUIDList has failed");
240
241         if (isAttached)
242         {
243             (*g_jvm)->DetachCurrentThread(g_jvm);
244         }
245
246         return ret;
247     }
248
249     ret = CALECreateJniInterfaceObject(); /* create java caleinterface instance*/
250     if (CA_STATUS_OK != ret)
251     {
252         OIC_LOG(ERROR, TAG, "CALECreateJniInterfaceObject has failed");
253
254         if (isAttached)
255         {
256             (*g_jvm)->DetachCurrentThread(g_jvm);
257         }
258
259         return ret;
260     }
261     g_isStartedLEClient = true;
262
263     return CA_STATUS_OK;
264 }
265
266 void CALEClientTerminate()
267 {
268     OIC_LOG(DEBUG, TAG, "CALEClientTerminate");
269
270     if (!g_jvm)
271     {
272         OIC_LOG(ERROR, TAG, "g_jvm is null");
273         return;
274     }
275
276     bool isAttached = false;
277     JNIEnv* env;
278     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
279     if (JNI_OK != res)
280     {
281         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
282         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
283
284         if (JNI_OK != res)
285         {
286             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
287             return;
288         }
289         isAttached = true;
290     }
291
292     if (g_leScanCallback)
293     {
294         (*env)->DeleteGlobalRef(env, g_leScanCallback);
295     }
296
297     if (g_leGattCallback)
298     {
299         (*env)->DeleteGlobalRef(env, g_leGattCallback);
300     }
301
302     if (g_sendBuffer)
303     {
304         (*env)->DeleteGlobalRef(env, g_sendBuffer);
305     }
306
307     if (g_uuidList)
308     {
309         (*env)->DeleteGlobalRef(env, g_uuidList);
310     }
311
312     CAResult_t ret = CALEClientRemoveAllDeviceState();
313     if (CA_STATUS_OK != ret)
314     {
315         OIC_LOG(ERROR, TAG, "CALEClientRemoveAllDeviceState has failed");
316     }
317
318     ret = CALEClientRemoveAllScanDevices(env);
319     if (CA_STATUS_OK != ret)
320     {
321         OIC_LOG(ERROR, TAG, "CALEClientRemoveAllScanDevices has failed");
322     }
323
324     ret = CALEClientRemoveAllGattObjs(env);
325     if (CA_STATUS_OK != ret)
326     {
327         OIC_LOG(ERROR, TAG, "CALEClientRemoveAllGattObjs has failed");
328     }
329
330     g_isStartedMulticastServer = false;
331     g_isStartedScan = false;
332     CALEClientSetSendFinishFlag(false);
333     CALEClientSetTheSendRequestFlag(false);
334     CALEClientSetWriteCharacteristicCBFlag(false);
335
336     CALEClientTerminateGattMutexVariables();
337
338     ca_cond_free(g_threadCond);
339     ca_cond_free(g_threadSendCond);
340     ca_cond_free(g_threadSendCBCond);
341
342     if (isAttached)
343     {
344         (*g_jvm)->DetachCurrentThread(g_jvm);
345     }
346 }
347
348 void CALEClientSendFinish(JNIEnv *env, jobject gatt)
349 {
350     OIC_LOG(DEBUG, TAG, "CALEClientSendFinish");
351     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
352
353     if (gatt)
354     {
355         CAResult_t res = CALEClientDisconnect(env, gatt);
356         if (CA_STATUS_OK != res)
357         {
358             OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
359         }
360     }
361     CALEClientUpdateSendCnt(env);
362 }
363
364 CAResult_t CALEClientSendUnicastMessage(const char* address, const char* data,
365                                         const uint32_t dataLen)
366 {
367     OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessage(%s, %s)", address, data);
368     VERIFY_NON_NULL(address, TAG, "address is null");
369     VERIFY_NON_NULL(data, TAG, "data is null");
370
371     return CALEClientSendUnicastMessageImpl(address, data, dataLen);
372 }
373
374 CAResult_t CALEClientSendMulticastMessage(const char* data, const uint32_t dataLen)
375 {
376     OIC_LOG_V(DEBUG, TAG, "CALEClientSendMulticastMessage(%s)", data);
377     VERIFY_NON_NULL(data, TAG, "data is null");
378
379     if (!g_jvm)
380     {
381         OIC_LOG(ERROR, TAG, "g_jvm is null");
382         return CA_STATUS_FAILED;
383     }
384
385     bool isAttached = false;
386     JNIEnv* env;
387     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
388     if (JNI_OK != res)
389     {
390         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
391         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
392
393         if (JNI_OK != res)
394         {
395             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
396             return CA_STATUS_FAILED;
397         }
398         isAttached = true;
399     }
400
401     CAResult_t ret = CALEClientSendMulticastMessageImpl(env, data, dataLen);
402     if (CA_STATUS_OK != ret)
403     {
404         OIC_LOG(ERROR, TAG, "CALEClientSendMulticastMessageImpl has failed");
405     }
406
407     if (isAttached)
408     {
409         (*g_jvm)->DetachCurrentThread(g_jvm);
410     }
411
412     return ret;
413 }
414
415 CAResult_t CALEClientStartUnicastServer(const char* address)
416 {
417     OIC_LOG_V(DEBUG, TAG, "it is not needed in this platform (%s)", address);
418
419     return CA_NOT_SUPPORTED;
420 }
421
422 CAResult_t CALEClientStartMulticastServer()
423 {
424     OIC_LOG(DEBUG, TAG, "CALEClientStartMulticastServer");
425
426     if (g_isStartedMulticastServer)
427     {
428         OIC_LOG(ERROR, TAG, "server is already started..it will be skipped");
429         return CA_STATUS_FAILED;
430     }
431
432     if (!g_jvm)
433     {
434         OIC_LOG(ERROR, TAG, "g_jvm is null");
435         return CA_STATUS_FAILED;
436     }
437
438     bool isAttached = false;
439     JNIEnv* env;
440     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
441     if (JNI_OK != res)
442     {
443         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
444         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
445
446         if (JNI_OK != res)
447         {
448             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
449             return CA_STATUS_FAILED;
450         }
451         isAttached = true;
452     }
453
454     g_isStartedMulticastServer = true;
455     CAResult_t ret = CALEClientStartScan();
456     if (CA_STATUS_OK != ret)
457     {
458         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
459     }
460
461     if (isAttached)
462     {
463         (*g_jvm)->DetachCurrentThread(g_jvm);
464     }
465
466     return ret;
467 }
468
469 void CALEClientStopUnicastServer()
470 {
471     OIC_LOG(DEBUG, TAG, "CALEClientStopUnicastServer");
472 }
473
474 void CALEClientStopMulticastServer()
475 {
476     OIC_LOG(DEBUG, TAG, "CALEClientStopMulticastServer");
477     g_isStartedMulticastServer = false;
478     CAResult_t res = CALEClientStopScan();
479     if (CA_STATUS_OK != res)
480     {
481         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
482         return;
483     }
484 }
485
486 void CALEClientSetCallback(CAPacketReceiveCallback callback)
487 {
488     g_packetReceiveCallback = callback;
489 }
490
491 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
492 {
493     g_clientErrorCallback = callback;
494 }
495
496 CAResult_t CALEClientGetInterfaceInfo(char **address)
497 {
498     OIC_LOG(INFO, TAG, "CALEClientGetInterfaceInfo is not supported");
499     return CA_NOT_SUPPORTED;
500 }
501
502 CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const char* data,
503                                       const uint32_t dataLen)
504 {
505     OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessageImpl, address: %s, data: %s", address,
506               data);
507     VERIFY_NON_NULL(address, TAG, "address is null");
508     VERIFY_NON_NULL(data, TAG, "data is null");
509
510     if (!g_jvm)
511     {
512         OIC_LOG(ERROR, TAG, "g_jvm is null");
513         return CA_STATUS_FAILED;
514     }
515
516     bool isAttached = false;
517     JNIEnv* env;
518     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
519     if (JNI_OK != res)
520     {
521         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
522         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
523         if (JNI_OK != res)
524         {
525             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
526             return CA_STATUS_FAILED;
527         }
528         isAttached = true;
529     }
530
531     ca_mutex_lock(g_threadSendMutex);
532
533     CAResult_t ret = CA_STATUS_OK;
534     if (g_context && g_deviceList)
535     {
536         uint32_t length = u_arraylist_length(g_deviceList);
537         for (uint32_t index = 0; index < length; index++)
538         {
539             jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
540             if (!jarrayObj)
541             {
542                 OIC_LOG(ERROR, TAG, "jarrayObj is null");
543                 goto error_exit;
544             }
545
546             jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
547             if (!jni_setAddress)
548             {
549                 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
550                 goto error_exit;
551             }
552
553             const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
554             if (!setAddress)
555             {
556                 OIC_LOG(ERROR, TAG, "setAddress is null");
557                 goto error_exit;
558             }
559
560             OIC_LOG_V(DEBUG, TAG, "remote device address is %s", setAddress);
561
562             if (!strcmp(setAddress, address))
563             {
564                 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
565
566                 // connect to gatt server
567                 ret = CALEClientStopScan();
568                 if (CA_STATUS_OK != ret)
569                 {
570                     OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
571                     goto error_exit;
572                 }
573
574                 if (g_sendBuffer)
575                 {
576                     (*env)->DeleteGlobalRef(env, g_sendBuffer);
577                 }
578                 jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
579                 (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
580                 g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
581
582                 ret = CALEClientSendData(env, jarrayObj);
583                 if (CA_STATUS_OK != ret)
584                 {
585                     OIC_LOG(ERROR, TAG, "CALEClientSendData in unicast is failed");
586                     goto error_exit;
587                 }
588                 else
589                 {
590                     CALEClientSetTheSendRequestFlag(true);
591                     ca_cond_signal(g_threadSendCBCond);
592
593                     if (!g_isReceivedWriteCB)
594                     {
595                         OIC_LOG(INFO, TAG, "wait..(unicast)");
596                         ca_cond_wait(g_threadSendCond, g_threadSendMutex);
597                     }
598                     else
599                     {
600                         CALEClientSetWriteCharacteristicCBFlag(false);
601                     }
602                 }
603
604                 OIC_LOG(INFO, TAG, "wake up");
605                 break;
606             }
607             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
608         }
609     }
610
611     if (isAttached)
612     {
613         (*g_jvm)->DetachCurrentThread(g_jvm);
614     }
615
616     ret = CALECheckSendState(address);
617     if(CA_STATUS_OK != ret)
618     {
619         OIC_LOG(ERROR, TAG, "send has failed");
620         goto error_exit;
621     }
622
623     // start LE Scan again
624     ret = CALEClientStartScan();
625     if (CA_STATUS_OK != ret)
626     {
627         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
628         ca_mutex_unlock(g_threadSendMutex);
629         return res;
630     }
631
632     ca_mutex_unlock(g_threadSendMutex);
633     OIC_LOG(INFO, TAG, "unicast - send success");
634     return CA_STATUS_OK;
635
636     // error label.
637 error_exit:
638
639     // start LE Scan again
640     ret = CALEClientStartScan();
641     if (CA_STATUS_OK != ret)
642     {
643         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
644         ca_mutex_unlock(g_threadSendMutex);
645         return res;
646     }
647
648     if (isAttached)
649     {
650         (*g_jvm)->DetachCurrentThread(g_jvm);
651     }
652     ca_mutex_unlock(g_threadSendMutex);
653     return CA_SEND_FAILED;
654 }
655
656 CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const char* data,
657                                               const uint32_t dataLen)
658 {
659     OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen);
660     VERIFY_NON_NULL(data, TAG, "data is null");
661     VERIFY_NON_NULL(env, TAG, "env is null");
662
663     if (!g_deviceList)
664     {
665         OIC_LOG(ERROR, TAG, "g_deviceList is null");
666         return CA_STATUS_FAILED;
667     }
668
669     ca_mutex_lock(g_threadSendMutex);
670
671     CALEClientSetSendFinishFlag(false);
672
673     OIC_LOG(DEBUG, TAG, "set byteArray for data");
674     if (g_sendBuffer)
675     {
676         (*env)->DeleteGlobalRef(env, g_sendBuffer);
677     }
678     jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
679     (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
680     g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
681
682     // connect to gatt server
683     CAResult_t res = CALEClientStopScan();
684     if (CA_STATUS_OK != res)
685     {
686         OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
687         ca_mutex_unlock(g_threadSendMutex);
688         return res;
689     }
690
691     uint32_t length = u_arraylist_length(g_deviceList);
692     g_targetCnt = length;
693     if (0 == length)
694     {
695         goto error_exit;
696     }
697
698     for (uint32_t index = 0; index < length; index++)
699     {
700         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
701         if (!jarrayObj)
702         {
703             OIC_LOG(ERROR, TAG, "jarrayObj is not available");
704             continue;
705         }
706
707         res = CALEClientSendData(env, jarrayObj);
708         if (res != CA_STATUS_OK)
709         {
710             OIC_LOG(ERROR, TAG, "BT device[%d] - send has failed");
711         }
712         else
713         {
714             CALEClientSetTheSendRequestFlag(true);
715             ca_cond_signal(g_threadSendCBCond);
716
717             if (!g_isReceivedWriteCB)
718             {
719                 OIC_LOG(INFO, TAG, "wait..(multicast)");
720                 ca_cond_wait(g_threadSendCond, g_threadSendMutex);
721             }
722             else
723             {
724                 CALEClientSetWriteCharacteristicCBFlag(false);
725             }
726         }
727
728         jstring jni_address = CALEGetAddressFromBTDevice(env, jarrayObj);
729         if (!jni_address)
730         {
731             OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
732             continue;
733         }
734
735         const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
736         if (!address)
737         {
738             OIC_LOG(ERROR, TAG, "address is not available");
739             continue;
740         }
741
742         res = CALECheckSendState(address);
743         if (CA_STATUS_OK != res)
744         {
745             OIC_LOG_V(INFO, TAG, "multicast : send has failed for this device[%s]", address);
746             g_clientErrorCallback(address, data, dataLen, res);
747             (*env)->ReleaseStringUTFChars(env, jni_address, address);
748             continue;
749         }
750
751         (*env)->ReleaseStringUTFChars(env, jni_address, address);
752     }
753
754     OIC_LOG(DEBUG, TAG, "connection routine is finished");
755
756     // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
757     if (!g_isFinishedSendData)
758     {
759         ca_mutex_lock(g_threadMutex);
760         ca_cond_wait(g_threadCond, g_threadMutex);
761         OIC_LOG(DEBUG, TAG, "the data was sent for All devices");
762         ca_mutex_unlock(g_threadMutex);
763     }
764
765     // start LE Scan again
766     res = CALEClientStartScan();
767     if (CA_STATUS_OK != res)
768     {
769         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
770         ca_mutex_unlock(g_threadSendMutex);
771         return res;
772     }
773
774     ca_mutex_unlock(g_threadSendMutex);
775     OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
776     return CA_STATUS_OK;
777
778 error_exit:
779     res = CALEClientStartScan();
780     if (CA_STATUS_OK != res)
781     {
782         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
783         ca_mutex_unlock(g_threadSendMutex);
784         return res;
785     }
786
787     ca_mutex_unlock(g_threadSendMutex);
788     OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
789     return CA_SEND_FAILED;
790 }
791
792 CAResult_t CALECheckSendState(const char* address)
793 {
794     VERIFY_NON_NULL(address, TAG, "address is null");
795
796     ca_mutex_lock(g_deviceStateListMutex);
797     CALEState_t* state = CALEClientGetStateInfo(address);
798     if (NULL == state)
799     {
800         OIC_LOG(ERROR, TAG, "state is null");
801         ca_mutex_unlock(g_deviceStateListMutex);
802         return CA_SEND_FAILED;
803     }
804
805     if (STATE_SEND_SUCCESS != state->sendState)
806     {
807         OIC_LOG(ERROR, TAG, "sendstate is not STATE_SEND_SUCCESS");
808         ca_mutex_unlock(g_deviceStateListMutex);
809         return CA_SEND_FAILED;
810     }
811     ca_mutex_unlock(g_deviceStateListMutex);
812     return CA_STATUS_OK;
813 }
814
815 CAResult_t CALEClientSendData(JNIEnv *env, jobject device)
816 {
817     OIC_LOG(DEBUG, TAG, "IN - CALEClientSendData");
818     VERIFY_NON_NULL(device, TAG, "device is null");
819     VERIFY_NON_NULL(env, TAG, "env is null");
820
821     jstring jni_address = CALEGetAddressFromBTDevice(env, device);
822     if (!jni_address)
823     {
824         OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
825         return CA_STATUS_FAILED;
826     }
827
828     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
829     if (!address)
830     {
831         OIC_LOG(ERROR, TAG, "address is not available");
832         return CA_STATUS_FAILED;
833     }
834
835     ca_mutex_lock(g_deviceStateListMutex);
836     CALEState_t* state = CALEClientGetStateInfo(address);
837     ca_mutex_unlock(g_deviceStateListMutex);
838     if (!state)
839     {
840         OIC_LOG(DEBUG, TAG, "state is empty..start to connect LE");
841         CAResult_t ret = CALEClientConnect(env, device, JNI_FALSE, g_leGattCallback);
842         if (CA_STATUS_OK != ret)
843         {
844             OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
845             (*env)->ReleaseStringUTFChars(env, jni_address, address);
846             return ret;
847         }
848     }
849     else
850     {
851         if (STATE_CONNECTED == state->connectedState)
852         {
853             OIC_LOG(INFO, TAG, "GATT has already connected");
854             jobject gatt = CALEClientGetGattObjInList(env, address);
855             if (!gatt)
856             {
857                 OIC_LOG(ERROR, TAG, "CALEClientGetGattObjInList has failed");
858                 (*env)->ReleaseStringUTFChars(env, jni_address, address);
859                 return CA_STATUS_FAILED;
860             }
861
862             CAResult_t ret = CALEClientWriteCharacteristic(env, gatt);
863             if (CA_STATUS_OK != ret)
864             {
865                 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
866                 (*env)->ReleaseStringUTFChars(env, jni_address, address);
867                 return ret;
868             }
869         }
870         else
871         {
872             OIC_LOG(DEBUG, TAG, "start to connect LE");
873             CAResult_t ret = CALEClientConnect(env, device, JNI_FALSE, g_leGattCallback);
874             if (CA_STATUS_OK != ret)
875             {
876                 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
877                 (*env)->ReleaseStringUTFChars(env, jni_address, address);
878                 return ret;
879             }
880         }
881     }
882
883     (*env)->ReleaseStringUTFChars(env, jni_address, address);
884     return CA_STATUS_OK;
885 }
886
887 jstring CALEClientGetAddressFromGattObj(JNIEnv *env, jobject gatt)
888 {
889     VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
890     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
891
892     jclass jni_cid_gattdevice_list = (*env)->FindClass(env, CLASSPATH_BT_GATT);
893     if (!jni_cid_gattdevice_list)
894     {
895         OIC_LOG(ERROR, TAG, "jni_cid_gattdevice_list is null");
896         return NULL;
897     }
898
899     jmethodID jni_mid_getDevice = (*env)->GetMethodID(env, jni_cid_gattdevice_list, "getDevice",
900                                                       "()Landroid/bluetooth/BluetoothDevice;");
901     if (!jni_mid_getDevice)
902     {
903         OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
904         return NULL;
905     }
906
907     jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
908     if (!jni_obj_device)
909     {
910         OIC_LOG(ERROR, TAG, "jni_obj_device is null");
911         return NULL;
912     }
913
914     jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
915     if (!jni_address)
916     {
917         OIC_LOG(ERROR, TAG, "jni_address is null");
918         return NULL;
919     }
920
921     return jni_address;
922 }
923
924 /**
925  * BLE layer
926  */
927 CAResult_t CALEClientGattClose(JNIEnv *env, jobject bluetoothGatt)
928 {
929     // GATT CLOSE
930     OIC_LOG(DEBUG, TAG, "Gatt Close");
931     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
932     VERIFY_NON_NULL(env, TAG, "env is null");
933
934     // get BluetoothGatt class
935     OIC_LOG(DEBUG, TAG, "get BluetoothGatt class");
936     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
937     if (!jni_cid_BluetoothGatt)
938     {
939         OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
940         return CA_STATUS_FAILED;
941     }
942
943     jmethodID jni_mid_closeGatt = (*env)->GetMethodID(env, jni_cid_BluetoothGatt, "close", "()V");
944     if (!jni_mid_closeGatt)
945     {
946         OIC_LOG(ERROR, TAG, "jni_mid_closeGatt is null");
947         return CA_STATUS_OK;
948     }
949
950     // call disconnect gatt method
951     OIC_LOG(DEBUG, TAG, "request to close GATT");
952     (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_closeGatt);
953
954     if ((*env)->ExceptionCheck(env))
955     {
956         OIC_LOG(ERROR, TAG, "closeGATT has failed");
957         (*env)->ExceptionDescribe(env);
958         (*env)->ExceptionClear(env);
959         return CA_STATUS_FAILED;
960     }
961
962     return CA_STATUS_OK;
963 }
964
965 CAResult_t CALEClientStartScan()
966 {
967     if (!g_isStartedMulticastServer)
968     {
969         OIC_LOG(ERROR, TAG, "server is not started yet..scan will be passed");
970         return CA_STATUS_FAILED;
971     }
972
973     if (!g_isStartedLEClient)
974     {
975         OIC_LOG(ERROR, TAG, "LE client is not started");
976         return CA_STATUS_FAILED;
977     }
978
979     if (!g_jvm)
980     {
981         OIC_LOG(ERROR, TAG, "g_jvm is null");
982         return CA_STATUS_FAILED;
983     }
984
985     if (g_isStartedScan)
986     {
987         OIC_LOG(INFO, TAG, "scanning is already started");
988         return CA_STATUS_OK;
989     }
990
991     bool isAttached = false;
992     JNIEnv* env;
993     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
994     if (JNI_OK != res)
995     {
996         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
997
998         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
999         if (JNI_OK != res)
1000         {
1001             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1002             return CA_STATUS_FAILED;
1003         }
1004         isAttached = true;
1005     }
1006
1007     OIC_LOG(DEBUG, TAG, "CALEClientStartScan");
1008
1009     CAResult_t ret = CA_STATUS_OK;
1010     // scan gatt server with UUID
1011     if (g_leScanCallback && g_uuidList)
1012     {
1013 #ifdef UUID_SCAN
1014         ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback);
1015         if(CA_STATUS_OK != ret)
1016         {
1017             OIC_LOG(ERROR, TAG, "CALEClientStartScanWithUUIDImpl has failed");
1018         }
1019 #else
1020         ret = CALEClientStartScanImpl(env, g_leScanCallback);
1021         if (CA_STATUS_OK != ret)
1022         {
1023             OIC_LOG(ERROR, TAG, "CALEClientStartScanImpl has failed");
1024         }
1025 #endif
1026     }
1027
1028     if (isAttached)
1029     {
1030         (*g_jvm)->DetachCurrentThread(g_jvm);
1031     }
1032
1033     return ret;
1034 }
1035
1036 CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback)
1037 {
1038     VERIFY_NON_NULL(callback, TAG, "callback is null");
1039     VERIFY_NON_NULL(env, TAG, "env is null");
1040
1041     if (!CALEIsEnableBTAdapter(env))
1042     {
1043         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1044         return CA_ADAPTER_NOT_ENABLED;
1045     }
1046
1047     // get default bt adapter class
1048     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1049     if (!jni_cid_BTAdapter)
1050     {
1051         OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1052         return CA_STATUS_FAILED;
1053     }
1054
1055     // get remote bt adapter method
1056     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1057                                                                     "getDefaultAdapter",
1058                                                                     METHODID_OBJECTNONPARAM);
1059     if (!jni_mid_getDefaultAdapter)
1060     {
1061         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1062         return CA_STATUS_FAILED;
1063     }
1064
1065     // get start le scan method
1066     jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1067                                                         "(Landroid/bluetooth/BluetoothAdapter$"
1068                                                         "LeScanCallback;)Z");
1069     if (!jni_mid_startLeScan)
1070     {
1071         OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1072         return CA_STATUS_FAILED;
1073     }
1074
1075     // gat bt adapter object
1076     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1077                                                                jni_mid_getDefaultAdapter);
1078     if (!jni_obj_BTAdapter)
1079     {
1080         OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1081         return CA_STATUS_FAILED;
1082     }
1083
1084     // call start le scan method
1085     jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1086                                                              jni_mid_startLeScan, callback);
1087     if (!jni_obj_startLeScan)
1088     {
1089         OIC_LOG(ERROR, TAG, "startLeScan is failed");
1090         return CA_STATUS_FAILED;
1091     }
1092     else
1093     {
1094         OIC_LOG(DEBUG, TAG, "startLeScan is started");
1095         g_isStartedScan = true;
1096     }
1097
1098     return CA_STATUS_OK;
1099 }
1100
1101 CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback)
1102 {
1103     VERIFY_NON_NULL(callback, TAG, "callback is null");
1104     VERIFY_NON_NULL(uuids, TAG, "uuids is null");
1105     VERIFY_NON_NULL(env, TAG, "env is null");
1106
1107     if (!CALEIsEnableBTAdapter(env))
1108     {
1109         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1110         return CA_ADAPTER_NOT_ENABLED;
1111     }
1112
1113     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1114     if (!jni_cid_BTAdapter)
1115     {
1116         OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1117         return CA_STATUS_FAILED;
1118     }
1119
1120     // get remote bt adapter method
1121     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1122                                                                     "getDefaultAdapter",
1123                                                                     METHODID_OBJECTNONPARAM);
1124     if (!jni_mid_getDefaultAdapter)
1125     {
1126         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1127         return CA_STATUS_FAILED;
1128     }
1129
1130     // get start le scan method
1131     jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1132                                                         "([Ljava/util/UUID;Landroid/bluetooth/"
1133                                                         "BluetoothAdapter$LeScanCallback;)Z");
1134     if (!jni_mid_startLeScan)
1135     {
1136         OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1137         return CA_STATUS_FAILED;
1138     }
1139
1140     // get bt adapter object
1141     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1142                                                                jni_mid_getDefaultAdapter);
1143     if (!jni_obj_BTAdapter)
1144     {
1145         OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1146         return CA_STATUS_FAILED;
1147     }
1148
1149     // call start le scan method
1150     jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1151                                                              jni_mid_startLeScan, uuids, callback);
1152     if (!jni_obj_startLeScan)
1153     {
1154         OIC_LOG(ERROR, TAG, "startLeScan With UUID is failed");
1155         return CA_STATUS_FAILED;
1156     }
1157     else
1158     {
1159         OIC_LOG(DEBUG, TAG, "startLeScan With UUID is started");
1160         g_isStartedScan = true;
1161     }
1162
1163     return CA_STATUS_OK;
1164 }
1165
1166 jobject CALEClientGetUUIDObject(JNIEnv *env, const char* uuid)
1167 {
1168     VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
1169     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1170
1171     // setting UUID
1172     jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1173     if (!jni_cid_uuid)
1174     {
1175         OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
1176         return NULL;
1177     }
1178
1179     jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_uuid, "fromString",
1180                                                              "(Ljava/lang/String;)"
1181                                                              "Ljava/util/UUID;");
1182     if (!jni_mid_fromString)
1183     {
1184         OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
1185         return NULL;
1186     }
1187
1188     jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
1189     jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1190                                                           jni_uuid);
1191     if (!jni_obj_uuid)
1192     {
1193         OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1194         return NULL;
1195     }
1196
1197     return jni_obj_uuid;
1198 }
1199
1200 CAResult_t CALEClientStopScan()
1201 {
1202     if (!g_jvm)
1203     {
1204         OIC_LOG(ERROR, TAG, "g_jvm is null");
1205         return CA_STATUS_FAILED;
1206     }
1207
1208     if (!g_isStartedScan)
1209     {
1210         OIC_LOG(INFO, TAG, "scanning is already stopped");
1211         return CA_STATUS_OK;
1212     }
1213
1214     bool isAttached = false;
1215     JNIEnv* env;
1216     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1217     if (JNI_OK != res)
1218     {
1219         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1220         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1221         if (JNI_OK != res)
1222         {
1223             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1224             return CA_STATUS_FAILED;
1225         }
1226         isAttached = true;
1227     }
1228
1229     CAResult_t ret = CALEClientStopScanImpl(env, g_leScanCallback);
1230     if (CA_STATUS_OK != ret)
1231     {
1232         OIC_LOG(ERROR, TAG, "CALEClientStopScanImpl has failed");
1233     }
1234     else
1235     {
1236         g_isStartedScan = false;
1237     }
1238
1239     if (isAttached)
1240     {
1241         (*g_jvm)->DetachCurrentThread(g_jvm);
1242     }
1243
1244     return ret;
1245 }
1246
1247 CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
1248 {
1249     OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl");
1250     VERIFY_NON_NULL(callback, TAG, "callback is null");
1251     VERIFY_NON_NULL(env, TAG, "env is null");
1252
1253     if (!CALEIsEnableBTAdapter(env))
1254     {
1255         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1256         return CA_ADAPTER_NOT_ENABLED;
1257     }
1258
1259     // get default bt adapter class
1260     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1261     if (!jni_cid_BTAdapter)
1262     {
1263         OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1264         return CA_STATUS_FAILED;
1265     }
1266
1267     // get remote bt adapter method
1268     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1269                                                                     "getDefaultAdapter",
1270                                                                     METHODID_OBJECTNONPARAM);
1271     if (!jni_mid_getDefaultAdapter)
1272     {
1273         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1274         return CA_STATUS_FAILED;
1275     }
1276
1277     // get start le scan method
1278     jmethodID jni_mid_stopLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "stopLeScan",
1279                                                        "(Landroid/bluetooth/"
1280                                                        "BluetoothAdapter$LeScanCallback;)V");
1281     if (!jni_mid_stopLeScan)
1282     {
1283         OIC_LOG(ERROR, TAG, "stopLeScan: jni_mid_stopLeScan is null");
1284         return CA_STATUS_FAILED;
1285     }
1286
1287     // gat bt adapter object
1288     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1289                                                                jni_mid_getDefaultAdapter);
1290     if (!jni_obj_BTAdapter)
1291     {
1292         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1293         return CA_STATUS_FAILED;
1294     }
1295
1296     OIC_LOG(DEBUG, TAG, "CALL API - request to stop LE Scan");
1297     // call start le scan method
1298     (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_stopLeScan, callback);
1299     if ((*env)->ExceptionCheck(env))
1300     {
1301         OIC_LOG(ERROR, TAG, "stopLeScan has failed");
1302         (*env)->ExceptionDescribe(env);
1303         (*env)->ExceptionClear(env);
1304         return CA_STATUS_FAILED;
1305     }
1306
1307     return CA_STATUS_OK;
1308 }
1309
1310 CAResult_t CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect,
1311                              jobject callback)
1312 {
1313     OIC_LOG(DEBUG, TAG, "GATT CONNECT");
1314     VERIFY_NON_NULL(env, TAG, "env is null");
1315     VERIFY_NON_NULL(bluetoothDevice, TAG, "bluetoothDevice is null");
1316     VERIFY_NON_NULL(callback, TAG, "callback is null");
1317
1318     if (!CALEIsEnableBTAdapter(env))
1319     {
1320         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1321         return CA_ADAPTER_NOT_ENABLED;
1322     }
1323
1324     jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
1325     if (!jni_address)
1326     {
1327         OIC_LOG(ERROR, TAG, "bleConnect: CALEGetAddressFromBTDevice is null");
1328         return CA_STATUS_FAILED;
1329     }
1330
1331     // get BluetoothDevice class
1332     OIC_LOG(DEBUG, TAG, "get BluetoothDevice class");
1333     jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, "android/bluetooth/BluetoothDevice");
1334     if (!jni_cid_BluetoothDevice)
1335     {
1336         OIC_LOG(ERROR, TAG, "bleConnect: jni_cid_BluetoothDevice is null");
1337         return CA_STATUS_FAILED;
1338     }
1339
1340     // get connectGatt method
1341     OIC_LOG(DEBUG, TAG, "get connectGatt method");
1342     jmethodID jni_mid_connectGatt = (*env)->GetMethodID(env, jni_cid_BluetoothDevice, "connectGatt",
1343                                                         "(Landroid/content/Context;ZLandroid/"
1344                                                         "bluetooth/BluetoothGattCallback;)"
1345                                                         "Landroid/bluetooth/BluetoothGatt;");
1346     if (!jni_mid_connectGatt)
1347     {
1348         OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null");
1349         return CA_STATUS_FAILED;
1350     }
1351
1352     OIC_LOG(DEBUG, TAG, "Call object method - connectGatt");
1353     jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice,
1354                                                            jni_mid_connectGatt,
1355                                                            NULL,
1356                                                            autoconnect, callback);
1357     if (!jni_obj_connectGatt)
1358     {
1359         OIC_LOG(ERROR, TAG, "CALL API - connectGatt was failed..it will be removed");
1360         CALEClientRemoveDeviceInScanDeviceList(env, jni_address);
1361         CALEClientUpdateSendCnt(env);
1362         return CA_STATUS_FAILED;
1363     }
1364     else
1365     {
1366         OIC_LOG(DEBUG, TAG, "le connecting..please wait..");
1367     }
1368     return CA_STATUS_OK;
1369 }
1370
1371 CAResult_t CALEClientDisconnect(JNIEnv *env, jobject bluetoothGatt)
1372 {
1373     OIC_LOG(DEBUG, TAG, "GATT DISCONNECT");
1374     VERIFY_NON_NULL(env, TAG, "env is null");
1375     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1376
1377     if (!CALEIsEnableBTAdapter(env))
1378     {
1379         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1380         return CA_ADAPTER_NOT_ENABLED;
1381     }
1382
1383     // get BluetoothGatt class
1384     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
1385     if (!jni_cid_BluetoothGatt)
1386     {
1387         OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
1388         return CA_STATUS_FAILED;
1389     }
1390
1391     OIC_LOG(DEBUG, TAG, "get gatt disconnect method");
1392     jmethodID jni_mid_disconnectGatt = (*env)->GetMethodID(env, jni_cid_BluetoothGatt,
1393                                                            "disconnect", "()V");
1394     if (!jni_mid_disconnectGatt)
1395     {
1396         OIC_LOG(ERROR, TAG, "jni_mid_disconnectGatt is null");
1397         return CA_STATUS_FAILED;
1398     }
1399
1400     // call disconnect gatt method
1401     (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_disconnectGatt);
1402     if ((*env)->ExceptionCheck(env))
1403     {
1404         OIC_LOG(ERROR, TAG, "disconnect has failed");
1405         (*env)->ExceptionDescribe(env);
1406         (*env)->ExceptionClear(env);
1407         return CA_STATUS_FAILED;
1408     }
1409
1410     OIC_LOG(DEBUG, TAG, "disconnecting Gatt...");
1411
1412     return CA_STATUS_OK;
1413 }
1414
1415 CAResult_t CALEClientDisconnectAll(JNIEnv *env)
1416 {
1417     OIC_LOG(DEBUG, TAG, "CALEClientDisconnectAll");
1418     VERIFY_NON_NULL(env, TAG, "env is null");
1419
1420     if (!g_gattObjectList)
1421     {
1422         OIC_LOG(ERROR, TAG, "g_gattObjectList is null");
1423         return CA_STATUS_FAILED;
1424     }
1425
1426     uint32_t length = u_arraylist_length(g_gattObjectList);
1427     for (uint32_t index = 0; index < length; index++)
1428     {
1429         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1430         if (!jarrayObj)
1431         {
1432             OIC_LOG(ERROR, TAG, "jarrayObj is null");
1433             continue;
1434         }
1435         CAResult_t res = CALEClientDisconnect(env, jarrayObj);
1436         if (CA_STATUS_OK != res)
1437         {
1438             OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
1439             continue;
1440         }
1441     }
1442
1443     OICFree(g_gattObjectList);
1444     g_gattObjectList = NULL;
1445
1446     return CA_STATUS_OK;
1447 }
1448
1449 CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt)
1450 {
1451     VERIFY_NON_NULL(env, TAG, "env is null");
1452     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1453
1454     if (!CALEIsEnableBTAdapter(env))
1455     {
1456         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1457         return CA_ADAPTER_NOT_ENABLED;
1458     }
1459
1460     // get BluetoothGatt class
1461     OIC_LOG(DEBUG, TAG, "get BluetoothGatt class");
1462     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
1463     if (!jni_cid_BluetoothGatt)
1464     {
1465         OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
1466         return CA_STATUS_FAILED;
1467     }
1468
1469     OIC_LOG(DEBUG, TAG, "discovery gatt services method");
1470     jmethodID jni_mid_discoverServices = (*env)->GetMethodID(env, jni_cid_BluetoothGatt,
1471                                                              "discoverServices", "()Z");
1472     if (!jni_mid_discoverServices)
1473     {
1474         OIC_LOG(ERROR, TAG, "jni_mid_discoverServices is null");
1475         return CA_STATUS_FAILED;
1476     }
1477     // call disconnect gatt method
1478     OIC_LOG(DEBUG, TAG, "CALL API - request discovery gatt services");
1479     jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_discoverServices);
1480     if (!ret)
1481     {
1482         OIC_LOG(ERROR, TAG, "discoverServices has not been started");
1483         return CA_STATUS_FAILED;
1484     }
1485
1486     return CA_STATUS_OK;
1487 }
1488
1489 CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt)
1490 {
1491     VERIFY_NON_NULL(env, TAG, "env is null");
1492     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
1493
1494     // send data
1495     jobject jni_obj_character = CALEClientCreateGattCharacteristic(env, gatt, g_sendBuffer);
1496     if (!jni_obj_character)
1497     {
1498         CALEClientSendFinish(env, gatt);
1499         ca_cond_signal(g_threadSendCond);
1500         return CA_STATUS_FAILED;
1501     }
1502
1503     CAResult_t ret = CALEClientWriteCharacteristicImpl(env, gatt, jni_obj_character);
1504     if (CA_STATUS_OK != ret)
1505     {
1506         CALEClientSendFinish(env, gatt);
1507         ca_cond_signal(g_threadSendCond);
1508         return ret;
1509     }
1510
1511     return CA_STATUS_OK;
1512 }
1513
1514 CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt,
1515                                            jobject gattCharacteristic)
1516 {
1517     OIC_LOG(DEBUG, TAG, "WRITE GATT CHARACTERISTIC");
1518     VERIFY_NON_NULL(env, TAG, "env is null");
1519     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1520     VERIFY_NON_NULL(gattCharacteristic, TAG, "gattCharacteristic is null");
1521
1522     if (!CALEIsEnableBTAdapter(env))
1523     {
1524         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1525         return CA_STATUS_FAILED;
1526     }
1527
1528     // get BluetoothGatt class
1529     OIC_LOG(DEBUG, TAG, "get BluetoothGatt class");
1530     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
1531     if (!jni_cid_BluetoothGatt)
1532     {
1533         OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
1534         return CA_STATUS_FAILED;
1535     }
1536
1537     OIC_LOG(DEBUG, TAG, "write characteristic method");
1538     jmethodID jni_mid_writeCharacteristic = (*env)->GetMethodID(env, jni_cid_BluetoothGatt,
1539                                                                 "writeCharacteristic",
1540                                                                 "(Landroid/bluetooth/"
1541                                                                 "BluetoothGattCharacteristic;)Z");
1542     if (!jni_mid_writeCharacteristic)
1543     {
1544         OIC_LOG(ERROR, TAG, "jni_mid_writeCharacteristic is null");
1545         return CA_STATUS_FAILED;
1546     }
1547
1548     // call disconnect gatt method
1549     OIC_LOG(DEBUG, TAG, "CALL API - request to write gatt characteristic");
1550     jboolean ret = (jboolean)(*env)->CallBooleanMethod(env, bluetoothGatt,
1551                                                        jni_mid_writeCharacteristic,
1552                                                        gattCharacteristic);
1553     if (ret)
1554     {
1555         OIC_LOG(DEBUG, TAG, "writeCharacteristic success");
1556     }
1557     else
1558     {
1559         OIC_LOG(ERROR, TAG, "writeCharacteristic has failed");
1560         return CA_STATUS_FAILED;
1561     }
1562
1563     return CA_STATUS_OK;
1564 }
1565
1566 CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt)
1567 {
1568     VERIFY_NON_NULL(env, TAG, "env is null");
1569     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1570
1571     if (!CALEIsEnableBTAdapter(env))
1572     {
1573         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1574         return CA_STATUS_FAILED;
1575     }
1576
1577     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
1578     if (!jni_cid_BluetoothGatt)
1579     {
1580         OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
1581         return CA_STATUS_FAILED;
1582     }
1583
1584     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
1585     if (!jni_uuid)
1586     {
1587         OIC_LOG(ERROR, TAG, "jni_uuid is null");
1588         return CA_STATUS_FAILED;
1589     }
1590
1591     jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
1592     if (!jni_obj_GattCharacteristic)
1593     {
1594         OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
1595         return CA_STATUS_FAILED;
1596     }
1597
1598     OIC_LOG(DEBUG, TAG, "read characteristic method");
1599     jmethodID jni_mid_readCharacteristic = (*env)->GetMethodID(env, jni_cid_BluetoothGatt,
1600                                                                "readCharacteristic",
1601                                                                "(Landroid/bluetooth/"
1602                                                                "BluetoothGattCharacteristic;)Z");
1603     if (!jni_mid_readCharacteristic)
1604     {
1605         OIC_LOG(ERROR, TAG, "jni_mid_readCharacteristic is null");
1606         return CA_STATUS_FAILED;
1607     }
1608
1609     // call disconnect gatt method
1610     OIC_LOG(DEBUG, TAG, "CALL API - request to read gatt characteristic");
1611     jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_readCharacteristic,
1612                                              jni_obj_GattCharacteristic);
1613     if (ret)
1614     {
1615         OIC_LOG(DEBUG, TAG, "readCharacteristic success");
1616     }
1617     else
1618     {
1619         OIC_LOG(ERROR, TAG, "readCharacteristic has failed");
1620         return CA_STATUS_FAILED;
1621     }
1622
1623     return CA_STATUS_OK;
1624 }
1625
1626 CAResult_t CALEClientSetCharacteristicNotification(JNIEnv *env, jobject bluetoothGatt,
1627                                                    jobject characteristic)
1628 {
1629     VERIFY_NON_NULL(env, TAG, "env is null");
1630     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1631     VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
1632
1633     if (!CALEIsEnableBTAdapter(env))
1634     {
1635         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1636         return CA_ADAPTER_NOT_ENABLED;
1637     }
1638
1639     // get BluetoothGatt class
1640     OIC_LOG(DEBUG, TAG, "CALEClientSetCharacteristicNotification");
1641     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
1642     if (!jni_cid_BluetoothGatt)
1643     {
1644         OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
1645         return CA_STATUS_FAILED;
1646     }
1647
1648     // set Characteristic Notification
1649     jmethodID jni_mid_setNotification = (*env)->GetMethodID(env, jni_cid_BluetoothGatt,
1650                                                             "setCharacteristicNotification",
1651                                                             "(Landroid/bluetooth/"
1652                                                             "BluetoothGattCharacteristic;Z)Z");
1653     if (!jni_mid_setNotification)
1654     {
1655         OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
1656         return CA_STATUS_FAILED;
1657     }
1658
1659     jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_setNotification,
1660                                              characteristic, JNI_TRUE);
1661     if (JNI_TRUE == ret)
1662     {
1663         OIC_LOG(DEBUG, TAG, "CALL API - setCharacteristicNotification success");
1664     }
1665     else
1666     {
1667         OIC_LOG(ERROR, TAG, "CALL API - setCharacteristicNotification has failed");
1668         return CA_STATUS_FAILED;
1669     }
1670
1671     return CA_STATUS_OK;
1672 }
1673
1674 jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID)
1675 {
1676     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1677     VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
1678     VERIFY_NON_NULL_RET(characterUUID, TAG, "characterUUID is null", NULL);
1679
1680     if (!CALEIsEnableBTAdapter(env))
1681     {
1682         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1683         return NULL;
1684     }
1685
1686     // get BluetoothGatt class
1687     OIC_LOG(DEBUG, TAG, "CALEClientGetGattService");
1688     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
1689     if (!jni_cid_BluetoothGatt)
1690     {
1691         OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGatt is null");
1692         return NULL;
1693     }
1694
1695     jmethodID jni_mid_getService = (*env)->GetMethodID(
1696             env, jni_cid_BluetoothGatt, "getService",
1697             "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattService;");
1698     if (!jni_mid_getService)
1699     {
1700         OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
1701         return NULL;
1702     }
1703
1704     jobject jni_obj_service_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
1705     if (!jni_obj_service_uuid)
1706     {
1707         OIC_LOG(ERROR, TAG, "jni_obj_service_uuid is null");
1708         return NULL;
1709     }
1710
1711     // get bluetooth gatt service
1712     OIC_LOG(DEBUG, TAG, "request to get service");
1713     jobject jni_obj_gattService = (*env)->CallObjectMethod(env, bluetoothGatt, jni_mid_getService,
1714                                                            jni_obj_service_uuid);
1715     if (!jni_obj_gattService)
1716     {
1717         OIC_LOG(ERROR, TAG, "jni_obj_gattService is null");
1718         return NULL;
1719     }
1720
1721     // get bluetooth gatt service class
1722     jclass jni_cid_BluetoothGattService = (*env)->FindClass(
1723             env, "android/bluetooth/BluetoothGattService");
1724     if (!jni_cid_BluetoothGattService)
1725     {
1726         OIC_LOG(ERROR, TAG, "jni_cid_BluetoothGattService is null");
1727         return NULL;
1728     }
1729
1730     OIC_LOG(DEBUG, TAG, "get gatt getCharacteristic method");
1731     jmethodID jni_mid_getCharacteristic = (*env)->GetMethodID(env, jni_cid_BluetoothGattService,
1732                                                               "getCharacteristic",
1733                                                               "(Ljava/util/UUID;)"
1734                                                               "Landroid/bluetooth/"
1735                                                               "BluetoothGattCharacteristic;");
1736     if (!jni_mid_getCharacteristic)
1737     {
1738         OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null");
1739         return NULL;
1740     }
1741
1742     const char* uuid = (*env)->GetStringUTFChars(env, characterUUID, NULL);
1743     if (!uuid)
1744     {
1745         OIC_LOG(ERROR, TAG, "uuid is null");
1746         return NULL;
1747     }
1748
1749     jobject jni_obj_tx_uuid = CALEClientGetUUIDObject(env, uuid);
1750     if (!jni_obj_tx_uuid)
1751     {
1752         OIC_LOG(ERROR, TAG, "jni_obj_tx_uuid is null");
1753         (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
1754         return NULL;
1755     }
1756
1757     OIC_LOG(DEBUG, TAG, "request to get Characteristic");
1758     jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService,
1759                                                                   jni_mid_getCharacteristic,
1760                                                                   jni_obj_tx_uuid);
1761
1762     (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
1763     return jni_obj_GattCharacteristic;
1764 }
1765
1766 jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data)
1767 {
1768     OIC_LOG(DEBUG, TAG, "CALEClientCreateGattCharacteristic");
1769     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1770     VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
1771     VERIFY_NON_NULL_RET(data, TAG, "data is null", NULL);
1772
1773     if (!CALEIsEnableBTAdapter(env))
1774     {
1775         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1776         return NULL;
1777     }
1778
1779     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
1780     if (!jni_uuid)
1781     {
1782         OIC_LOG(ERROR, TAG, "jni_uuid is null");
1783         return NULL;
1784     }
1785
1786     jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
1787     if (!jni_obj_GattCharacteristic)
1788     {
1789         OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
1790         return NULL;
1791     }
1792
1793     jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth"
1794                                                             "/BluetoothGattCharacteristic");
1795     if (!jni_cid_BTGattCharacteristic)
1796     {
1797         OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
1798         return NULL;
1799     }
1800
1801     OIC_LOG(DEBUG, TAG, "set value in Characteristic");
1802     jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "setValue",
1803                                                      "([B)Z");
1804     if (!jni_mid_setValue)
1805     {
1806         OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
1807         return NULL;
1808     }
1809
1810     jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue,
1811                                              data);
1812     if (JNI_TRUE == ret)
1813     {
1814         OIC_LOG(DEBUG, TAG, "the locally stored value has been set");
1815     }
1816     else
1817     {
1818         OIC_LOG(ERROR, TAG, "the locally stored value hasn't been set");
1819         return NULL;
1820     }
1821
1822     // set Write Type
1823     jmethodID jni_mid_setWriteType = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic,
1824                                                          "setWriteType", "(I)V");
1825     if (!jni_mid_setWriteType)
1826     {
1827         OIC_LOG(ERROR, TAG, "jni_mid_setWriteType is null");
1828         return NULL;
1829     }
1830
1831     jfieldID jni_fid_no_response = (*env)->GetStaticFieldID(env, jni_cid_BTGattCharacteristic,
1832                                                             "WRITE_TYPE_NO_RESPONSE", "I");
1833     if (!jni_fid_no_response)
1834     {
1835         OIC_LOG(ERROR, TAG, "jni_fid_no_response is not available");
1836         return NULL;
1837     }
1838
1839     jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTGattCharacteristic,
1840                                                  jni_fid_no_response);
1841
1842     (*env)->CallVoidMethod(env, jni_obj_GattCharacteristic, jni_mid_setWriteType, jni_int_val);
1843
1844     return jni_obj_GattCharacteristic;
1845 }
1846
1847 jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteristic)
1848 {
1849     VERIFY_NON_NULL_RET(characteristic, TAG, "characteristic is null", NULL);
1850     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1851
1852     if (!CALEIsEnableBTAdapter(env))
1853     {
1854         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1855         return NULL;
1856     }
1857
1858     jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/"
1859                                                             "BluetoothGattCharacteristic");
1860     if (!jni_cid_BTGattCharacteristic)
1861     {
1862         OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
1863         return NULL;
1864     }
1865
1866     OIC_LOG(DEBUG, TAG, "get value in Characteristic");
1867     jmethodID jni_mid_getValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "getValue",
1868                                                      "()[B");
1869     if (!jni_mid_getValue)
1870     {
1871         OIC_LOG(ERROR, TAG, "jni_mid_getValue is null");
1872         return NULL;
1873     }
1874
1875     jbyteArray jni_obj_data_array = (*env)->CallObjectMethod(env, characteristic,
1876                                                              jni_mid_getValue);
1877     return jni_obj_data_array;
1878 }
1879
1880 CAResult_t CALEClientCreateUUIDList()
1881 {
1882     if (!g_jvm)
1883     {
1884         OIC_LOG(ERROR, TAG, "g_jvm is null");
1885         return CA_STATUS_FAILED;
1886     }
1887
1888     bool isAttached = false;
1889     JNIEnv* env;
1890     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1891     if (JNI_OK != res)
1892     {
1893         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1894         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1895
1896         if (JNI_OK != res)
1897         {
1898             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1899             return CA_STATUS_FAILED;
1900         }
1901         isAttached = true;
1902     }
1903
1904     // create new object array
1905     jclass jni_cid_uuid_list = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1906     if (!jni_cid_uuid_list)
1907     {
1908         OIC_LOG(ERROR, TAG, "jni_cid_uuid_list is null");
1909         goto error_exit;
1910     }
1911
1912     jobjectArray jni_obj_uuid_list = (jobjectArray)(*env)->NewObjectArray(env, 1,
1913                                                                           jni_cid_uuid_list, NULL);
1914     if (!jni_obj_uuid_list)
1915     {
1916         OIC_LOG(ERROR, TAG, "jni_obj_uuid_list is null");
1917         goto error_exit;
1918     }
1919
1920     // make uuid list
1921     jobject jni_obj_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
1922     if (!jni_obj_uuid)
1923     {
1924         OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1925         goto error_exit;
1926     }
1927     (*env)->SetObjectArrayElement(env, jni_obj_uuid_list, 0, jni_obj_uuid);
1928
1929     g_uuidList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list);
1930
1931     if (isAttached)
1932     {
1933         (*g_jvm)->DetachCurrentThread(g_jvm);
1934     }
1935
1936     return CA_STATUS_OK;
1937
1938     // error label.
1939 error_exit:
1940
1941     if (isAttached)
1942     {
1943         (*g_jvm)->DetachCurrentThread(g_jvm);
1944     }
1945     return CA_STATUS_FAILED;
1946 }
1947
1948 CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt,
1949                                          jobject characteristic)
1950 {
1951     VERIFY_NON_NULL(env, TAG, "env is null");
1952     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1953     VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
1954
1955     if (!CALEIsEnableBTAdapter(env))
1956     {
1957         OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
1958         return CA_ADAPTER_NOT_ENABLED;
1959     }
1960
1961     OIC_LOG(DEBUG, TAG, "CALEClientSetUUIDToDescriptor");
1962     jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/"
1963                                                             "BluetoothGattCharacteristic");
1964     if (!jni_cid_BTGattCharacteristic)
1965     {
1966         OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
1967         return CA_STATUS_FAILED;
1968     }
1969
1970     OIC_LOG(DEBUG, TAG, "set value in Characteristic");
1971     jmethodID jni_mid_getDescriptor = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic,
1972                                                           "getDescriptor",
1973                                                           "(Ljava/util/UUID;)Landroid/bluetooth/"
1974                                                           "BluetoothGattDescriptor;");
1975     if (!jni_mid_getDescriptor)
1976     {
1977         OIC_LOG(ERROR, TAG, "jni_mid_getDescriptor is null");
1978         return CA_STATUS_FAILED;
1979     }
1980
1981     jobject jni_obj_cc_uuid = CALEClientGetUUIDObject(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID);
1982     if (!jni_obj_cc_uuid)
1983     {
1984         OIC_LOG(ERROR, TAG, "jni_obj_cc_uuid is null");
1985         return CA_STATUS_FAILED;
1986     }
1987
1988     OIC_LOG(DEBUG, TAG, "request to get descriptor");
1989     jobject jni_obj_descriptor = (*env)->CallObjectMethod(env, characteristic,
1990                                                           jni_mid_getDescriptor, jni_obj_cc_uuid);
1991     if (!jni_obj_descriptor)
1992     {
1993         OIC_LOG(ERROR, TAG, "jni_obj_descriptor is null");
1994         return CA_STATUS_FAILED;
1995     }
1996
1997     OIC_LOG(DEBUG, TAG, "set value in descriptor");
1998     jclass jni_cid_descriptor = (*env)->FindClass(env,
1999                                                   "android/bluetooth/BluetoothGattDescriptor");
2000     if (!jni_cid_descriptor)
2001     {
2002         OIC_LOG(ERROR, TAG, "jni_cid_descriptor is null");
2003         return CA_STATUS_FAILED;
2004     }
2005
2006     jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_descriptor, "setValue", "([B)Z");
2007     if (!jni_mid_setValue)
2008     {
2009         OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2010         return CA_STATUS_FAILED;
2011     }
2012
2013     jfieldID jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor,
2014                                                           "ENABLE_NOTIFICATION_VALUE", "[B");
2015     if (!jni_fid_NotiValue)
2016     {
2017         OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null");
2018         return CA_STATUS_FAILED;
2019     }
2020
2021     OIC_LOG(DEBUG, TAG, "get ENABLE_NOTIFICATION_VALUE");
2022
2023     jboolean jni_setvalue = (*env)->CallBooleanMethod(
2024             env, jni_obj_descriptor, jni_mid_setValue,
2025             (jbyteArray)(*env)->GetStaticObjectField(env, jni_cid_descriptor, jni_fid_NotiValue));
2026     if (jni_setvalue)
2027     {
2028         OIC_LOG(DEBUG, TAG, "setValue success");
2029     }
2030     else
2031     {
2032         OIC_LOG(ERROR, TAG, "setValue has failed");
2033         return CA_STATUS_FAILED;
2034     }
2035
2036     jclass jni_cid_gatt = (*env)->FindClass(env, "android/bluetooth/BluetoothGatt");
2037     if (!jni_cid_gatt)
2038     {
2039         OIC_LOG(ERROR, TAG, "jni_cid_gatt is null");
2040         return CA_STATUS_FAILED;
2041     }
2042
2043     OIC_LOG(DEBUG, TAG, "write Descriptor in gatt object");
2044     jmethodID jni_mid_writeDescriptor = (*env)->GetMethodID(env, jni_cid_gatt, "writeDescriptor",
2045                                                             "(Landroid/bluetooth/"
2046                                                             "BluetoothGattDescriptor;)Z");
2047     if (!jni_mid_writeDescriptor)
2048     {
2049         OIC_LOG(ERROR, TAG, "jni_mid_writeDescriptor is null");
2050         return CA_STATUS_FAILED;
2051     }
2052
2053     OIC_LOG(DEBUG, TAG, "request to write descriptor");
2054     jboolean jni_ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_writeDescriptor,
2055                                                  jni_obj_descriptor);
2056     if (jni_ret)
2057     {
2058         OIC_LOG(DEBUG, TAG, "writeDescriptor success");
2059     }
2060     else
2061     {
2062         OIC_LOG(ERROR, TAG, "writeDescriptor has failed");
2063         return CA_STATUS_FAILED;
2064     }
2065
2066     return CA_STATUS_OK;
2067 }
2068
2069 void CALEClientCreateScanDeviceList(JNIEnv *env)
2070 {
2071     OIC_LOG(DEBUG, TAG, "CALEClientCreateScanDeviceList");
2072     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
2073
2074     ca_mutex_lock(g_deviceListMutex);
2075     // create new object array
2076     if (g_deviceList == NULL)
2077     {
2078         OIC_LOG(DEBUG, TAG, "Create device list");
2079
2080         g_deviceList = u_arraylist_create();
2081     }
2082     ca_mutex_unlock(g_deviceListMutex);
2083 }
2084
2085 CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device)
2086 {
2087     OIC_LOG(DEBUG, TAG, "IN - CALEClientAddScanDeviceToList");
2088     VERIFY_NON_NULL(device, TAG, "device is null");
2089     VERIFY_NON_NULL(env, TAG, "env is null");
2090
2091     ca_mutex_lock(g_deviceListMutex);
2092
2093     if (!g_deviceList)
2094     {
2095         OIC_LOG(ERROR, TAG, "gdevice_list is null");
2096         ca_mutex_unlock(g_deviceListMutex);
2097         return CA_STATUS_FAILED;
2098     }
2099
2100     jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2101     if (!jni_remoteAddress)
2102     {
2103         OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2104         ca_mutex_unlock(g_deviceListMutex);
2105         return CA_STATUS_FAILED;
2106     }
2107
2108     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2109     if (!remoteAddress)
2110     {
2111         OIC_LOG(ERROR, TAG, "remoteAddress is null");
2112         ca_mutex_unlock(g_deviceListMutex);
2113         return CA_STATUS_FAILED;
2114     }
2115
2116     if (!CALEClientIsDeviceInScanDeviceList(env, remoteAddress))
2117     {
2118         jobject gdevice = (*env)->NewGlobalRef(env, device);
2119         u_arraylist_add(g_deviceList, gdevice);
2120         OIC_LOG(DEBUG, TAG, "Set Object to Array as Element");
2121     }
2122     (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2123
2124     ca_mutex_unlock(g_deviceListMutex);
2125
2126     OIC_LOG(DEBUG, TAG, "OUT - CALEClientAddScanDeviceToList");
2127     return CA_STATUS_OK;
2128 }
2129
2130 bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress)
2131 {
2132     OIC_LOG(DEBUG, TAG, "IN - CALEClientIsDeviceInScanDeviceList");
2133     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2134     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2135
2136     if (!g_deviceList)
2137     {
2138         OIC_LOG(DEBUG, TAG, "g_deviceList is null");
2139         return true;
2140     }
2141
2142     uint32_t length = u_arraylist_length(g_deviceList);
2143     for (uint32_t index = 0; index < length; index++)
2144     {
2145         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2146         if (!jarrayObj)
2147         {
2148             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2149             return true;
2150         }
2151
2152         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2153         if (!jni_setAddress)
2154         {
2155             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2156             return true;
2157         }
2158
2159         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2160         if (!setAddress)
2161         {
2162             OIC_LOG(ERROR, TAG, "setAddress is null");
2163             return true;
2164         }
2165
2166         if (!strcmp(remoteAddress, setAddress))
2167         {
2168             OIC_LOG(DEBUG, TAG, "the device is already set");
2169             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2170             return true;
2171         }
2172
2173         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2174     }
2175
2176     OIC_LOG(DEBUG, TAG, "OUT - CALEClientIsDeviceInScanDeviceList");
2177     OIC_LOG(DEBUG, TAG, "there are no the device in list. we can add");
2178
2179     return false;
2180 }
2181
2182 CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env)
2183 {
2184     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices");
2185     VERIFY_NON_NULL(env, TAG, "env is null");
2186
2187     ca_mutex_lock(g_deviceListMutex);
2188
2189     if (!g_deviceList)
2190     {
2191         OIC_LOG(ERROR, TAG, "g_deviceList is null");
2192         ca_mutex_unlock(g_deviceListMutex);
2193         return CA_STATUS_FAILED;
2194     }
2195
2196     uint32_t length = u_arraylist_length(g_deviceList);
2197     for (uint32_t index = 0; index < length; index++)
2198     {
2199         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2200         if (!jarrayObj)
2201         {
2202             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2203             continue;
2204         }
2205         (*env)->DeleteGlobalRef(env, jarrayObj);
2206     }
2207
2208     OICFree(g_deviceList);
2209     g_deviceList = NULL;
2210
2211     ca_mutex_unlock(g_deviceListMutex);
2212     return CA_STATUS_OK;
2213 }
2214
2215 CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address)
2216 {
2217     OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceInScanDeviceList");
2218     VERIFY_NON_NULL(address, TAG, "address is null");
2219     VERIFY_NON_NULL(env, TAG, "env is null");
2220
2221     ca_mutex_lock(g_deviceListMutex);
2222
2223     if (!g_deviceList)
2224     {
2225         OIC_LOG(ERROR, TAG, "g_deviceList is null");
2226         ca_mutex_unlock(g_deviceListMutex);
2227         return CA_STATUS_FAILED;
2228     }
2229
2230     uint32_t length = u_arraylist_length(g_deviceList);
2231     for (uint32_t index = 0; index < length; index++)
2232     {
2233         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2234         if (!jarrayObj)
2235         {
2236             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2237             ca_mutex_unlock(g_deviceListMutex);
2238             return CA_STATUS_FAILED;
2239         }
2240
2241         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2242         if (!jni_setAddress)
2243         {
2244             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2245             ca_mutex_unlock(g_deviceListMutex);
2246             return CA_STATUS_FAILED;
2247         }
2248
2249         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2250         if (!setAddress)
2251         {
2252             OIC_LOG(ERROR, TAG, "setAddress is null");
2253             ca_mutex_unlock(g_deviceListMutex);
2254             return CA_STATUS_FAILED;
2255         }
2256
2257         const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
2258         if (!remoteAddress)
2259         {
2260             OIC_LOG(ERROR, TAG, "remoteAddress is null");
2261             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2262             ca_mutex_unlock(g_deviceListMutex);
2263             return CA_STATUS_FAILED;
2264         }
2265
2266         if (!strcmp(setAddress, remoteAddress))
2267         {
2268             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2269             (*env)->DeleteGlobalRef(env, jarrayObj);
2270             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2271             (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2272
2273             CALEClientReorderingList(index, g_deviceList);
2274             ca_mutex_unlock(g_deviceListMutex);
2275             return CA_STATUS_OK;
2276         }
2277         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2278         (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2279     }
2280
2281     ca_mutex_unlock(g_deviceListMutex);
2282     OIC_LOG(DEBUG, TAG, "There are no object in the device list");
2283
2284     return CA_STATUS_OK;
2285 }
2286
2287 /**
2288  * Gatt Object List
2289  */
2290
2291 CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt)
2292 {
2293     OIC_LOG(DEBUG, TAG, "CALEClientAddGattobjToList");
2294     VERIFY_NON_NULL(env, TAG, "env is null");
2295     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2296
2297     ca_mutex_lock(g_gattObjectMutex);
2298
2299     jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
2300     if (!jni_remoteAddress)
2301     {
2302         OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2303         ca_mutex_unlock(g_gattObjectMutex);
2304         return CA_STATUS_FAILED;
2305     }
2306
2307     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2308     if (!remoteAddress)
2309     {
2310         OIC_LOG(ERROR, TAG, "remoteAddress is null");
2311         ca_mutex_unlock(g_gattObjectMutex);
2312         return CA_STATUS_FAILED;
2313     }
2314
2315     if (!CALEClientIsGattObjInList(env, remoteAddress))
2316     {
2317         jobject newGatt = (*env)->NewGlobalRef(env, gatt);
2318         u_arraylist_add(g_gattObjectList, newGatt);
2319         OIC_LOG(DEBUG, TAG, "Set GATT Object to Array as Element");
2320     }
2321
2322     (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2323     ca_mutex_unlock(g_gattObjectMutex);
2324     return CA_STATUS_OK;
2325 }
2326
2327 bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress)
2328 {
2329     OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList");
2330     VERIFY_NON_NULL(env, TAG, "env is null");
2331     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2332
2333     uint32_t length = u_arraylist_length(g_gattObjectList);
2334     for (uint32_t index = 0; index < length; index++)
2335     {
2336
2337         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2338         if (!jarrayObj)
2339         {
2340             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2341             return true;
2342         }
2343
2344         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2345         if (!jni_setAddress)
2346         {
2347             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2348             return true;
2349         }
2350
2351         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2352         if (!setAddress)
2353         {
2354             OIC_LOG(ERROR, TAG, "setAddress is null");
2355             return true;
2356         }
2357
2358         if (!strcmp(remoteAddress, setAddress))
2359         {
2360             OIC_LOG(DEBUG, TAG, "the device is already set");
2361             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2362             return true;
2363         }
2364         else
2365         {
2366             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2367             continue;
2368         }
2369     }
2370
2371     OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added");
2372     return false;
2373 }
2374
2375 jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress)
2376 {
2377     OIC_LOG(DEBUG, TAG, "CALEClientGetGattObjInList");
2378     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2379     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
2380
2381     ca_mutex_lock(g_gattObjectMutex);
2382     uint32_t length = u_arraylist_length(g_gattObjectList);
2383     for (uint32_t index = 0; index < length; index++)
2384     {
2385         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2386         if (!jarrayObj)
2387         {
2388             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2389             ca_mutex_unlock(g_gattObjectMutex);
2390             return NULL;
2391         }
2392
2393         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2394         if (!jni_setAddress)
2395         {
2396             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2397             ca_mutex_unlock(g_gattObjectMutex);
2398             return NULL;
2399         }
2400
2401         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2402         if (!setAddress)
2403         {
2404             OIC_LOG(ERROR, TAG, "setAddress is null");
2405             ca_mutex_unlock(g_gattObjectMutex);
2406             return NULL;
2407         }
2408
2409         if (!strcmp(remoteAddress, setAddress))
2410         {
2411             OIC_LOG(DEBUG, TAG, "the device is already set");
2412             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2413             ca_mutex_unlock(g_gattObjectMutex);
2414             return jarrayObj;
2415         }
2416         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2417     }
2418
2419     ca_mutex_unlock(g_gattObjectMutex);
2420     OIC_LOG(DEBUG, TAG, "There are no the gatt object in list");
2421     return NULL;
2422 }
2423
2424 CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env)
2425 {
2426     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs");
2427     VERIFY_NON_NULL(env, TAG, "env is null");
2428
2429     ca_mutex_lock(g_gattObjectMutex);
2430     if (!g_gattObjectList)
2431     {
2432         OIC_LOG(ERROR, TAG, "g_gattObjectList is null");
2433         ca_mutex_unlock(g_gattObjectMutex);
2434         return CA_STATUS_FAILED;
2435     }
2436
2437     uint32_t length = u_arraylist_length(g_gattObjectList);
2438     for (uint32_t index = 0; index < length; index++)
2439     {
2440         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2441         if (!jarrayObj)
2442         {
2443             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2444             continue;
2445         }
2446         (*env)->DeleteGlobalRef(env, jarrayObj);
2447     }
2448
2449     OICFree(g_gattObjectList);
2450     g_gattObjectList = NULL;
2451     ca_mutex_unlock(g_gattObjectMutex);
2452     return CA_STATUS_OK;
2453 }
2454
2455 CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt)
2456 {
2457     OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObj");
2458     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2459     VERIFY_NON_NULL(env, TAG, "env is null");
2460
2461     ca_mutex_lock(g_gattObjectMutex);
2462     if (!g_gattObjectList)
2463     {
2464         OIC_LOG(ERROR, TAG, "g_gattObjectList is null");
2465         ca_mutex_unlock(g_gattObjectMutex);
2466         return CA_STATUS_FAILED;
2467     }
2468
2469     uint32_t length = u_arraylist_length(g_gattObjectList);
2470     for (uint32_t index = 0; index < length; index++)
2471     {
2472         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2473         if (!jarrayObj)
2474         {
2475             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2476             ca_mutex_unlock(g_gattObjectMutex);
2477             return CA_STATUS_FAILED;
2478         }
2479
2480         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2481         if (!jni_setAddress)
2482         {
2483             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2484             ca_mutex_unlock(g_gattObjectMutex);
2485             return CA_STATUS_FAILED;
2486         }
2487
2488         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2489         if (!setAddress)
2490         {
2491             OIC_LOG(ERROR, TAG, "setAddress is null");
2492             ca_mutex_unlock(g_gattObjectMutex);
2493             return CA_STATUS_FAILED;
2494         }
2495
2496         jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
2497         if (!jni_remoteAddress)
2498         {
2499             OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2500             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2501             ca_mutex_unlock(g_gattObjectMutex);
2502             return CA_STATUS_FAILED;
2503         }
2504
2505         const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2506         if (!remoteAddress)
2507         {
2508             OIC_LOG(ERROR, TAG, "remoteAddress is null");
2509             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2510             ca_mutex_unlock(g_gattObjectMutex);
2511             return CA_STATUS_FAILED;
2512         }
2513
2514         if (!strcmp(setAddress, remoteAddress))
2515         {
2516             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2517             (*env)->DeleteGlobalRef(env, jarrayObj);
2518             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2519             (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2520             ca_mutex_unlock(g_gattObjectMutex);
2521             return CALEClientReorderingList(index, g_gattObjectList);
2522         }
2523         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2524         (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2525     }
2526
2527     ca_mutex_unlock(g_gattObjectMutex);
2528     OIC_LOG(DEBUG, TAG, "there are no target object");
2529     return CA_STATUS_OK;
2530 }
2531
2532 CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr)
2533 {
2534     OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObjForAddr");
2535     VERIFY_NON_NULL(addr, TAG, "addr is null");
2536     VERIFY_NON_NULL(env, TAG, "env is null");
2537
2538     ca_mutex_lock(g_gattObjectMutex);
2539     if (!g_gattObjectList)
2540     {
2541         OIC_LOG(ERROR, TAG, "g_gattObjectList is null");
2542         ca_mutex_unlock(g_gattObjectMutex);
2543         return CA_STATUS_FAILED;
2544     }
2545
2546     uint32_t length = u_arraylist_length(g_gattObjectList);
2547     for (uint32_t index = 0; index < length; index++)
2548     {
2549         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2550         if (!jarrayObj)
2551         {
2552             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2553             ca_mutex_unlock(g_gattObjectMutex);
2554             return CA_STATUS_FAILED;
2555         }
2556
2557         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2558         if (!jni_setAddress)
2559         {
2560             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2561             ca_mutex_unlock(g_gattObjectMutex);
2562             return CA_STATUS_FAILED;
2563         }
2564
2565         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2566         if (!setAddress)
2567         {
2568             OIC_LOG(ERROR, TAG, "setAddress is null");
2569             ca_mutex_unlock(g_gattObjectMutex);
2570             return CA_STATUS_FAILED;
2571         }
2572
2573         const char* remoteAddress = (*env)->GetStringUTFChars(env, addr, NULL);
2574         if (!remoteAddress)
2575         {
2576             OIC_LOG(ERROR, TAG, "remoteAddress is null");
2577             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2578             ca_mutex_unlock(g_gattObjectMutex);
2579             return CA_STATUS_FAILED;
2580         }
2581
2582         if (!strcmp(setAddress, remoteAddress))
2583         {
2584             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2585             (*env)->DeleteGlobalRef(env, jarrayObj);
2586
2587             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2588             (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
2589             ca_mutex_unlock(g_gattObjectMutex);
2590             return CALEClientReorderingList(index, g_gattObjectList);
2591         }
2592         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2593         (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
2594     }
2595
2596     ca_mutex_unlock(g_gattObjectMutex);
2597     OIC_LOG(DEBUG, TAG, "there are no target object");
2598     return CA_STATUS_FAILED;
2599 }
2600
2601 /**
2602  * BT State List
2603  */
2604
2605 CAResult_t CALEClientUpdateDeviceState(const char* address, uint32_t connectedState,
2606                                        uint16_t notificationState, uint16_t sendState)
2607 {
2608     VERIFY_NON_NULL(address, TAG, "address is null");
2609
2610     CALEState_t *newstate = (CALEState_t*) OICMalloc(sizeof(CALEState_t));
2611     if (!newstate)
2612     {
2613         OIC_LOG(ERROR, TAG, "out of memory");
2614         return CA_MEMORY_ALLOC_FAILED;
2615     }
2616
2617     if (strlen(address) > CA_MACADDR_SIZE)
2618     {
2619         OIC_LOG(ERROR, TAG, "address is not proper");
2620         OICFree(newstate);
2621         return CA_STATUS_FAILED;
2622     }
2623
2624     OICStrcpy(newstate->address, sizeof(newstate->address), address);
2625     newstate->connectedState = connectedState;
2626     newstate->notificationState = notificationState;
2627     newstate->sendState = sendState;
2628     return CALEClientAddDeviceStateToList(newstate);
2629 }
2630
2631 CAResult_t CALEClientAddDeviceStateToList(CALEState_t* state)
2632 {
2633     VERIFY_NON_NULL(state, TAG, "state is null");
2634
2635     ca_mutex_lock(g_deviceStateListMutex);
2636
2637     if (!g_deviceStateList)
2638     {
2639         OIC_LOG(ERROR, TAG, "gdevice_list is null");
2640         ca_mutex_unlock(g_deviceStateListMutex);
2641         return CA_STATUS_FAILED;
2642     }
2643
2644     if (CALEClientIsDeviceInList(state->address))
2645     {
2646         CALEState_t* curState = CALEClientGetStateInfo(state->address);
2647         if(!curState)
2648         {
2649             OIC_LOG(ERROR, TAG, "curState is null");
2650             ca_mutex_unlock(g_deviceStateListMutex);
2651             return CA_STATUS_FAILED;
2652         }
2653
2654         if (STATE_CHARACTER_NO_CHANGE == state->notificationState)
2655         {
2656             state->notificationState = curState->notificationState;
2657         }
2658
2659         // delete previous state for update new state
2660         CAResult_t res = CALEClientRemoveDeviceState(state->address);
2661         if (CA_STATUS_OK != res)
2662         {
2663             OIC_LOG(ERROR, TAG, "CALEClientRemoveDeviceState has failed");
2664             ca_mutex_unlock(g_deviceStateListMutex);
2665             return res;
2666         }
2667     }
2668     u_arraylist_add(g_deviceStateList, state); // update new state
2669     OIC_LOG_V(DEBUG, TAG, "Set State Info to List : %d, %d",
2670               state->connectedState, state->notificationState);
2671
2672     ca_mutex_unlock(g_deviceStateListMutex);
2673     return CA_STATUS_OK;
2674 }
2675
2676 bool CALEClientIsDeviceInList(const char* remoteAddress)
2677 {
2678     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
2679
2680     if (!g_deviceStateList)
2681     {
2682         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2683         return false;
2684     }
2685
2686     uint32_t length = u_arraylist_length(g_deviceStateList);
2687     for (uint32_t index = 0; index < length; index++)
2688     {
2689         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2690         if (!state)
2691         {
2692             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2693             return false;
2694         }
2695
2696         if (!strcmp(remoteAddress, state->address))
2697         {
2698             OIC_LOG(DEBUG, TAG, "the device is already set");
2699             return true;
2700         }
2701         else
2702         {
2703             continue;
2704         }
2705     }
2706
2707     OIC_LOG(DEBUG, TAG, "there are no the device in list.");
2708     return false;
2709 }
2710
2711 CAResult_t CALEClientRemoveAllDeviceState()
2712 {
2713     OIC_LOG(DEBUG, TAG, "CALENativeRemoveAllDevices");
2714
2715     ca_mutex_lock(g_deviceStateListMutex);
2716     if (!g_deviceStateList)
2717     {
2718         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2719         ca_mutex_unlock(g_deviceStateListMutex);
2720         return CA_STATUS_FAILED;
2721     }
2722
2723     uint32_t length = u_arraylist_length(g_deviceStateList);
2724     for (uint32_t index = 0; index < length; index++)
2725     {
2726         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2727         if (!state)
2728         {
2729             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2730             continue;
2731         }
2732         OICFree(state);
2733     }
2734
2735     OICFree(g_deviceStateList);
2736     g_deviceStateList = NULL;
2737     ca_mutex_unlock(g_deviceStateListMutex);
2738
2739     return CA_STATUS_OK;
2740 }
2741
2742 CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress)
2743 {
2744     OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceState");
2745     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
2746
2747     if (!g_deviceStateList)
2748     {
2749         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2750         return CA_STATUS_FAILED;
2751     }
2752
2753     uint32_t length = u_arraylist_length(g_deviceStateList);
2754     for (uint32_t index = 0; index < length; index++)
2755     {
2756         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2757         if (!state)
2758         {
2759             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2760             continue;
2761         }
2762
2763         if (!strcmp(state->address, remoteAddress))
2764         {
2765             OIC_LOG_V(DEBUG, TAG, "remove state : %s", remoteAddress);
2766             OICFree(state);
2767
2768             CAResult_t res = CALEClientReorderingList(index, g_deviceStateList);
2769             if(CA_STATUS_OK != res)
2770             {
2771                 OIC_LOG(ERROR, TAG, "CALEClientReorderingList has failed");
2772                 return res;
2773             }
2774             return CA_STATUS_OK;
2775         }
2776     }
2777
2778     return CA_STATUS_FAILED;
2779 }
2780
2781 CALEState_t* CALEClientGetStateInfo(const char* remoteAddress)
2782 {
2783     OIC_LOG(DEBUG, TAG, "CALEClientGetStateInfo");
2784     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
2785
2786     if (!g_deviceStateList)
2787     {
2788         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2789         return NULL;
2790     }
2791
2792     uint32_t length = u_arraylist_length(g_deviceStateList);
2793     for (uint32_t index = 0; index < length; index++)
2794     {
2795         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2796         if (!state)
2797         {
2798             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2799             continue;
2800         }
2801
2802         if (!strcmp(state->address, remoteAddress))
2803         {
2804             OIC_LOG_V(DEBUG, TAG, "get state : %s", remoteAddress);
2805             return state;
2806         }
2807     }
2808     return NULL;
2809 }
2810
2811 bool CALEClientIsConnectedDevice(const char* remoteAddress)
2812 {
2813     OIC_LOG(DEBUG, TAG, "CALEClientIsConnectedDevice");
2814     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
2815
2816     ca_mutex_lock(g_deviceStateListMutex);
2817     if (!g_deviceStateList)
2818     {
2819         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2820         ca_mutex_unlock(g_deviceStateListMutex);
2821         return false;
2822     }
2823
2824     uint32_t length = u_arraylist_length(g_deviceStateList);
2825     for (uint32_t index = 0; index < length; index++)
2826     {
2827         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2828         if (!state)
2829         {
2830             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2831             continue;
2832         }
2833
2834         if (!strcmp(state->address, remoteAddress))
2835         {
2836             OIC_LOG(DEBUG, TAG, "check whether it is connected or not");
2837
2838             if (STATE_CONNECTED == state->connectedState)
2839             {
2840                 ca_mutex_unlock(g_deviceStateListMutex);
2841                 return true;
2842             }
2843             else
2844             {
2845                 ca_mutex_unlock(g_deviceStateListMutex);
2846                 return false;
2847             }
2848         }
2849     }
2850     ca_mutex_unlock(g_deviceStateListMutex);
2851     return false;
2852 }
2853
2854 bool CALEClientIsSetCharacteristic(const char* remoteAddress)
2855 {
2856     OIC_LOG(DEBUG, TAG, "CALEClientIsSetCharacteristic");
2857     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
2858
2859     ca_mutex_lock(g_deviceStateListMutex);
2860     if (!g_deviceStateList)
2861     {
2862         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2863         ca_mutex_unlock(g_deviceStateListMutex);
2864         return false;
2865     }
2866
2867     uint32_t length = u_arraylist_length(g_deviceStateList);
2868     for (uint32_t index = 0; index < length; index++)
2869     {
2870         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2871         if (!state)
2872         {
2873             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2874             continue;
2875         }
2876
2877         if (!strcmp(state->address, remoteAddress))
2878         {
2879             OIC_LOG_V(DEBUG, TAG, "check whether it was set or not:%d", state->notificationState);
2880
2881             if (STATE_CHARACTER_SET == state->notificationState)
2882             {
2883                 ca_mutex_unlock(g_deviceStateListMutex);
2884                 return true;
2885             }
2886             else
2887             {
2888                 ca_mutex_unlock(g_deviceStateListMutex);
2889                 return false;
2890             }
2891         }
2892     }
2893
2894     ca_mutex_unlock(g_deviceStateListMutex);
2895     return false;
2896 }
2897
2898 void CALEClientCreateDeviceList()
2899 {
2900     OIC_LOG(DEBUG, TAG, "CALEClientCreateDeviceList");
2901
2902     // create new object array
2903     if (!g_gattObjectList)
2904     {
2905         OIC_LOG(DEBUG, TAG, "Create g_gattObjectList");
2906
2907         g_gattObjectList = u_arraylist_create();
2908     }
2909
2910     if (!g_deviceStateList)
2911     {
2912         OIC_LOG(DEBUG, TAG, "Create g_deviceStateList");
2913
2914         g_deviceStateList = u_arraylist_create();
2915     }
2916
2917     if (!g_deviceList)
2918     {
2919         OIC_LOG(DEBUG, TAG, "Create g_deviceList");
2920
2921         g_deviceList = u_arraylist_create();
2922     }
2923 }
2924
2925 CAResult_t CALEClientReorderingList(uint32_t index, u_arraylist_t *list)
2926 {
2927     if (!list)
2928     {
2929         OIC_LOG(ERROR, TAG, "list is null");
2930         return CA_STATUS_FAILED;
2931     }
2932
2933     if (index >= list->length)
2934     {
2935         OIC_LOG(ERROR, TAG, "index is not available");
2936         return CA_STATUS_FAILED;
2937     }
2938
2939     if (index < list->length - 1)
2940     {
2941         memmove(&list->data[index], &list->data[index + 1],
2942                 (list->length - index - 1) * sizeof(void *));
2943     }
2944
2945     list->size--;
2946     list->length--;
2947
2948     return CA_STATUS_OK;
2949 }
2950
2951 /**
2952  * Check Sent Count for remove g_sendBuffer
2953  */
2954 void CALEClientUpdateSendCnt(JNIEnv *env)
2955 {
2956     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
2957     // mutex lock
2958     ca_mutex_lock(g_threadMutex);
2959
2960     g_currentSentCnt++;
2961
2962     if (g_targetCnt <= g_currentSentCnt)
2963     {
2964         g_targetCnt = 0;
2965         g_currentSentCnt = 0;
2966
2967         if (g_sendBuffer)
2968         {
2969             (*env)->DeleteGlobalRef(env, g_sendBuffer);
2970             g_sendBuffer = NULL;
2971         }
2972         // notity the thread
2973         ca_cond_signal(g_threadCond);
2974         CALEClientSetSendFinishFlag(true);
2975         OIC_LOG(DEBUG, TAG, "set signal for send data");
2976     }
2977     // mutex unlock
2978     ca_mutex_unlock(g_threadMutex);
2979 }
2980
2981 CAResult_t CALEClientInitGattMutexVaraibles()
2982 {
2983     OIC_LOG(DEBUG, TAG, "IN");
2984
2985     if (NULL == g_bleReqRespClientCbMutex)
2986     {
2987         g_bleReqRespClientCbMutex = ca_mutex_new();
2988         if (NULL == g_bleReqRespClientCbMutex)
2989         {
2990             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2991             return CA_STATUS_FAILED;
2992         }
2993     }
2994
2995     if (NULL == g_bleServerBDAddressMutex)
2996     {
2997         g_bleServerBDAddressMutex = ca_mutex_new();
2998         if (NULL == g_bleServerBDAddressMutex)
2999         {
3000             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3001             return CA_STATUS_FAILED;
3002         }
3003     }
3004
3005     if (NULL == g_threadMutex)
3006     {
3007         g_threadMutex = ca_mutex_new();
3008         if (NULL == g_threadMutex)
3009         {
3010             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3011             return CA_STATUS_FAILED;
3012         }
3013     }
3014
3015     if (NULL == g_threadSendMutex)
3016     {
3017         g_threadSendMutex = ca_mutex_new();
3018         if (NULL == g_threadSendMutex)
3019         {
3020             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3021             return CA_STATUS_FAILED;
3022         }
3023     }
3024
3025     if (NULL == g_threadSendCBMutex)
3026     {
3027         g_threadSendCBMutex = ca_mutex_new();
3028         if (NULL == g_threadSendCBMutex)
3029         {
3030             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3031             return CA_STATUS_FAILED;
3032         }
3033     }
3034
3035     if (NULL == g_deviceListMutex)
3036     {
3037         g_deviceListMutex = ca_mutex_new();
3038         if (NULL == g_deviceListMutex)
3039         {
3040             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3041             return CA_STATUS_FAILED;
3042         }
3043     }
3044
3045     if (NULL == g_gattObjectMutex)
3046     {
3047         g_gattObjectMutex = ca_mutex_new();
3048         if (NULL == g_gattObjectMutex)
3049         {
3050             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3051             return CA_STATUS_FAILED;
3052         }
3053     }
3054
3055     if (NULL == g_deviceStateListMutex)
3056     {
3057         g_deviceStateListMutex = ca_mutex_new();
3058         if (NULL == g_deviceStateListMutex)
3059         {
3060             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3061             return CA_STATUS_FAILED;
3062         }
3063     }
3064
3065     if (NULL == g_SendFinishMutex)
3066     {
3067         g_SendFinishMutex = ca_mutex_new();
3068         if (NULL == g_SendFinishMutex)
3069         {
3070             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3071             return CA_STATUS_FAILED;
3072         }
3073     }
3074
3075     if (NULL == g_writeCharacteristicCBMutex)
3076     {
3077         g_writeCharacteristicCBMutex = ca_mutex_new();
3078         if (NULL == g_writeCharacteristicCBMutex)
3079         {
3080             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3081             return CA_STATUS_FAILED;
3082         }
3083     }
3084
3085     if (NULL == g_theSendRequestMutex)
3086     {
3087         g_theSendRequestMutex = ca_mutex_new();
3088         if (NULL == g_theSendRequestMutex)
3089         {
3090             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3091             return CA_STATUS_FAILED;
3092         }
3093     }
3094
3095     OIC_LOG(DEBUG, TAG, "OUT");
3096     return CA_STATUS_OK;
3097 }
3098
3099 void CALEClientTerminateGattMutexVariables()
3100 {
3101     OIC_LOG(DEBUG, TAG, "IN");
3102
3103     ca_mutex_free(g_bleReqRespClientCbMutex);
3104     g_bleReqRespClientCbMutex = NULL;
3105
3106     ca_mutex_free(g_bleServerBDAddressMutex);
3107     g_bleServerBDAddressMutex = NULL;
3108
3109     ca_mutex_free(g_threadMutex);
3110     g_threadMutex = NULL;
3111
3112     ca_mutex_free(g_threadSendMutex);
3113     g_threadSendMutex = NULL;
3114
3115     ca_mutex_free(g_threadSendCBMutex);
3116     g_threadSendCBMutex = NULL;
3117
3118     ca_mutex_free(g_deviceListMutex);
3119     g_deviceListMutex = NULL;
3120
3121     ca_mutex_free(g_SendFinishMutex);
3122     g_SendFinishMutex = NULL;
3123
3124     ca_mutex_free(g_writeCharacteristicCBMutex);
3125     g_writeCharacteristicCBMutex = NULL;
3126
3127     ca_mutex_free(g_theSendRequestMutex);
3128     g_theSendRequestMutex = NULL;
3129
3130     OIC_LOG(DEBUG, TAG, "OUT");
3131 }
3132
3133 void CALEClientSetSendFinishFlag(bool flag)
3134 {
3135     OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag);
3136
3137     ca_mutex_lock(g_SendFinishMutex);
3138     g_isFinishedSendData = flag;
3139     ca_mutex_unlock(g_SendFinishMutex);
3140 }
3141
3142 void CALEClientSetWriteCharacteristicCBFlag(bool flag)
3143 {
3144     OIC_LOG_V(DEBUG, TAG, "g_isReceivedWriteCB is %d", flag);
3145
3146     ca_mutex_lock(g_writeCharacteristicCBMutex);
3147     g_isReceivedWriteCB = flag;
3148     ca_mutex_unlock(g_writeCharacteristicCBMutex);
3149 }
3150
3151 void CALEClientSetTheSendRequestFlag(bool flag)
3152 {
3153     OIC_LOG_V(DEBUG, TAG, "g_isRequestedSend is %d", flag);
3154
3155     ca_mutex_lock(g_theSendRequestMutex);
3156     g_isRequestedSend = flag;
3157     ca_mutex_unlock(g_theSendRequestMutex);
3158 }
3159
3160 /**
3161  * adapter common
3162  */
3163
3164 CAResult_t CAStartBLEGattClient()
3165 {
3166     CAResult_t res = CALEClientStartMulticastServer();
3167     if (CA_STATUS_OK != res)
3168     {
3169         OIC_LOG(ERROR, TAG, "CALEClientStartMulticastServer has failed");
3170     }
3171     else
3172     {
3173         g_isStartedLEClient = true;
3174     }
3175
3176     return res;
3177 }
3178
3179 void CAStopBLEGattClient()
3180 {
3181     OIC_LOG(DEBUG, TAG, "CAStopBLEGattClient");
3182
3183     if (!g_jvm)
3184     {
3185         OIC_LOG(ERROR, TAG, "g_jvm is null");
3186         return;
3187     }
3188
3189     bool isAttached = false;
3190     JNIEnv* env;
3191     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
3192     if (JNI_OK != res)
3193     {
3194         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
3195         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
3196
3197         if (JNI_OK != res)
3198         {
3199             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
3200             return;
3201         }
3202         isAttached = true;
3203     }
3204
3205     CAResult_t ret = CALEClientDisconnectAll(env);
3206     if (CA_STATUS_OK != ret)
3207     {
3208         OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
3209     }
3210
3211     ret = CALEClientStopScan();
3212     if(CA_STATUS_OK != ret)
3213     {
3214         OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
3215     }
3216
3217     ca_cond_signal(g_threadCond);
3218     ca_cond_signal(g_threadSendCond);
3219     g_isStartedLEClient = false;
3220
3221     if (isAttached)
3222     {
3223         (*g_jvm)->DetachCurrentThread(g_jvm);
3224     }
3225
3226 }
3227
3228 void CATerminateBLEGattClient()
3229 {
3230     OIC_LOG(DEBUG, TAG, "Terminate GATT Client");
3231     CALEClientTerminate();
3232 }
3233
3234 CAResult_t  CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const char  *data,
3235                                                 const uint32_t dataLen, CALETransferType_t type,
3236                                                 const int32_t position)
3237 {
3238     OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage");
3239     VERIFY_NON_NULL(data, TAG, "data is null");
3240     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
3241
3242     return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
3243 }
3244
3245 CAResult_t CAUpdateCharacteristicsToAllGattServers(const char *data, uint32_t dataLen)
3246 {
3247     OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
3248     VERIFY_NON_NULL(data, TAG, "data is null");
3249
3250     return CALEClientSendMulticastMessage(data, dataLen);
3251 }
3252
3253 void CASetBLEReqRespClientCallback(CABLEClientDataReceivedCallback callback)
3254 {
3255     OIC_LOG(DEBUG, TAG, "IN");
3256
3257     ca_mutex_lock(g_bleReqRespClientCbMutex);
3258     g_CABLEClientDataReceivedCallback = callback;
3259     ca_mutex_unlock(g_bleReqRespClientCbMutex);
3260
3261     OIC_LOG(DEBUG, TAG, "OUT");
3262 }
3263
3264 void CASetBleClientThreadPoolHandle(ca_thread_pool_t handle)
3265 {
3266     OIC_LOG(DEBUG, TAG, "IN");
3267
3268     CALEClientInitialize(handle);
3269
3270     OIC_LOG(DEBUG, TAG, "OUT");
3271 }
3272
3273 CAResult_t CAGetLEAddress(char **local_address)
3274 {
3275     OIC_LOG(DEBUG, TAG, "IN");
3276
3277     VERIFY_NON_NULL(local_address, TAG, "local_address is null");
3278     CAResult_t res = CALEClientGetInterfaceInfo(local_address);
3279     if (CA_STATUS_OK != res)
3280     {
3281         OIC_LOG(INFO, TAG, "it didn't get local address");
3282     }
3283
3284     OIC_LOG(DEBUG, TAG, "OUT");
3285     return CA_STATUS_OK;
3286 }
3287
3288 JNIEXPORT void JNICALL
3289 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
3290                                                                     jobject callback)
3291 {
3292     OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
3293     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3294     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
3295
3296     g_leScanCallback = (*env)->NewGlobalRef(env, callback);
3297 }
3298
3299 JNIEXPORT void JNICALL
3300 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
3301                                                                   jobject callback)
3302 {
3303     OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
3304     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3305     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
3306
3307     g_leGattCallback = (*env)->NewGlobalRef(env, callback);
3308 }
3309
3310 JNIEXPORT void JNICALL
3311 Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
3312                                                            jobject device, jint rssi,
3313                                                            jbyteArray scanRecord)
3314 {
3315     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3316     VERIFY_NON_NULL_VOID(device, TAG, "device is null");
3317
3318     CAResult_t res = CALEClientAddScanDeviceToList(env, device);
3319     if (CA_STATUS_OK != res)
3320     {
3321         OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
3322     }
3323 }
3324
3325 /*
3326  * Class:     org_iotivity_ca_jar_caleinterface
3327  * Method:    CALeGattConnectionStateChangeCallback
3328  * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
3329  */
3330 JNIEXPORT void JNICALL
3331 Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
3332                                                                                 jobject obj,
3333                                                                                 jobject gatt,
3334                                                                                 jint status,
3335                                                                                 jint newstate)
3336 {
3337     OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
3338             newstate);
3339     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3340     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
3341
3342     if (GATT_SUCCESS == status && STATE_CONNECTED == newstate) // le connected
3343     {
3344         jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
3345         if (!jni_address)
3346         {
3347             goto error_exit;
3348         }
3349
3350         const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
3351         if (address)
3352         {
3353             CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED,
3354                                                          STATE_CHARACTER_NO_CHANGE,
3355                                                          STATE_SEND_NONE);
3356             if (CA_STATUS_OK != res)
3357             {
3358                 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
3359                 (*env)->ReleaseStringUTFChars(env, jni_address, address);
3360                 goto error_exit;
3361             }
3362             (*env)->ReleaseStringUTFChars(env, jni_address, address);
3363         }
3364
3365         CAResult_t res = CALEClientAddGattobjToList(env, gatt);
3366         if (CA_STATUS_OK != res)
3367         {
3368             OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
3369             goto error_exit;
3370         }
3371
3372         res = CALEClientDiscoverServices(env, gatt);
3373         if (CA_STATUS_OK != res)
3374         {
3375             OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
3376             goto error_exit;
3377         }
3378     }
3379     else if (GATT_SUCCESS == status && STATE_DISCONNECTED == newstate) // le disconnected
3380     {
3381         CAResult_t res = CALEClientStartScan();
3382         if (CA_STATUS_OK != res)
3383         {
3384             OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
3385         }
3386
3387         jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
3388         if (!jni_address)
3389         {
3390             OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
3391         }
3392
3393         const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
3394         if (address)
3395         {
3396             res = CALEClientUpdateDeviceState(address, STATE_DISCONNECTED,
3397                                               STATE_CHARACTER_NO_CHANGE,
3398                                               STATE_SEND_NONE);
3399             if (CA_STATUS_OK != res)
3400             {
3401                 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
3402             }
3403             (*env)->ReleaseStringUTFChars(env, jni_address, address);
3404         }
3405
3406         res = CALEClientGattClose(env, gatt);
3407         if (CA_STATUS_OK != res)
3408         {
3409             OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
3410         }
3411
3412         ca_cond_signal(g_threadSendCond);
3413     }
3414     else // error
3415     {
3416         // update state
3417         jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
3418         if (!jni_address)
3419         {
3420             OIC_LOG(ERROR, TAG, "jni_address is null");
3421             goto error_exit;
3422
3423         }
3424
3425         const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
3426         if (address)
3427         {
3428             CAResult_t res = CALEClientUpdateDeviceState(address, STATE_DISCONNECTED,
3429                                                          STATE_CHARACTER_NO_CHANGE,
3430                                                          STATE_SEND_FAILED);
3431             if (CA_STATUS_OK != res)
3432             {
3433                 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
3434             }
3435         }
3436         (*env)->ReleaseStringUTFChars(env, jni_address, address);
3437
3438         goto error_exit;
3439     }
3440     return;
3441
3442     // error label.
3443 error_exit:
3444
3445     CALEClientSendFinish(env, gatt);
3446     ca_cond_signal(g_threadSendCond);
3447     return;
3448 }
3449
3450 /*
3451  * Class:     org_iotivity_ca_jar_caleinterface
3452  * Method:    CALeGattServicesDiscoveredCallback
3453  * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
3454  */
3455 JNIEXPORT void JNICALL
3456 Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
3457                                                                              jobject obj,
3458                                                                              jobject gatt,
3459                                                                              jint status)
3460 {
3461     OIC_LOG_V(DEBUG, TAG, "CALeGattServicesDiscoveredCallback - status %d: ", status);
3462     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3463     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
3464
3465     if (0 != status) // discovery error
3466     {
3467         CALEClientSendFinish(env, gatt);
3468         ca_cond_signal(g_threadSendCond);
3469         return;
3470     }
3471
3472     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
3473     if (!jni_address)
3474     {
3475         CALEClientSendFinish(env, gatt);
3476         ca_cond_signal(g_threadSendCond);
3477         return;
3478     }
3479
3480     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
3481     if (!address)
3482     {
3483         CALEClientSendFinish(env, gatt);
3484         ca_cond_signal(g_threadSendCond);
3485         return;
3486     }
3487
3488     if (!CALEClientIsSetCharacteristic(address))
3489     {
3490         jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
3491         if (!jni_uuid)
3492         {
3493             OIC_LOG(ERROR, TAG, "jni_uuid is null");
3494             goto error_exit;
3495         }
3496
3497         jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
3498         if (!jni_obj_GattCharacteristic)
3499         {
3500             OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
3501             goto error_exit;
3502         }
3503
3504         CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
3505                                                                  jni_obj_GattCharacteristic);
3506         if (CA_STATUS_OK != res)
3507         {
3508             OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
3509             goto error_exit;
3510         }
3511
3512         res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
3513         if (CA_STATUS_OK != res)
3514         {
3515             OIC_LOG(ERROR, TAG, "CALEClientSetUUIDToDescriptor has failed");
3516             goto error_exit;
3517         }
3518
3519         res = CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
3520                                           STATE_SEND_NONE);
3521         if (CA_STATUS_OK != res)
3522         {
3523             OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
3524             goto error_exit;
3525         }
3526     }
3527     else
3528     {
3529         CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
3530         if (CA_STATUS_OK != res)
3531         {
3532             OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
3533             goto error_exit;
3534         }
3535     }
3536     (*env)->ReleaseStringUTFChars(env, jni_address, address);
3537     return;
3538
3539     // error label.
3540 error_exit:
3541     (*env)->ReleaseStringUTFChars(env, jni_address, address);
3542     CALEClientSendFinish(env, gatt);
3543     ca_cond_signal(g_threadSendCond);
3544     return;
3545 }
3546
3547 /*
3548  * Class:     org_iotivity_ca_jar_caleinterface
3549  * Method:    CALeGattCharacteristicReadCallback
3550  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
3551  */
3552 JNIEXPORT void JNICALL
3553 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicReadCallback(JNIEnv *env,
3554                                                                              jobject obj,
3555                                                                              jobject gatt,
3556                                                                              jobject characteristic,
3557                                                                              jbyteArray data,
3558                                                                              jint status)
3559 {
3560     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicReadCallback - status : %d", status);
3561 }
3562
3563 /*
3564  * Class:     org_iotivity_ca_jar_caleinterface
3565  * Method:    CALeGattCharacteristicWritjclasseCallback
3566  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
3567  */
3568 JNIEXPORT void JNICALL
3569 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
3570         JNIEnv *env, jobject obj, jobject gatt, jobject characteristic, jbyteArray data,
3571         jint status)
3572 {
3573     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
3574     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3575     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
3576
3577     ca_mutex_lock(g_threadSendCBMutex);
3578     if (!g_isRequestedSend)
3579     {
3580         OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - waiting");
3581         ca_cond_wait(g_threadSendCBCond, g_threadSendCBMutex);
3582     }
3583     ca_mutex_unlock(g_threadSendCBMutex);
3584
3585     jboolean isCopy;
3586     char* wroteData = (char*) (*env)->GetByteArrayElements(env, data, &isCopy);
3587
3588     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - write data : %s", wroteData);
3589
3590     // send success & signal
3591     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
3592     if (!jni_address)
3593     {
3594         goto error_exit;
3595     }
3596
3597     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
3598     if (!address)
3599     {
3600         goto error_exit;
3601     }
3602
3603     if (GATT_SUCCESS != status) // error case
3604     {
3605         OIC_LOG(ERROR, TAG, "send failure");
3606         CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
3607                                                      STATE_SEND_FAILED);
3608         if (CA_STATUS_OK != res)
3609         {
3610             OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
3611         }
3612         CALEClientSendFinish(env, gatt);
3613     }
3614     else
3615     {
3616         OIC_LOG(DEBUG, TAG, "send success");
3617         CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
3618                                                      STATE_SEND_SUCCESS);
3619         if (CA_STATUS_OK != res)
3620         {
3621             OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
3622         }
3623         CALEClientUpdateSendCnt(env);
3624     }
3625
3626     CALEClientSetWriteCharacteristicCBFlag(true);
3627     CALEClientSetTheSendRequestFlag(false);
3628     ca_cond_signal(g_threadSendCond);
3629     (*env)->ReleaseStringUTFChars(env, jni_address, address);
3630     return;
3631
3632     // error label.
3633 error_exit:
3634
3635     CALEClientSetWriteCharacteristicCBFlag(true);
3636     CALEClientSetTheSendRequestFlag(false);
3637     CALEClientSendFinish(env, gatt);
3638     ca_cond_signal(g_threadSendCond);
3639     return;
3640 }
3641
3642 /*
3643  * Class:     org_iotivity_ca_jar_caleinterface
3644  * Method:    CALeGattCharacteristicChangedCallback
3645  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
3646  */
3647 JNIEXPORT void JNICALL
3648 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
3649         JNIEnv *env, jobject obj, jobject gatt, jobject characteristic, jbyteArray data)
3650 {
3651     OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicChangedCallback");
3652     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3653     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
3654     VERIFY_NON_NULL_VOID(data, TAG, "data is null");
3655
3656     // get Byte Array and covert to char*
3657     jint length = (*env)->GetArrayLength(env, data);
3658
3659     jboolean isCopy;
3660     jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
3661
3662     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %s",
3663             jni_byte_responseData);
3664
3665     char* receivedData = (char*) OICMalloc(sizeof(char) * length + 1);
3666     if (!receivedData)
3667     {
3668         OIC_LOG(ERROR, TAG, "recevicedData is null");
3669         return;
3670     }
3671
3672     memcpy(receivedData, (const char*) jni_byte_responseData, length);
3673     receivedData[length] = '\0';
3674     (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
3675
3676     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
3677     if (!jni_address)
3678     {
3679         OIC_LOG(ERROR, TAG, "jni_address is null");
3680         OICFree(receivedData);
3681         return;
3682     }
3683
3684     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
3685     if (!address)
3686     {
3687         OIC_LOG(ERROR, TAG, "address is null");
3688         OICFree(receivedData);
3689         return;
3690     }
3691
3692     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %s, %d",
3693               receivedData, length);
3694
3695     ca_mutex_lock(g_bleServerBDAddressMutex);
3696     uint32_t sentLength = 0;
3697     g_CABLEClientDataReceivedCallback(address, OIC_GATT_SERVICE_UUID, receivedData, length,
3698                                       &sentLength);
3699     ca_mutex_unlock(g_bleServerBDAddressMutex);
3700
3701     (*env)->ReleaseStringUTFChars(env, jni_address, address);
3702 }
3703
3704 /*
3705  * Class:     org_iotivity_ca_jar_caleinterface
3706  * Method:    CALeGattDescriptorReadCallback
3707  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
3708  */
3709 JNIEXPORT void JNICALL
3710 Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorReadCallback(JNIEnv *env, jobject obj,
3711                                                                          jobject gatt,
3712                                                                          jobject descriptor,
3713                                                                          jint status)
3714 {
3715     OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorReadCallback - status %d: ", status);
3716 }
3717
3718 /*
3719  * Class:     org_iotivity_ca_jar_caleinterface
3720  * Method:    CALeGattDescriptorWriteCallback
3721  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
3722  */
3723 JNIEXPORT void JNICALL
3724 Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
3725                                                                           jobject gatt,
3726                                                                           jobject descriptor,
3727                                                                           jint status)
3728 {
3729     OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorWriteCallback - status %d: ", status);
3730     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3731     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
3732
3733     CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
3734     if (CA_STATUS_OK != res)
3735     {
3736         OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
3737         goto error_exit;
3738     }
3739     return;
3740
3741 // error label.
3742 error_exit:
3743
3744     CALEClientSendFinish(env, gatt);
3745     ca_cond_signal(g_threadSendCond);
3746     return;
3747 }
3748
3749 /*
3750  * Class:     org_iotivity_ca_jar_caleinterface
3751  * Method:    CALeGattReliableWriteCompletedCallback
3752  * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
3753  */
3754 JNIEXPORT void JNICALL
3755 Java_org_iotivity_ca_CaLeClientInterface_caLeGattReliableWriteCompletedCallback(JNIEnv *env,
3756                                                                                  jobject obj,
3757                                                                                  jobject gatt,
3758                                                                                  jint status)
3759 {
3760     OIC_LOG_V(DEBUG, TAG, "CALeGattReliableWriteCompletedCallback - status %d: ", status);
3761 }
3762
3763 /*
3764  * Class:     org_iotivity_ca_jar_caleinterface
3765  * Method:    CALeGattReadRemoteRssiCallback
3766  * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
3767  */
3768 JNIEXPORT void JNICALL
3769 Java_org_iotivity_ca_CaLeClientInterface_caLeGattReadRemoteRssiCallback(JNIEnv *env, jobject obj,
3770                                                                          jobject gatt, jint rssi,
3771                                                                          jint status)
3772 {
3773     OIC_LOG_V(DEBUG, TAG, "CALeGattReadRemoteRssiCallback - rssi %d,  status %d: ", rssi, status);
3774 }