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