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