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