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