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