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