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