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