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