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