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