removed unnecessary log for Android BLE
[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             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2159             return true;
2160         }
2161
2162         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2163     }
2164
2165     OIC_LOG(DEBUG, TAG, "there are no the device in list. we can add");
2166
2167     return false;
2168 }
2169
2170 CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env)
2171 {
2172     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices");
2173     VERIFY_NON_NULL(env, TAG, "env is null");
2174
2175     ca_mutex_lock(g_deviceListMutex);
2176
2177     if (!g_deviceList)
2178     {
2179         OIC_LOG(ERROR, TAG, "g_deviceList is null");
2180         ca_mutex_unlock(g_deviceListMutex);
2181         return CA_STATUS_FAILED;
2182     }
2183
2184     uint32_t length = u_arraylist_length(g_deviceList);
2185     for (uint32_t index = 0; index < length; index++)
2186     {
2187         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2188         if (!jarrayObj)
2189         {
2190             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2191             continue;
2192         }
2193         (*env)->DeleteGlobalRef(env, jarrayObj);
2194     }
2195
2196     OICFree(g_deviceList);
2197     g_deviceList = NULL;
2198
2199     ca_mutex_unlock(g_deviceListMutex);
2200     return CA_STATUS_OK;
2201 }
2202
2203 CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address)
2204 {
2205     OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceInScanDeviceList");
2206     VERIFY_NON_NULL(address, TAG, "address is null");
2207     VERIFY_NON_NULL(env, TAG, "env is null");
2208
2209     ca_mutex_lock(g_deviceListMutex);
2210
2211     if (!g_deviceList)
2212     {
2213         OIC_LOG(ERROR, TAG, "g_deviceList is null");
2214         ca_mutex_unlock(g_deviceListMutex);
2215         return CA_STATUS_FAILED;
2216     }
2217
2218     uint32_t length = u_arraylist_length(g_deviceList);
2219     for (uint32_t index = 0; index < length; index++)
2220     {
2221         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2222         if (!jarrayObj)
2223         {
2224             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2225             ca_mutex_unlock(g_deviceListMutex);
2226             return CA_STATUS_FAILED;
2227         }
2228
2229         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2230         if (!jni_setAddress)
2231         {
2232             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2233             ca_mutex_unlock(g_deviceListMutex);
2234             return CA_STATUS_FAILED;
2235         }
2236
2237         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2238         if (!setAddress)
2239         {
2240             OIC_LOG(ERROR, TAG, "setAddress is null");
2241             ca_mutex_unlock(g_deviceListMutex);
2242             return CA_STATUS_FAILED;
2243         }
2244
2245         const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
2246         if (!remoteAddress)
2247         {
2248             OIC_LOG(ERROR, TAG, "remoteAddress is null");
2249             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2250             ca_mutex_unlock(g_deviceListMutex);
2251             return CA_STATUS_FAILED;
2252         }
2253
2254         if (!strcmp(setAddress, remoteAddress))
2255         {
2256             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2257             (*env)->DeleteGlobalRef(env, jarrayObj);
2258             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2259             (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2260
2261             if (NULL == u_arraylist_remove(g_deviceList, index))
2262             {
2263                 OIC_LOG(ERROR, TAG, "List removal failed.");
2264                 ca_mutex_unlock(g_deviceListMutex);
2265                 return CA_STATUS_FAILED;
2266             }
2267             ca_mutex_unlock(g_deviceListMutex);
2268             return CA_STATUS_OK;
2269         }
2270         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2271         (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2272     }
2273
2274     ca_mutex_unlock(g_deviceListMutex);
2275     OIC_LOG(DEBUG, TAG, "There are no object in the device list");
2276
2277     return CA_STATUS_OK;
2278 }
2279
2280 /**
2281  * Gatt Object List
2282  */
2283
2284 CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt)
2285 {
2286     OIC_LOG(DEBUG, TAG, "CALEClientAddGattobjToList");
2287     VERIFY_NON_NULL(env, TAG, "env is null");
2288     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2289
2290     ca_mutex_lock(g_gattObjectMutex);
2291
2292     jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
2293     if (!jni_remoteAddress)
2294     {
2295         OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2296         ca_mutex_unlock(g_gattObjectMutex);
2297         return CA_STATUS_FAILED;
2298     }
2299
2300     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2301     if (!remoteAddress)
2302     {
2303         OIC_LOG(ERROR, TAG, "remoteAddress is null");
2304         ca_mutex_unlock(g_gattObjectMutex);
2305         return CA_STATUS_FAILED;
2306     }
2307
2308     if (!CALEClientIsGattObjInList(env, remoteAddress))
2309     {
2310         jobject newGatt = (*env)->NewGlobalRef(env, gatt);
2311         u_arraylist_add(g_gattObjectList, newGatt);
2312         OIC_LOG(DEBUG, TAG, "Set GATT Object to Array as Element");
2313     }
2314
2315     (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2316     ca_mutex_unlock(g_gattObjectMutex);
2317     return CA_STATUS_OK;
2318 }
2319
2320 bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress)
2321 {
2322     OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList");
2323     VERIFY_NON_NULL(env, TAG, "env is null");
2324     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2325
2326     uint32_t length = u_arraylist_length(g_gattObjectList);
2327     for (uint32_t index = 0; index < length; index++)
2328     {
2329
2330         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2331         if (!jarrayObj)
2332         {
2333             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2334             return true;
2335         }
2336
2337         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2338         if (!jni_setAddress)
2339         {
2340             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2341             return true;
2342         }
2343
2344         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2345         if (!setAddress)
2346         {
2347             OIC_LOG(ERROR, TAG, "setAddress is null");
2348             return true;
2349         }
2350
2351         if (!strcmp(remoteAddress, setAddress))
2352         {
2353             OIC_LOG(DEBUG, TAG, "the device is already set");
2354             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2355             return true;
2356         }
2357         else
2358         {
2359             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2360             continue;
2361         }
2362     }
2363
2364     OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added");
2365     return false;
2366 }
2367
2368 jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress)
2369 {
2370     OIC_LOG(DEBUG, TAG, "CALEClientGetGattObjInList");
2371     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2372     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
2373
2374     ca_mutex_lock(g_gattObjectMutex);
2375     uint32_t length = u_arraylist_length(g_gattObjectList);
2376     for (uint32_t index = 0; index < length; index++)
2377     {
2378         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2379         if (!jarrayObj)
2380         {
2381             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2382             ca_mutex_unlock(g_gattObjectMutex);
2383             return NULL;
2384         }
2385
2386         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2387         if (!jni_setAddress)
2388         {
2389             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2390             ca_mutex_unlock(g_gattObjectMutex);
2391             return NULL;
2392         }
2393
2394         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2395         if (!setAddress)
2396         {
2397             OIC_LOG(ERROR, TAG, "setAddress is null");
2398             ca_mutex_unlock(g_gattObjectMutex);
2399             return NULL;
2400         }
2401
2402         if (!strcmp(remoteAddress, setAddress))
2403         {
2404             OIC_LOG(DEBUG, TAG, "the device is already set");
2405             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2406             ca_mutex_unlock(g_gattObjectMutex);
2407             return jarrayObj;
2408         }
2409         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2410     }
2411
2412     ca_mutex_unlock(g_gattObjectMutex);
2413     OIC_LOG(DEBUG, TAG, "There are no the gatt object in list");
2414     return NULL;
2415 }
2416
2417 CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env)
2418 {
2419     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs");
2420     VERIFY_NON_NULL(env, TAG, "env is null");
2421
2422     ca_mutex_lock(g_gattObjectMutex);
2423     if (!g_gattObjectList)
2424     {
2425         OIC_LOG(ERROR, TAG, "g_gattObjectList is null");
2426         ca_mutex_unlock(g_gattObjectMutex);
2427         return CA_STATUS_FAILED;
2428     }
2429
2430     uint32_t length = u_arraylist_length(g_gattObjectList);
2431     for (uint32_t index = 0; index < length; index++)
2432     {
2433         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2434         if (!jarrayObj)
2435         {
2436             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2437             continue;
2438         }
2439         (*env)->DeleteGlobalRef(env, jarrayObj);
2440     }
2441
2442     OICFree(g_gattObjectList);
2443     g_gattObjectList = NULL;
2444     ca_mutex_unlock(g_gattObjectMutex);
2445     return CA_STATUS_OK;
2446 }
2447
2448 CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt)
2449 {
2450     OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObj");
2451     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2452     VERIFY_NON_NULL(env, TAG, "env is null");
2453
2454     ca_mutex_lock(g_gattObjectMutex);
2455     if (!g_gattObjectList)
2456     {
2457         OIC_LOG(ERROR, TAG, "g_gattObjectList is null");
2458         ca_mutex_unlock(g_gattObjectMutex);
2459         return CA_STATUS_FAILED;
2460     }
2461
2462     uint32_t length = u_arraylist_length(g_gattObjectList);
2463     for (uint32_t index = 0; index < length; index++)
2464     {
2465         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2466         if (!jarrayObj)
2467         {
2468             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2469             ca_mutex_unlock(g_gattObjectMutex);
2470             return CA_STATUS_FAILED;
2471         }
2472
2473         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2474         if (!jni_setAddress)
2475         {
2476             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2477             ca_mutex_unlock(g_gattObjectMutex);
2478             return CA_STATUS_FAILED;
2479         }
2480
2481         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2482         if (!setAddress)
2483         {
2484             OIC_LOG(ERROR, TAG, "setAddress is null");
2485             ca_mutex_unlock(g_gattObjectMutex);
2486             return CA_STATUS_FAILED;
2487         }
2488
2489         jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
2490         if (!jni_remoteAddress)
2491         {
2492             OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2493             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2494             ca_mutex_unlock(g_gattObjectMutex);
2495             return CA_STATUS_FAILED;
2496         }
2497
2498         const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2499         if (!remoteAddress)
2500         {
2501             OIC_LOG(ERROR, TAG, "remoteAddress is null");
2502             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2503             ca_mutex_unlock(g_gattObjectMutex);
2504             return CA_STATUS_FAILED;
2505         }
2506
2507         if (!strcmp(setAddress, remoteAddress))
2508         {
2509             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2510             (*env)->DeleteGlobalRef(env, jarrayObj);
2511             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2512             (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2513
2514             if (NULL == u_arraylist_remove(g_gattObjectList, index))
2515             {
2516                 OIC_LOG(ERROR, TAG, "List removal failed.");
2517                 ca_mutex_unlock(g_gattObjectMutex);
2518                 return CA_STATUS_FAILED;
2519             }
2520             ca_mutex_unlock(g_gattObjectMutex);
2521             return CA_STATUS_OK;
2522         }
2523         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2524         (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2525     }
2526
2527     ca_mutex_unlock(g_gattObjectMutex);
2528     OIC_LOG(DEBUG, TAG, "there are no target object");
2529     return CA_STATUS_OK;
2530 }
2531
2532 CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr)
2533 {
2534     OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObjForAddr");
2535     VERIFY_NON_NULL(addr, TAG, "addr is null");
2536     VERIFY_NON_NULL(env, TAG, "env is null");
2537
2538     ca_mutex_lock(g_gattObjectMutex);
2539     if (!g_gattObjectList)
2540     {
2541         OIC_LOG(ERROR, TAG, "g_gattObjectList is null");
2542         ca_mutex_unlock(g_gattObjectMutex);
2543         return CA_STATUS_FAILED;
2544     }
2545
2546     uint32_t length = u_arraylist_length(g_gattObjectList);
2547     for (uint32_t index = 0; index < length; index++)
2548     {
2549         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2550         if (!jarrayObj)
2551         {
2552             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2553             ca_mutex_unlock(g_gattObjectMutex);
2554             return CA_STATUS_FAILED;
2555         }
2556
2557         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2558         if (!jni_setAddress)
2559         {
2560             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2561             ca_mutex_unlock(g_gattObjectMutex);
2562             return CA_STATUS_FAILED;
2563         }
2564
2565         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2566         if (!setAddress)
2567         {
2568             OIC_LOG(ERROR, TAG, "setAddress is null");
2569             ca_mutex_unlock(g_gattObjectMutex);
2570             return CA_STATUS_FAILED;
2571         }
2572
2573         const char* remoteAddress = (*env)->GetStringUTFChars(env, addr, NULL);
2574         if (!remoteAddress)
2575         {
2576             OIC_LOG(ERROR, TAG, "remoteAddress is null");
2577             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2578             ca_mutex_unlock(g_gattObjectMutex);
2579             return CA_STATUS_FAILED;
2580         }
2581
2582         if (!strcmp(setAddress, remoteAddress))
2583         {
2584             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2585             (*env)->DeleteGlobalRef(env, jarrayObj);
2586
2587             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2588             (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
2589             if (NULL == u_arraylist_remove(g_gattObjectList, index))
2590             {
2591                 OIC_LOG(ERROR, TAG, "List removal failed.");
2592                 ca_mutex_unlock(g_gattObjectMutex);
2593                 return CA_STATUS_FAILED;
2594             }
2595             ca_mutex_unlock(g_gattObjectMutex);
2596             return CA_STATUS_OK;
2597         }
2598         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2599         (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
2600     }
2601
2602     ca_mutex_unlock(g_gattObjectMutex);
2603     OIC_LOG(DEBUG, TAG, "there are no target object");
2604     return CA_STATUS_FAILED;
2605 }
2606
2607 /**
2608  * BT State List
2609  */
2610
2611 CAResult_t CALEClientUpdateDeviceState(const char* address, uint32_t connectedState,
2612                                        uint16_t notificationState, uint16_t sendState)
2613 {
2614     VERIFY_NON_NULL(address, TAG, "address is null");
2615
2616     CALEState_t *newstate = (CALEState_t*) OICMalloc(sizeof(CALEState_t));
2617     if (!newstate)
2618     {
2619         OIC_LOG(ERROR, TAG, "out of memory");
2620         return CA_MEMORY_ALLOC_FAILED;
2621     }
2622
2623     if (strlen(address) > CA_MACADDR_SIZE)
2624     {
2625         OIC_LOG(ERROR, TAG, "address is not proper");
2626         OICFree(newstate);
2627         return CA_STATUS_FAILED;
2628     }
2629
2630     OICStrcpy(newstate->address, sizeof(newstate->address), address);
2631     newstate->connectedState = connectedState;
2632     newstate->notificationState = notificationState;
2633     newstate->sendState = sendState;
2634     return CALEClientAddDeviceStateToList(newstate);
2635 }
2636
2637 CAResult_t CALEClientAddDeviceStateToList(CALEState_t* state)
2638 {
2639     VERIFY_NON_NULL(state, TAG, "state is null");
2640
2641     ca_mutex_lock(g_deviceStateListMutex);
2642
2643     if (!g_deviceStateList)
2644     {
2645         OIC_LOG(ERROR, TAG, "gdevice_list is null");
2646         ca_mutex_unlock(g_deviceStateListMutex);
2647         return CA_STATUS_FAILED;
2648     }
2649
2650     if (CALEClientIsDeviceInList(state->address))
2651     {
2652         CALEState_t* curState = CALEClientGetStateInfo(state->address);
2653         if(!curState)
2654         {
2655             OIC_LOG(ERROR, TAG, "curState is null");
2656             ca_mutex_unlock(g_deviceStateListMutex);
2657             return CA_STATUS_FAILED;
2658         }
2659
2660         if (STATE_CHARACTER_NO_CHANGE == state->notificationState)
2661         {
2662             state->notificationState = curState->notificationState;
2663         }
2664
2665         // delete previous state for update new state
2666         CAResult_t res = CALEClientRemoveDeviceState(state->address);
2667         if (CA_STATUS_OK != res)
2668         {
2669             OIC_LOG(ERROR, TAG, "CALEClientRemoveDeviceState has failed");
2670             ca_mutex_unlock(g_deviceStateListMutex);
2671             return res;
2672         }
2673     }
2674     u_arraylist_add(g_deviceStateList, state); // update new state
2675     OIC_LOG_V(DEBUG, TAG, "Set State Info to List : %d, %d",
2676               state->connectedState, state->notificationState);
2677
2678     ca_mutex_unlock(g_deviceStateListMutex);
2679     return CA_STATUS_OK;
2680 }
2681
2682 bool CALEClientIsDeviceInList(const char* remoteAddress)
2683 {
2684     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
2685
2686     if (!g_deviceStateList)
2687     {
2688         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2689         return false;
2690     }
2691
2692     uint32_t length = u_arraylist_length(g_deviceStateList);
2693     for (uint32_t index = 0; index < length; index++)
2694     {
2695         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2696         if (!state)
2697         {
2698             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2699             return false;
2700         }
2701
2702         if (!strcmp(remoteAddress, state->address))
2703         {
2704             OIC_LOG(DEBUG, TAG, "the device is already set");
2705             return true;
2706         }
2707         else
2708         {
2709             continue;
2710         }
2711     }
2712
2713     OIC_LOG(DEBUG, TAG, "there are no the device in list.");
2714     return false;
2715 }
2716
2717 CAResult_t CALEClientRemoveAllDeviceState()
2718 {
2719     OIC_LOG(DEBUG, TAG, "CALENativeRemoveAllDevices");
2720
2721     ca_mutex_lock(g_deviceStateListMutex);
2722     if (!g_deviceStateList)
2723     {
2724         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2725         ca_mutex_unlock(g_deviceStateListMutex);
2726         return CA_STATUS_FAILED;
2727     }
2728
2729     uint32_t length = u_arraylist_length(g_deviceStateList);
2730     for (uint32_t index = 0; index < length; index++)
2731     {
2732         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2733         if (!state)
2734         {
2735             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2736             continue;
2737         }
2738         OICFree(state);
2739     }
2740
2741     OICFree(g_deviceStateList);
2742     g_deviceStateList = NULL;
2743     ca_mutex_unlock(g_deviceStateListMutex);
2744
2745     return CA_STATUS_OK;
2746 }
2747
2748 CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress)
2749 {
2750     OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceState");
2751     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
2752
2753     if (!g_deviceStateList)
2754     {
2755         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2756         return CA_STATUS_FAILED;
2757     }
2758
2759     uint32_t length = u_arraylist_length(g_deviceStateList);
2760     for (uint32_t index = 0; index < length; index++)
2761     {
2762         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2763         if (!state)
2764         {
2765             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2766             continue;
2767         }
2768
2769         if (!strcmp(state->address, remoteAddress))
2770         {
2771             OIC_LOG_V(DEBUG, TAG, "remove state : %s", remoteAddress);
2772             OICFree(state);
2773
2774             if (NULL == u_arraylist_remove(g_deviceStateList, index))
2775             {
2776                 OIC_LOG(ERROR, TAG, "List removal failed.");
2777                 return CA_STATUS_FAILED;
2778             }
2779
2780             return CA_STATUS_OK;
2781         }
2782     }
2783
2784     return CA_STATUS_FAILED;
2785 }
2786
2787 CALEState_t* CALEClientGetStateInfo(const char* remoteAddress)
2788 {
2789     OIC_LOG(DEBUG, TAG, "CALEClientGetStateInfo");
2790     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
2791
2792     if (!g_deviceStateList)
2793     {
2794         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2795         return NULL;
2796     }
2797
2798     uint32_t length = u_arraylist_length(g_deviceStateList);
2799     for (uint32_t index = 0; index < length; index++)
2800     {
2801         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2802         if (!state)
2803         {
2804             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2805             continue;
2806         }
2807
2808         if (!strcmp(state->address, remoteAddress))
2809         {
2810             OIC_LOG_V(DEBUG, TAG, "get state : %s", remoteAddress);
2811             return state;
2812         }
2813     }
2814     return NULL;
2815 }
2816
2817 bool CALEClientIsConnectedDevice(const char* remoteAddress)
2818 {
2819     OIC_LOG(DEBUG, TAG, "CALEClientIsConnectedDevice");
2820     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
2821
2822     ca_mutex_lock(g_deviceStateListMutex);
2823     if (!g_deviceStateList)
2824     {
2825         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2826         ca_mutex_unlock(g_deviceStateListMutex);
2827         return false;
2828     }
2829
2830     uint32_t length = u_arraylist_length(g_deviceStateList);
2831     for (uint32_t index = 0; index < length; index++)
2832     {
2833         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2834         if (!state)
2835         {
2836             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2837             continue;
2838         }
2839
2840         if (!strcmp(state->address, remoteAddress))
2841         {
2842             OIC_LOG(DEBUG, TAG, "check whether it is connected or not");
2843
2844             if (STATE_CONNECTED == state->connectedState)
2845             {
2846                 ca_mutex_unlock(g_deviceStateListMutex);
2847                 return true;
2848             }
2849             else
2850             {
2851                 ca_mutex_unlock(g_deviceStateListMutex);
2852                 return false;
2853             }
2854         }
2855     }
2856     ca_mutex_unlock(g_deviceStateListMutex);
2857     return false;
2858 }
2859
2860 bool CALEClientIsSetCharacteristic(const char* remoteAddress)
2861 {
2862     OIC_LOG(DEBUG, TAG, "CALEClientIsSetCharacteristic");
2863     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
2864
2865     ca_mutex_lock(g_deviceStateListMutex);
2866     if (!g_deviceStateList)
2867     {
2868         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2869         ca_mutex_unlock(g_deviceStateListMutex);
2870         return false;
2871     }
2872
2873     uint32_t length = u_arraylist_length(g_deviceStateList);
2874     for (uint32_t index = 0; index < length; index++)
2875     {
2876         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2877         if (!state)
2878         {
2879             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2880             continue;
2881         }
2882
2883         if (!strcmp(state->address, remoteAddress))
2884         {
2885             OIC_LOG_V(DEBUG, TAG, "check whether it was set or not:%d", state->notificationState);
2886
2887             if (STATE_CHARACTER_SET == state->notificationState)
2888             {
2889                 ca_mutex_unlock(g_deviceStateListMutex);
2890                 return true;
2891             }
2892             else
2893             {
2894                 ca_mutex_unlock(g_deviceStateListMutex);
2895                 return false;
2896             }
2897         }
2898     }
2899
2900     ca_mutex_unlock(g_deviceStateListMutex);
2901     return false;
2902 }
2903
2904 void CALEClientCreateDeviceList()
2905 {
2906     OIC_LOG(DEBUG, TAG, "CALEClientCreateDeviceList");
2907
2908     // create new object array
2909     if (!g_gattObjectList)
2910     {
2911         OIC_LOG(DEBUG, TAG, "Create g_gattObjectList");
2912
2913         g_gattObjectList = u_arraylist_create();
2914     }
2915
2916     if (!g_deviceStateList)
2917     {
2918         OIC_LOG(DEBUG, TAG, "Create g_deviceStateList");
2919
2920         g_deviceStateList = u_arraylist_create();
2921     }
2922
2923     if (!g_deviceList)
2924     {
2925         OIC_LOG(DEBUG, TAG, "Create g_deviceList");
2926
2927         g_deviceList = u_arraylist_create();
2928     }
2929 }
2930
2931 /**
2932  * Check Sent Count for remove g_sendBuffer
2933  */
2934 void CALEClientUpdateSendCnt(JNIEnv *env)
2935 {
2936     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
2937     // mutex lock
2938     ca_mutex_lock(g_threadMutex);
2939
2940     g_currentSentCnt++;
2941
2942     if (g_targetCnt <= g_currentSentCnt)
2943     {
2944         g_targetCnt = 0;
2945         g_currentSentCnt = 0;
2946
2947         if (g_sendBuffer)
2948         {
2949             (*env)->DeleteGlobalRef(env, g_sendBuffer);
2950             g_sendBuffer = NULL;
2951         }
2952         // notity the thread
2953         ca_cond_signal(g_threadCond);
2954         CALEClientSetSendFinishFlag(true);
2955         OIC_LOG(DEBUG, TAG, "set signal for send data");
2956     }
2957     // mutex unlock
2958     ca_mutex_unlock(g_threadMutex);
2959 }
2960
2961 CAResult_t CALEClientInitGattMutexVaraibles()
2962 {
2963     if (NULL == g_bleReqRespClientCbMutex)
2964     {
2965         g_bleReqRespClientCbMutex = ca_mutex_new();
2966         if (NULL == g_bleReqRespClientCbMutex)
2967         {
2968             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2969             return CA_STATUS_FAILED;
2970         }
2971     }
2972
2973     if (NULL == g_bleServerBDAddressMutex)
2974     {
2975         g_bleServerBDAddressMutex = ca_mutex_new();
2976         if (NULL == g_bleServerBDAddressMutex)
2977         {
2978             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2979             return CA_STATUS_FAILED;
2980         }
2981     }
2982
2983     if (NULL == g_threadMutex)
2984     {
2985         g_threadMutex = ca_mutex_new();
2986         if (NULL == g_threadMutex)
2987         {
2988             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2989             return CA_STATUS_FAILED;
2990         }
2991     }
2992
2993     if (NULL == g_threadSendMutex)
2994     {
2995         g_threadSendMutex = ca_mutex_new();
2996         if (NULL == g_threadSendMutex)
2997         {
2998             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
2999             return CA_STATUS_FAILED;
3000         }
3001     }
3002
3003     if (NULL == g_deviceListMutex)
3004     {
3005         g_deviceListMutex = ca_mutex_new();
3006         if (NULL == g_deviceListMutex)
3007         {
3008             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3009             return CA_STATUS_FAILED;
3010         }
3011     }
3012
3013     if (NULL == g_gattObjectMutex)
3014     {
3015         g_gattObjectMutex = ca_mutex_new();
3016         if (NULL == g_gattObjectMutex)
3017         {
3018             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3019             return CA_STATUS_FAILED;
3020         }
3021     }
3022
3023     if (NULL == g_deviceStateListMutex)
3024     {
3025         g_deviceStateListMutex = ca_mutex_new();
3026         if (NULL == g_deviceStateListMutex)
3027         {
3028             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3029             return CA_STATUS_FAILED;
3030         }
3031     }
3032
3033     if (NULL == g_SendFinishMutex)
3034     {
3035         g_SendFinishMutex = ca_mutex_new();
3036         if (NULL == g_SendFinishMutex)
3037         {
3038             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3039             return CA_STATUS_FAILED;
3040         }
3041     }
3042
3043     if (NULL == g_scanMutex)
3044     {
3045         g_scanMutex = ca_mutex_new();
3046         if (NULL == g_scanMutex)
3047         {
3048             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3049             return CA_STATUS_FAILED;
3050         }
3051     }
3052
3053     return CA_STATUS_OK;
3054 }
3055
3056 void CALEClientTerminateGattMutexVariables()
3057 {
3058     ca_mutex_free(g_bleReqRespClientCbMutex);
3059     g_bleReqRespClientCbMutex = NULL;
3060
3061     ca_mutex_free(g_bleServerBDAddressMutex);
3062     g_bleServerBDAddressMutex = NULL;
3063
3064     ca_mutex_free(g_threadMutex);
3065     g_threadMutex = NULL;
3066
3067     ca_mutex_free(g_threadSendMutex);
3068     g_threadSendMutex = NULL;
3069
3070     ca_mutex_free(g_deviceListMutex);
3071     g_deviceListMutex = NULL;
3072
3073     ca_mutex_free(g_SendFinishMutex);
3074     g_SendFinishMutex = NULL;
3075
3076     ca_mutex_free(g_scanMutex);
3077     g_scanMutex = NULL;
3078 }
3079
3080 void CALEClientSetSendFinishFlag(bool flag)
3081 {
3082     OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag);
3083
3084     ca_mutex_lock(g_SendFinishMutex);
3085     g_isFinishedSendData = flag;
3086     ca_mutex_unlock(g_SendFinishMutex);
3087 }
3088
3089 /**
3090  * adapter common
3091  */
3092
3093 CAResult_t CAStartLEGattClient()
3094 {
3095     CAResult_t res = CALEClientStartMulticastServer();
3096     if (CA_STATUS_OK != res)
3097     {
3098         OIC_LOG(ERROR, TAG, "CALEClientStartMulticastServer has failed");
3099     }
3100     else
3101     {
3102         g_isStartedLEClient = true;
3103     }
3104
3105     return res;
3106 }
3107
3108 void CAStopLEGattClient()
3109 {
3110     OIC_LOG(DEBUG, TAG, "CAStopBLEGattClient");
3111
3112     if (!g_jvm)
3113     {
3114         OIC_LOG(ERROR, TAG, "g_jvm is null");
3115         return;
3116     }
3117
3118     bool isAttached = false;
3119     JNIEnv* env;
3120     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
3121     if (JNI_OK != res)
3122     {
3123         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
3124         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
3125
3126         if (JNI_OK != res)
3127         {
3128             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
3129             return;
3130         }
3131         isAttached = true;
3132     }
3133
3134     CAResult_t ret = CALEClientDisconnectAll(env);
3135     if (CA_STATUS_OK != ret)
3136     {
3137         OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
3138     }
3139
3140     ret = CALEClientStopScan();
3141     if(CA_STATUS_OK != ret)
3142     {
3143         OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
3144     }
3145
3146     ca_cond_signal(g_threadCond);
3147
3148     if (isAttached)
3149     {
3150         (*g_jvm)->DetachCurrentThread(g_jvm);
3151     }
3152
3153 }
3154
3155 void CATerminateLEGattClient()
3156 {
3157     OIC_LOG(DEBUG, TAG, "Terminate GATT Client");
3158     CALEClientTerminate();
3159 }
3160
3161 CAResult_t  CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t  *data,
3162                                                 uint32_t dataLen, CALETransferType_t type,
3163                                                 int32_t position)
3164 {
3165     OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage");
3166     VERIFY_NON_NULL(data, TAG, "data is null");
3167     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
3168
3169     if (LE_UNICAST != type || position < 0)
3170     {
3171         OIC_LOG(ERROR, TAG, "this request is not unicast");
3172         return CA_STATUS_INVALID_PARAM;
3173     }
3174
3175     return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
3176 }
3177
3178 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
3179 {
3180     OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
3181     VERIFY_NON_NULL(data, TAG, "data is null");
3182
3183     return CALEClientSendMulticastMessage(data, dataLen);
3184 }
3185
3186 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
3187 {
3188     ca_mutex_lock(g_bleReqRespClientCbMutex);
3189     g_CABLEClientDataReceivedCallback = callback;
3190     ca_mutex_unlock(g_bleReqRespClientCbMutex);
3191 }
3192
3193 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
3194 {
3195     CALEClientInitialize(handle);
3196 }
3197
3198 CAResult_t CAGetLEAddress(char **local_address)
3199 {
3200     VERIFY_NON_NULL(local_address, TAG, "local_address");
3201     OIC_LOG(INFO, TAG, "CAGetLEAddress is not support");
3202     return CA_NOT_SUPPORTED;
3203 }
3204
3205 JNIEXPORT void JNICALL
3206 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
3207                                                                     jobject callback)
3208 {
3209     OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
3210     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3211     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3212     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
3213
3214     g_leScanCallback = (*env)->NewGlobalRef(env, callback);
3215 }
3216
3217 JNIEXPORT void JNICALL
3218 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
3219                                                                   jobject callback)
3220 {
3221     OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
3222     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3223     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3224     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
3225
3226     g_leGattCallback = (*env)->NewGlobalRef(env, callback);
3227 }
3228
3229 JNIEXPORT void JNICALL
3230 Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
3231                                                           jobject device)
3232 {
3233     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3234     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3235     VERIFY_NON_NULL_VOID(device, TAG, "device is null");
3236
3237     CAResult_t res = CALEClientAddScanDeviceToList(env, device);
3238     if (CA_STATUS_OK != res)
3239     {
3240         OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
3241     }
3242 }
3243
3244 /*
3245  * Class:     org_iotivity_ca_jar_caleinterface
3246  * Method:    CALeGattConnectionStateChangeCallback
3247  * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
3248  */
3249 JNIEXPORT void JNICALL
3250 Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
3251                                                                                 jobject obj,
3252                                                                                 jobject gatt,
3253                                                                                 jint status,
3254                                                                                 jint newstate)
3255 {
3256     OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
3257             newstate);
3258     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3259     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3260     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
3261
3262     if (GATT_SUCCESS == status && STATE_CONNECTED == newstate) // le connected
3263     {
3264         jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
3265         if (!jni_address)
3266         {
3267             goto error_exit;
3268         }
3269
3270         const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
3271         if (address)
3272         {
3273             CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED,
3274                                                          STATE_CHARACTER_NO_CHANGE,
3275                                                          STATE_SEND_NONE);
3276             if (CA_STATUS_OK != res)
3277             {
3278                 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
3279                 (*env)->ReleaseStringUTFChars(env, jni_address, address);
3280                 goto error_exit;
3281             }
3282             (*env)->ReleaseStringUTFChars(env, jni_address, address);
3283         }
3284
3285         CAResult_t res = CALEClientAddGattobjToList(env, gatt);
3286         if (CA_STATUS_OK != res)
3287         {
3288             OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
3289             goto error_exit;
3290         }
3291
3292         res = CALEClientDiscoverServices(env, gatt);
3293         if (CA_STATUS_OK != res)
3294         {
3295             OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
3296             goto error_exit;
3297         }
3298     }
3299     else // le disconnected
3300     {
3301         CAResult_t res = CALEClientStartScan();
3302         if (CA_STATUS_OK != res)
3303         {
3304             OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
3305             goto error_exit;
3306         }
3307
3308         jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
3309         if (!jni_address)
3310         {
3311             OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
3312             goto error_exit;
3313         }
3314
3315         const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
3316         if (address)
3317         {
3318             res = CALEClientRemoveDeviceState(address);
3319             if (CA_STATUS_OK != res)
3320             {
3321                 OIC_LOG(ERROR, TAG, "CALEClientRemoveDeviceState has failed");
3322                 goto error_exit;
3323             }
3324
3325             res = CALEClientRemoveGattObjForAddr(env, jni_address);
3326             if (CA_STATUS_OK != res)
3327             {
3328                 OIC_LOG(ERROR, TAG, "CALEClientRemoveGattObjForAddr has failed");
3329                 goto error_exit;
3330             }
3331
3332             (*env)->ReleaseStringUTFChars(env, jni_address, address);
3333         }
3334
3335         res = CALEClientGattClose(env, gatt);
3336         if (CA_STATUS_OK != res)
3337         {
3338             OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
3339         }
3340     }
3341     return;
3342
3343     // error label.
3344 error_exit:
3345
3346     CALEClientSendFinish(env, gatt);
3347     return;
3348 }
3349
3350 /*
3351  * Class:     org_iotivity_ca_jar_caleinterface
3352  * Method:    CALeGattServicesDiscoveredCallback
3353  * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
3354  */
3355 JNIEXPORT void JNICALL
3356 Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
3357                                                                              jobject obj,
3358                                                                              jobject gatt,
3359                                                                              jint status)
3360 {
3361     OIC_LOG_V(DEBUG, TAG, "CALeGattServicesDiscoveredCallback - status %d: ", status);
3362     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3363     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3364     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
3365
3366     if (0 != status) // discovery error
3367     {
3368         CALEClientSendFinish(env, gatt);
3369         return;
3370     }
3371
3372     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
3373     if (!jni_address)
3374     {
3375         CALEClientSendFinish(env, gatt);
3376         return;
3377     }
3378
3379     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
3380     if (!address)
3381     {
3382         CALEClientSendFinish(env, gatt);
3383         return;
3384     }
3385
3386     if (!CALEClientIsSetCharacteristic(address))
3387     {
3388         jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
3389         if (!jni_uuid)
3390         {
3391             OIC_LOG(ERROR, TAG, "jni_uuid is null");
3392             goto error_exit;
3393         }
3394
3395         jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
3396         if (!jni_obj_GattCharacteristic)
3397         {
3398             OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
3399             goto error_exit;
3400         }
3401
3402         CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
3403                                                                  jni_obj_GattCharacteristic);
3404         if (CA_STATUS_OK != res)
3405         {
3406             OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
3407             goto error_exit;
3408         }
3409
3410         res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
3411         if (CA_STATUS_OK != res)
3412         {
3413             OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
3414             CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
3415             if (CA_STATUS_OK != res)
3416             {
3417                 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
3418                 goto error_exit;
3419             }
3420         }
3421
3422         res = CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
3423                                           STATE_SEND_NONE);
3424         if (CA_STATUS_OK != res)
3425         {
3426             OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
3427             goto error_exit;
3428         }
3429     }
3430     else
3431     {
3432         CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
3433         if (CA_STATUS_OK != res)
3434         {
3435             OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
3436             goto error_exit;
3437         }
3438     }
3439     (*env)->ReleaseStringUTFChars(env, jni_address, address);
3440     return;
3441
3442     // error label.
3443 error_exit:
3444     (*env)->ReleaseStringUTFChars(env, jni_address, address);
3445     CALEClientSendFinish(env, gatt);
3446     return;
3447 }
3448
3449 /*
3450  * Class:     org_iotivity_ca_jar_caleinterface
3451  * Method:    CALeGattCharacteristicWritjclasseCallback
3452  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
3453  */
3454 JNIEXPORT void JNICALL
3455 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
3456         JNIEnv *env, jobject obj, jobject gatt, jbyteArray data,
3457         jint status)
3458 {
3459     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
3460     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3461     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3462     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
3463
3464     jboolean isCopy;
3465     char* wroteData = (char*) (*env)->GetByteArrayElements(env, data, &isCopy);
3466
3467     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - write data : %s", wroteData);
3468
3469     // send success & signal
3470     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
3471     if (!jni_address)
3472     {
3473         goto error_exit;
3474     }
3475
3476     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
3477     if (!address)
3478     {
3479         goto error_exit;
3480     }
3481
3482     if (GATT_SUCCESS != status) // error case
3483     {
3484         OIC_LOG(ERROR, TAG, "send failure");
3485         CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
3486                                                      STATE_SEND_FAILED);
3487         if (CA_STATUS_OK != res)
3488         {
3489             OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
3490         }
3491
3492         if (g_clientErrorCallback)
3493         {
3494             jint length = (*env)->GetArrayLength(env, data);
3495             g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
3496         }
3497
3498         CALEClientSendFinish(env, gatt);
3499     }
3500     else
3501     {
3502         OIC_LOG(DEBUG, TAG, "send success");
3503         CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
3504                                                      STATE_SEND_SUCCESS);
3505         if (CA_STATUS_OK != res)
3506         {
3507             OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
3508         }
3509         CALEClientUpdateSendCnt(env);
3510     }
3511
3512     (*env)->ReleaseStringUTFChars(env, jni_address, address);
3513     return;
3514
3515     // error label.
3516 error_exit:
3517
3518     CALEClientSendFinish(env, gatt);
3519     return;
3520 }
3521
3522 /*
3523  * Class:     org_iotivity_ca_jar_caleinterface
3524  * Method:    CALeGattCharacteristicChangedCallback
3525  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
3526  */
3527 JNIEXPORT void JNICALL
3528 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
3529         JNIEnv *env, jobject obj, jobject gatt, jbyteArray data)
3530 {
3531     OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicChangedCallback");
3532     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3533     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3534     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
3535     VERIFY_NON_NULL_VOID(data, TAG, "data is null");
3536
3537     // get Byte Array and convert to uint8_t*
3538     jint length = (*env)->GetArrayLength(env, data);
3539
3540     jboolean isCopy;
3541     jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
3542
3543     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %p",
3544             jni_byte_responseData);
3545
3546     uint8_t* receivedData = OICMalloc(length);
3547     if (!receivedData)
3548     {
3549         OIC_LOG(ERROR, TAG, "receivedData is null");
3550         return;
3551     }
3552
3553     memcpy(receivedData, jni_byte_responseData, length);
3554     (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
3555
3556     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
3557     if (!jni_address)
3558     {
3559         OIC_LOG(ERROR, TAG, "jni_address is null");
3560         OICFree(receivedData);
3561         return;
3562     }
3563
3564     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
3565     if (!address)
3566     {
3567         OIC_LOG(ERROR, TAG, "address is null");
3568         OICFree(receivedData);
3569         return;
3570     }
3571
3572     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
3573               receivedData, length);
3574
3575     ca_mutex_lock(g_bleServerBDAddressMutex);
3576     uint32_t sentLength = 0;
3577     g_CABLEClientDataReceivedCallback(address, receivedData, length,
3578                                       &sentLength);
3579     ca_mutex_unlock(g_bleServerBDAddressMutex);
3580
3581     (*env)->ReleaseStringUTFChars(env, jni_address, address);
3582 }
3583
3584 /*
3585  * Class:     org_iotivity_ca_jar_caleinterface
3586  * Method:    CALeGattDescriptorWriteCallback
3587  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
3588  */
3589 JNIEXPORT void JNICALL
3590 Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
3591                                                                          jobject gatt,
3592                                                                          jint status)
3593 {
3594     OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorWriteCallback - status %d: ", status);
3595     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3596     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3597     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
3598
3599     CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
3600     if (CA_STATUS_OK != res)
3601     {
3602         OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
3603         goto error_exit;
3604     }
3605     return;
3606
3607 // error label.
3608 error_exit:
3609
3610     CALEClientSendFinish(env, gatt);
3611     return;
3612 }