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