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