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