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