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