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