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