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