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