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