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