resolve build warnings for android
[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     OIC_LOG(INFO, TAG, "writeCharacteristic success!!");
2240     return CA_STATUS_OK;
2241 }
2242
2243 CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt)
2244 {
2245     OIC_LOG(DEBUG, TAG, "IN - CALEClientWriteCharacteristic");
2246     VERIFY_NON_NULL(env, TAG, "env is null");
2247     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2248
2249     jobject gattParam = (*env)->NewGlobalRef(env, gatt);
2250     if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle,
2251                                                 CALEWriteCharacteristicThread, (void*)gattParam))
2252     {
2253         OIC_LOG(ERROR, TAG, "Failed to create read thread!");
2254         return CA_STATUS_FAILED;
2255     }
2256
2257     OIC_LOG(DEBUG, TAG, "OUT - CALEClientWriteCharacteristic");
2258     return CA_STATUS_OK;
2259 }
2260
2261 CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt,
2262                                              jobject gattCharacteristic)
2263 {
2264     OIC_LOG(DEBUG, TAG, "WRITE GATT CHARACTERISTIC");
2265     VERIFY_NON_NULL(env, TAG, "env is null");
2266     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2267     VERIFY_NON_NULL(gattCharacteristic, TAG, "gattCharacteristic is null");
2268
2269     if (!CALEIsEnableBTAdapter(env))
2270     {
2271         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2272         return CA_STATUS_FAILED;
2273     }
2274
2275     // get BluetoothGatt.write characteristic method
2276     OIC_LOG(DEBUG, TAG, "write characteristic method");
2277     jmethodID jni_mid_writeCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2278                                                              "writeCharacteristic",
2279                                                              "(Landroid/bluetooth/"
2280                                                              "BluetoothGattCharacteristic;)Z");
2281     if (!jni_mid_writeCharacteristic)
2282     {
2283         OIC_LOG(ERROR, TAG, "jni_mid_writeCharacteristic is null");
2284         return CA_STATUS_FAILED;
2285     }
2286
2287     // call disconnect gatt method
2288     OIC_LOG(INFO, TAG, "CALL API - writeCharacteristic");
2289     jboolean ret = (jboolean)(*env)->CallBooleanMethod(env, bluetoothGatt,
2290                                                        jni_mid_writeCharacteristic,
2291                                                        gattCharacteristic);
2292     if (ret)
2293     {
2294         OIC_LOG(DEBUG, TAG, "writeCharacteristic is called successfully");
2295     }
2296     else
2297     {
2298         OIC_LOG(ERROR, TAG, "writeCharacteristic has failed");
2299         return CA_STATUS_FAILED;
2300     }
2301
2302     return CA_STATUS_OK;
2303 }
2304
2305 CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt)
2306 {
2307     VERIFY_NON_NULL(env, TAG, "env is null");
2308     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2309
2310     if (!CALEIsEnableBTAdapter(env))
2311     {
2312         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2313         return CA_STATUS_FAILED;
2314     }
2315
2316     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
2317     if (!jni_uuid)
2318     {
2319         OIC_LOG(ERROR, TAG, "jni_uuid is null");
2320         return CA_STATUS_FAILED;
2321     }
2322
2323     jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2324     if (!jni_obj_GattCharacteristic)
2325     {
2326         OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2327         return CA_STATUS_FAILED;
2328     }
2329
2330     OIC_LOG(DEBUG, TAG, "read characteristic method");
2331     jmethodID jni_mid_readCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2332                                                             "readCharacteristic",
2333                                                             "(Landroid/bluetooth/"
2334                                                             "BluetoothGattCharacteristic;)Z");
2335     if (!jni_mid_readCharacteristic)
2336     {
2337         OIC_LOG(ERROR, TAG, "jni_mid_readCharacteristic is null");
2338         return CA_STATUS_FAILED;
2339     }
2340
2341     // call disconnect gatt method
2342     OIC_LOG(INFO, TAG, "CALL API - readCharacteristic");
2343     jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_readCharacteristic,
2344                                              jni_obj_GattCharacteristic);
2345     if (ret)
2346     {
2347         OIC_LOG(DEBUG, TAG, "readCharacteristic success");
2348     }
2349     else
2350     {
2351         OIC_LOG(ERROR, TAG, "readCharacteristic has failed");
2352         return CA_STATUS_FAILED;
2353     }
2354
2355     return CA_STATUS_OK;
2356 }
2357
2358 CAResult_t CALEClientSetCharacteristicNotification(JNIEnv *env, jobject bluetoothGatt,
2359                                                    jobject characteristic)
2360 {
2361     VERIFY_NON_NULL(env, TAG, "env is null");
2362     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2363     VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2364
2365     if (!CALEIsEnableBTAdapter(env))
2366     {
2367         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2368         return CA_ADAPTER_NOT_ENABLED;
2369     }
2370
2371     // get BluetoothGatt.setCharacteristicNotification method
2372     OIC_LOG(DEBUG, TAG, "CALEClientSetCharacteristicNotification");
2373     jmethodID jni_mid_setNotification = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2374                                                          "setCharacteristicNotification",
2375                                                          "(Landroid/bluetooth/"
2376                                                          "BluetoothGattCharacteristic;Z)Z");
2377     if (!jni_mid_setNotification)
2378     {
2379         OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2380         return CA_STATUS_FAILED;
2381     }
2382
2383     OIC_LOG(INFO, TAG, "CALL API - setCharacteristicNotification");
2384     jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_setNotification,
2385                                              characteristic, JNI_TRUE);
2386     if (JNI_TRUE == ret)
2387     {
2388         OIC_LOG(DEBUG, TAG, "setCharacteristicNotification success");
2389     }
2390     else
2391     {
2392         OIC_LOG(ERROR, TAG, "setCharacteristicNotification has failed");
2393         return CA_STATUS_FAILED;
2394     }
2395
2396     return CA_STATUS_OK;
2397 }
2398
2399 jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID)
2400 {
2401     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2402     VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2403     VERIFY_NON_NULL_RET(characterUUID, TAG, "characterUUID is null", NULL);
2404
2405     if (!CALEIsEnableBTAdapter(env))
2406     {
2407         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2408         return NULL;
2409     }
2410
2411     // get BluetoothGatt.getService method
2412     OIC_LOG(DEBUG, TAG, "BluetoothGatt.getService");
2413     jmethodID jni_mid_getService = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2414                                                     "getService",
2415                                                     "(Ljava/util/UUID;)Landroid/bluetooth/"
2416                                                     "BluetoothGattService;");
2417     if (!jni_mid_getService)
2418     {
2419         OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2420         return NULL;
2421     }
2422
2423     jobject jni_obj_service_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2424     if (!jni_obj_service_uuid)
2425     {
2426         OIC_LOG(ERROR, TAG, "jni_obj_service_uuid is null");
2427         return NULL;
2428     }
2429
2430     // get bluetooth gatt service
2431     OIC_LOG(DEBUG, TAG, "request to get service");
2432     jobject jni_obj_gattService = (*env)->CallObjectMethod(env, bluetoothGatt, jni_mid_getService,
2433                                                            jni_obj_service_uuid);
2434     if (!jni_obj_gattService)
2435     {
2436         OIC_LOG(ERROR, TAG, "jni_obj_gattService is null");
2437         return NULL;
2438     }
2439
2440     // get bluetooth gatt service method
2441     jmethodID jni_mid_getCharacteristic = CAGetJNIMethodID(env, "android/bluetooth/"
2442                                                            "BluetoothGattService",
2443                                                            "getCharacteristic",
2444                                                            "(Ljava/util/UUID;)"
2445                                                            "Landroid/bluetooth/"
2446                                                            "BluetoothGattCharacteristic;");
2447     if (!jni_mid_getCharacteristic)
2448     {
2449         OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null");
2450         return NULL;
2451     }
2452
2453     const char* uuid = (*env)->GetStringUTFChars(env, characterUUID, NULL);
2454     if (!uuid)
2455     {
2456         OIC_LOG(ERROR, TAG, "uuid is null");
2457         return NULL;
2458     }
2459
2460     jobject jni_obj_tx_uuid = CALEClientGetUUIDObject(env, uuid);
2461     if (!jni_obj_tx_uuid)
2462     {
2463         OIC_LOG(ERROR, TAG, "jni_obj_tx_uuid is null");
2464         (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2465         return NULL;
2466     }
2467
2468     OIC_LOG(DEBUG, TAG, "request to get Characteristic");
2469     jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService,
2470                                                                   jni_mid_getCharacteristic,
2471                                                                   jni_obj_tx_uuid);
2472
2473     (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2474     return jni_obj_GattCharacteristic;
2475 }
2476
2477 jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data)
2478 {
2479     OIC_LOG(DEBUG, TAG, "CALEClientCreateGattCharacteristic");
2480     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2481     VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2482     VERIFY_NON_NULL_RET(data, TAG, "data is null", NULL);
2483
2484     if (!CALEIsEnableBTAdapter(env))
2485     {
2486         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2487         return NULL;
2488     }
2489
2490     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
2491     if (!jni_uuid)
2492     {
2493         OIC_LOG(ERROR, TAG, "jni_uuid is null");
2494         return NULL;
2495     }
2496
2497     jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2498     if (!jni_obj_GattCharacteristic)
2499     {
2500         OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2501         return NULL;
2502     }
2503
2504     jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth"
2505                                                             "/BluetoothGattCharacteristic");
2506     if (!jni_cid_BTGattCharacteristic)
2507     {
2508         OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
2509         return NULL;
2510     }
2511
2512     OIC_LOG(DEBUG, TAG, "set value in Characteristic");
2513     jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "setValue",
2514                                                      "([B)Z");
2515     if (!jni_mid_setValue)
2516     {
2517         OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2518         return NULL;
2519     }
2520
2521     jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue,
2522                                              data);
2523     if (JNI_TRUE == ret)
2524     {
2525         OIC_LOG(DEBUG, TAG, "the locally stored value has been set");
2526     }
2527     else
2528     {
2529         OIC_LOG(ERROR, TAG, "the locally stored value hasn't been set");
2530         return NULL;
2531     }
2532
2533     // set Write Type
2534     jmethodID jni_mid_setWriteType = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic,
2535                                                          "setWriteType", "(I)V");
2536     if (!jni_mid_setWriteType)
2537     {
2538         OIC_LOG(ERROR, TAG, "jni_mid_setWriteType is null");
2539         return NULL;
2540     }
2541
2542     jfieldID jni_fid_no_response = (*env)->GetStaticFieldID(env, jni_cid_BTGattCharacteristic,
2543                                                             "WRITE_TYPE_NO_RESPONSE", "I");
2544     if (!jni_fid_no_response)
2545     {
2546         OIC_LOG(ERROR, TAG, "jni_fid_no_response is not available");
2547         return NULL;
2548     }
2549
2550     jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTGattCharacteristic,
2551                                                  jni_fid_no_response);
2552
2553     (*env)->CallVoidMethod(env, jni_obj_GattCharacteristic, jni_mid_setWriteType, jni_int_val);
2554
2555     return jni_obj_GattCharacteristic;
2556 }
2557
2558 jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteristic)
2559 {
2560     VERIFY_NON_NULL_RET(characteristic, TAG, "characteristic is null", NULL);
2561     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2562
2563     if (!CALEIsEnableBTAdapter(env))
2564     {
2565         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2566         return NULL;
2567     }
2568
2569     jmethodID jni_mid_getValue  = CAGetJNIMethodID(env, "android/bluetooth/"
2570                                                    "BluetoothGattCharacteristic",
2571                                                    "getValue", "()[B");
2572     if (!jni_mid_getValue)
2573     {
2574         OIC_LOG(ERROR, TAG, "jni_mid_getValue is null");
2575         return NULL;
2576     }
2577
2578     jbyteArray jni_obj_data_array = (*env)->CallObjectMethod(env, characteristic,
2579                                                              jni_mid_getValue);
2580     return jni_obj_data_array;
2581 }
2582
2583 CAResult_t CALEClientCreateUUIDList()
2584 {
2585     if (!g_jvm)
2586     {
2587         OIC_LOG(ERROR, TAG, "g_jvm is null");
2588         return CA_STATUS_FAILED;
2589     }
2590
2591     bool isAttached = false;
2592     JNIEnv* env = NULL;
2593     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
2594     if (JNI_OK != res)
2595     {
2596         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
2597         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
2598
2599         if (JNI_OK != res)
2600         {
2601             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
2602             return CA_STATUS_FAILED;
2603         }
2604         isAttached = true;
2605     }
2606
2607     // create new object array
2608     jclass jni_cid_uuid_list = (*env)->FindClass(env, CLASSPATH_BT_UUID);
2609     if (!jni_cid_uuid_list)
2610     {
2611         OIC_LOG(ERROR, TAG, "jni_cid_uuid_list is null");
2612         goto error_exit;
2613     }
2614
2615     jobjectArray jni_obj_uuid_list = (jobjectArray)(*env)->NewObjectArray(env, 1,
2616                                                                           jni_cid_uuid_list, NULL);
2617     if (!jni_obj_uuid_list)
2618     {
2619         OIC_LOG(ERROR, TAG, "jni_obj_uuid_list is null");
2620         goto error_exit;
2621     }
2622
2623     // make uuid list
2624     jobject jni_obj_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2625     if (!jni_obj_uuid)
2626     {
2627         OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
2628         goto error_exit;
2629     }
2630     (*env)->SetObjectArrayElement(env, jni_obj_uuid_list, 0, jni_obj_uuid);
2631
2632     g_uuidList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list);
2633
2634     if (isAttached)
2635     {
2636         (*g_jvm)->DetachCurrentThread(g_jvm);
2637     }
2638
2639     return CA_STATUS_OK;
2640
2641     // error label.
2642 error_exit:
2643
2644     if (isAttached)
2645     {
2646         (*g_jvm)->DetachCurrentThread(g_jvm);
2647     }
2648     return CA_STATUS_FAILED;
2649 }
2650
2651 CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt,
2652                                          jobject characteristic)
2653 {
2654     VERIFY_NON_NULL(env, TAG, "env is null");
2655     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2656     VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2657
2658     if (!CALEIsEnableBTAdapter(env))
2659     {
2660         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2661         return CA_ADAPTER_NOT_ENABLED;
2662     }
2663
2664     OIC_LOG(DEBUG, TAG, "CALEClientSetUUIDToDescriptor");
2665     jmethodID jni_mid_getDescriptor  = CAGetJNIMethodID(env, "android/bluetooth/"
2666                                                         "BluetoothGattCharacteristic",
2667                                                         "getDescriptor",
2668                                                         "(Ljava/util/UUID;)Landroid/bluetooth/"
2669                                                         "BluetoothGattDescriptor;");
2670     if (!jni_mid_getDescriptor)
2671     {
2672         OIC_LOG(ERROR, TAG, "jni_mid_getDescriptor is null");
2673         return CA_STATUS_FAILED;
2674     }
2675
2676     jobject jni_obj_cc_uuid = CALEClientGetUUIDObject(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID);
2677     if (!jni_obj_cc_uuid)
2678     {
2679         OIC_LOG(ERROR, TAG, "jni_obj_cc_uuid is null");
2680         return CA_STATUS_FAILED;
2681     }
2682
2683     OIC_LOG(DEBUG, TAG, "request to get descriptor");
2684     jobject jni_obj_descriptor = (*env)->CallObjectMethod(env, characteristic,
2685                                                           jni_mid_getDescriptor, jni_obj_cc_uuid);
2686     if (!jni_obj_descriptor)
2687     {
2688         OIC_LOG(INFO, TAG, "jni_obj_descriptor is null");
2689         return CA_NOT_SUPPORTED;
2690     }
2691
2692     OIC_LOG(DEBUG, TAG, "set value in descriptor");
2693     jclass jni_cid_descriptor = (*env)->FindClass(env,
2694                                                   "android/bluetooth/BluetoothGattDescriptor");
2695     if (!jni_cid_descriptor)
2696     {
2697         OIC_LOG(ERROR, TAG, "jni_cid_descriptor is null");
2698         return CA_STATUS_FAILED;
2699     }
2700
2701     jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_descriptor, "setValue", "([B)Z");
2702     if (!jni_mid_setValue)
2703     {
2704         OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2705         return CA_STATUS_FAILED;
2706     }
2707
2708     jfieldID jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor,
2709                                                           "ENABLE_NOTIFICATION_VALUE", "[B");
2710     if (!jni_fid_NotiValue)
2711     {
2712         OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null");
2713         return CA_STATUS_FAILED;
2714     }
2715
2716     OIC_LOG(DEBUG, TAG, "get ENABLE_NOTIFICATION_VALUE");
2717
2718     jboolean jni_setvalue = (*env)->CallBooleanMethod(
2719             env, jni_obj_descriptor, jni_mid_setValue,
2720             (jbyteArray)(*env)->GetStaticObjectField(env, jni_cid_descriptor, jni_fid_NotiValue));
2721     if (jni_setvalue)
2722     {
2723         OIC_LOG(DEBUG, TAG, "setValue success");
2724     }
2725     else
2726     {
2727         OIC_LOG(ERROR, TAG, "setValue has failed");
2728         return CA_STATUS_FAILED;
2729     }
2730
2731     jmethodID jni_mid_writeDescriptor  = CAGetJNIMethodID(env, "android/bluetooth/BluetoothGatt",
2732                                                           "writeDescriptor",
2733                                                           "(Landroid/bluetooth/"
2734                                                           "BluetoothGattDescriptor;)Z");
2735     if (!jni_mid_writeDescriptor)
2736     {
2737         OIC_LOG(ERROR, TAG, "jni_mid_writeDescriptor is null");
2738         return CA_STATUS_FAILED;
2739     }
2740
2741     OIC_LOG(INFO, TAG, "CALL API - writeDescriptor");
2742     jboolean jni_ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_writeDescriptor,
2743                                                  jni_obj_descriptor);
2744     if (jni_ret)
2745     {
2746         OIC_LOG(DEBUG, TAG, "writeDescriptor success");
2747     }
2748     else
2749     {
2750         OIC_LOG(ERROR, TAG, "writeDescriptor has failed");
2751         return CA_STATUS_FAILED;
2752     }
2753
2754     return CA_STATUS_OK;
2755 }
2756
2757 void CALEClientCreateScanDeviceList(JNIEnv *env)
2758 {
2759     OIC_LOG(DEBUG, TAG, "CALEClientCreateScanDeviceList");
2760     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
2761
2762     ca_mutex_lock(g_deviceListMutex);
2763     // create new object array
2764     if (g_deviceList == NULL)
2765     {
2766         OIC_LOG(DEBUG, TAG, "Create device list");
2767
2768         g_deviceList = u_arraylist_create();
2769     }
2770     ca_mutex_unlock(g_deviceListMutex);
2771 }
2772
2773 CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device)
2774 {
2775     VERIFY_NON_NULL(device, TAG, "device is null");
2776     VERIFY_NON_NULL(env, TAG, "env is null");
2777
2778     ca_mutex_lock(g_deviceListMutex);
2779
2780     if (!g_deviceList)
2781     {
2782         OIC_LOG(ERROR, TAG, "gdevice_list is null");
2783         CALEClientStopScanWithInterval();
2784
2785         ca_mutex_unlock(g_deviceListMutex);
2786         return CA_STATUS_FAILED;
2787     }
2788
2789     jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2790     if (!jni_remoteAddress)
2791     {
2792         OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2793         ca_mutex_unlock(g_deviceListMutex);
2794         return CA_STATUS_FAILED;
2795     }
2796
2797     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2798     if (!remoteAddress)
2799     {
2800         OIC_LOG(ERROR, TAG, "remoteAddress is null");
2801         (*env)->DeleteLocalRef(env, jni_remoteAddress);
2802         ca_mutex_unlock(g_deviceListMutex);
2803         return CA_STATUS_FAILED;
2804     }
2805
2806     if (!CALEClientIsDeviceInScanDeviceList(env, remoteAddress))
2807     {
2808         jobject gdevice = (*env)->NewGlobalRef(env, device);
2809         u_arraylist_add(g_deviceList, gdevice);
2810         ca_cond_signal(g_deviceDescCond);
2811         OIC_LOG_V(DEBUG, TAG, "Added a new BT Device in deviceList [%s]", remoteAddress);
2812     }
2813     (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2814     (*env)->DeleteLocalRef(env, jni_remoteAddress);
2815
2816     ca_mutex_unlock(g_deviceListMutex);
2817
2818     return CA_STATUS_OK;
2819 }
2820
2821 bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress)
2822 {
2823     VERIFY_NON_NULL_RET(env, TAG, "env is null", true);
2824     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2825
2826     if (!g_deviceList)
2827     {
2828         OIC_LOG(DEBUG, TAG, "g_deviceList is null");
2829         return true;
2830     }
2831
2832     uint32_t length = u_arraylist_length(g_deviceList);
2833     for (uint32_t index = 0; index < length; index++)
2834     {
2835         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2836         if (!jarrayObj)
2837         {
2838             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2839             return true;
2840         }
2841
2842         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2843         if (!jni_setAddress)
2844         {
2845             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2846             return true;
2847         }
2848
2849         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2850         if (!setAddress)
2851         {
2852             OIC_LOG(ERROR, TAG, "setAddress is null");
2853             (*env)->DeleteLocalRef(env, jni_setAddress);
2854             return true;
2855         }
2856
2857         if (!strcmp(remoteAddress, setAddress))
2858         {
2859             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2860             (*env)->DeleteLocalRef(env, jni_setAddress);
2861             return true;
2862         }
2863
2864         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2865         (*env)->DeleteLocalRef(env, jni_setAddress);
2866     }
2867
2868     OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in scanned device list", remoteAddress);
2869
2870     return false;
2871 }
2872
2873 CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env)
2874 {
2875     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices");
2876     VERIFY_NON_NULL(env, TAG, "env is null");
2877
2878     ca_mutex_lock(g_deviceListMutex);
2879
2880     if (!g_deviceList)
2881     {
2882         OIC_LOG(ERROR, TAG, "g_deviceList is null");
2883         ca_mutex_unlock(g_deviceListMutex);
2884         return CA_STATUS_FAILED;
2885     }
2886
2887     uint32_t length = u_arraylist_length(g_deviceList);
2888     for (uint32_t index = 0; index < length; index++)
2889     {
2890         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2891         if (!jarrayObj)
2892         {
2893             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2894             continue;
2895         }
2896         (*env)->DeleteGlobalRef(env, jarrayObj);
2897         jarrayObj = NULL;
2898     }
2899
2900     OICFree(g_deviceList);
2901     g_deviceList = NULL;
2902
2903     ca_mutex_unlock(g_deviceListMutex);
2904     return CA_STATUS_OK;
2905 }
2906
2907 CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address)
2908 {
2909     OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceInScanDeviceList");
2910     VERIFY_NON_NULL(address, TAG, "address is null");
2911     VERIFY_NON_NULL(env, TAG, "env is null");
2912
2913     ca_mutex_lock(g_deviceListMutex);
2914
2915     if (!g_deviceList)
2916     {
2917         OIC_LOG(ERROR, TAG, "g_deviceList is null");
2918         ca_mutex_unlock(g_deviceListMutex);
2919         return CA_STATUS_FAILED;
2920     }
2921
2922     uint32_t length = u_arraylist_length(g_deviceList);
2923     for (uint32_t index = 0; index < length; index++)
2924     {
2925         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2926         if (!jarrayObj)
2927         {
2928             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2929             ca_mutex_unlock(g_deviceListMutex);
2930             return CA_STATUS_FAILED;
2931         }
2932
2933         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2934         if (!jni_setAddress)
2935         {
2936             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2937             ca_mutex_unlock(g_deviceListMutex);
2938             return CA_STATUS_FAILED;
2939         }
2940
2941         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2942         if (!setAddress)
2943         {
2944             OIC_LOG(ERROR, TAG, "setAddress is null");
2945             ca_mutex_unlock(g_deviceListMutex);
2946             return CA_STATUS_FAILED;
2947         }
2948
2949         const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
2950         if (!remoteAddress)
2951         {
2952             OIC_LOG(ERROR, TAG, "remoteAddress is null");
2953             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2954             ca_mutex_unlock(g_deviceListMutex);
2955             return CA_STATUS_FAILED;
2956         }
2957
2958         if (!strcmp(setAddress, remoteAddress))
2959         {
2960             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2961             (*env)->DeleteGlobalRef(env, jarrayObj);
2962             jarrayObj = NULL;
2963             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2964             (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2965
2966             if (NULL == u_arraylist_remove(g_deviceList, index))
2967             {
2968                 OIC_LOG(ERROR, TAG, "List removal failed.");
2969                 ca_mutex_unlock(g_deviceListMutex);
2970                 return CA_STATUS_FAILED;
2971             }
2972             ca_mutex_unlock(g_deviceListMutex);
2973             return CA_STATUS_OK;
2974         }
2975         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2976         (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2977     }
2978
2979     ca_mutex_unlock(g_deviceListMutex);
2980     OIC_LOG(DEBUG, TAG, "There are no object in the device list");
2981
2982     return CA_STATUS_OK;
2983 }
2984
2985 /**
2986  * Gatt Object List
2987  */
2988
2989 CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt)
2990 {
2991     OIC_LOG(DEBUG, TAG, "CALEClientAddGattobjToList");
2992     VERIFY_NON_NULL(env, TAG, "env is null");
2993     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2994
2995     ca_mutex_lock(g_gattObjectMutex);
2996
2997     if (!g_gattObjectList)
2998     {
2999         OIC_LOG(ERROR, TAG, "g_gattObjectList is not available");
3000         ca_mutex_unlock(g_gattObjectMutex);
3001         return CA_STATUS_FAILED;
3002     }
3003
3004     jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
3005     if (!jni_remoteAddress)
3006     {
3007         OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
3008         ca_mutex_unlock(g_gattObjectMutex);
3009         return CA_STATUS_FAILED;
3010     }
3011
3012     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
3013     if (!remoteAddress)
3014     {
3015         OIC_LOG(ERROR, TAG, "remoteAddress is null");
3016         ca_mutex_unlock(g_gattObjectMutex);
3017         return CA_STATUS_FAILED;
3018     }
3019
3020     OIC_LOG_V(DEBUG, TAG, "remote address : %s", remoteAddress);
3021     if (!CALEClientIsGattObjInList(env, remoteAddress))
3022     {
3023         jobject newGatt = (*env)->NewGlobalRef(env, gatt);
3024         u_arraylist_add(g_gattObjectList, newGatt);
3025         OIC_LOG(INFO, TAG, "added a newGatt object to gattObjectList");
3026     }
3027
3028     (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3029     ca_mutex_unlock(g_gattObjectMutex);
3030     return CA_STATUS_OK;
3031 }
3032
3033 bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress)
3034 {
3035     OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList");
3036     VERIFY_NON_NULL(env, TAG, "env is null");
3037     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
3038
3039     uint32_t length = u_arraylist_length(g_gattObjectList);
3040     for (uint32_t index = 0; index < length; index++)
3041     {
3042
3043         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3044         if (!jarrayObj)
3045         {
3046             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3047             return true;
3048         }
3049
3050         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3051         if (!jni_setAddress)
3052         {
3053             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3054             return true;
3055         }
3056
3057         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3058         if (!setAddress)
3059         {
3060             OIC_LOG(ERROR, TAG, "setAddress is null");
3061             return true;
3062         }
3063
3064         if (!strcmp(remoteAddress, setAddress))
3065         {
3066             OIC_LOG(DEBUG, TAG, "the device is already set");
3067             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3068             return true;
3069         }
3070         else
3071         {
3072             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3073             continue;
3074         }
3075     }
3076
3077     OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added");
3078     return false;
3079 }
3080
3081 jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress)
3082 {
3083     OIC_LOG(DEBUG, TAG, "CALEClientGetGattObjInList");
3084     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
3085     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
3086
3087     ca_mutex_lock(g_gattObjectMutex);
3088     uint32_t length = u_arraylist_length(g_gattObjectList);
3089     for (uint32_t index = 0; index < length; index++)
3090     {
3091         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3092         if (!jarrayObj)
3093         {
3094             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3095             ca_mutex_unlock(g_gattObjectMutex);
3096             return NULL;
3097         }
3098
3099         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3100         if (!jni_setAddress)
3101         {
3102             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3103             ca_mutex_unlock(g_gattObjectMutex);
3104             return NULL;
3105         }
3106
3107         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3108         if (!setAddress)
3109         {
3110             OIC_LOG(ERROR, TAG, "setAddress is null");
3111             ca_mutex_unlock(g_gattObjectMutex);
3112             return NULL;
3113         }
3114
3115         if (!strcmp(remoteAddress, setAddress))
3116         {
3117             OIC_LOG(DEBUG, TAG, "the device is already set");
3118             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3119             ca_mutex_unlock(g_gattObjectMutex);
3120             return jarrayObj;
3121         }
3122         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3123     }
3124
3125     ca_mutex_unlock(g_gattObjectMutex);
3126     OIC_LOG(DEBUG, TAG, "There are no the gatt object in list");
3127     return NULL;
3128 }
3129
3130 CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env)
3131 {
3132     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs");
3133     VERIFY_NON_NULL(env, TAG, "env is null");
3134
3135     ca_mutex_lock(g_gattObjectMutex);
3136     if (!g_gattObjectList)
3137     {
3138         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3139         ca_mutex_unlock(g_gattObjectMutex);
3140         return CA_STATUS_OK;
3141     }
3142
3143     uint32_t length = u_arraylist_length(g_gattObjectList);
3144     for (uint32_t index = 0; index < length; index++)
3145     {
3146         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3147         if (!jarrayObj)
3148         {
3149             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3150             continue;
3151         }
3152         (*env)->DeleteGlobalRef(env, jarrayObj);
3153         jarrayObj = NULL;
3154     }
3155
3156     OICFree(g_gattObjectList);
3157     g_gattObjectList = NULL;
3158     OIC_LOG(INFO, TAG, "g_gattObjectList is removed");
3159     ca_mutex_unlock(g_gattObjectMutex);
3160     return CA_STATUS_OK;
3161 }
3162
3163 CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt)
3164 {
3165     OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObj");
3166     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
3167     VERIFY_NON_NULL(env, TAG, "env is null");
3168
3169     ca_mutex_lock(g_gattObjectMutex);
3170     if (!g_gattObjectList)
3171     {
3172         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3173         ca_mutex_unlock(g_gattObjectMutex);
3174         return CA_STATUS_OK;
3175     }
3176
3177     uint32_t length = u_arraylist_length(g_gattObjectList);
3178     for (uint32_t index = 0; index < length; index++)
3179     {
3180         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3181         if (!jarrayObj)
3182         {
3183             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3184             ca_mutex_unlock(g_gattObjectMutex);
3185             return CA_STATUS_FAILED;
3186         }
3187
3188         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3189         if (!jni_setAddress)
3190         {
3191             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3192             ca_mutex_unlock(g_gattObjectMutex);
3193             return CA_STATUS_FAILED;
3194         }
3195
3196         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3197         if (!setAddress)
3198         {
3199             OIC_LOG(ERROR, TAG, "setAddress is null");
3200             ca_mutex_unlock(g_gattObjectMutex);
3201             return CA_STATUS_FAILED;
3202         }
3203
3204         jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
3205         if (!jni_remoteAddress)
3206         {
3207             OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
3208             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3209             ca_mutex_unlock(g_gattObjectMutex);
3210             return CA_STATUS_FAILED;
3211         }
3212
3213         const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
3214         if (!remoteAddress)
3215         {
3216             OIC_LOG(ERROR, TAG, "remoteAddress is null");
3217             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3218             ca_mutex_unlock(g_gattObjectMutex);
3219             return CA_STATUS_FAILED;
3220         }
3221
3222         if (!strcmp(setAddress, remoteAddress))
3223         {
3224             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3225             (*env)->DeleteGlobalRef(env, jarrayObj);
3226             jarrayObj = NULL;
3227             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3228             (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3229
3230             if (NULL == u_arraylist_remove(g_gattObjectList, index))
3231             {
3232                 OIC_LOG(ERROR, TAG, "List removal failed.");
3233                 ca_mutex_unlock(g_gattObjectMutex);
3234                 return CA_STATUS_FAILED;
3235             }
3236             ca_mutex_unlock(g_gattObjectMutex);
3237             return CA_STATUS_OK;
3238         }
3239         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3240         (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3241     }
3242
3243     ca_mutex_unlock(g_gattObjectMutex);
3244     OIC_LOG(DEBUG, TAG, "there are no target object");
3245     return CA_STATUS_OK;
3246 }
3247
3248 CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr)
3249 {
3250     OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObjForAddr");
3251     VERIFY_NON_NULL(addr, TAG, "addr is null");
3252     VERIFY_NON_NULL(env, TAG, "env is null");
3253
3254     ca_mutex_lock(g_gattObjectMutex);
3255     if (!g_gattObjectList)
3256     {
3257         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3258         ca_mutex_unlock(g_gattObjectMutex);
3259         return CA_STATUS_OK;
3260     }
3261
3262     uint32_t length = u_arraylist_length(g_gattObjectList);
3263     for (uint32_t index = 0; index < length; index++)
3264     {
3265         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3266         if (!jarrayObj)
3267         {
3268             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3269             ca_mutex_unlock(g_gattObjectMutex);
3270             return CA_STATUS_FAILED;
3271         }
3272
3273         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3274         if (!jni_setAddress)
3275         {
3276             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3277             ca_mutex_unlock(g_gattObjectMutex);
3278             return CA_STATUS_FAILED;
3279         }
3280
3281         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3282         if (!setAddress)
3283         {
3284             OIC_LOG(ERROR, TAG, "setAddress is null");
3285             ca_mutex_unlock(g_gattObjectMutex);
3286             return CA_STATUS_FAILED;
3287         }
3288
3289         const char* remoteAddress = (*env)->GetStringUTFChars(env, addr, NULL);
3290         if (!remoteAddress)
3291         {
3292             OIC_LOG(ERROR, TAG, "remoteAddress is null");
3293             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3294             ca_mutex_unlock(g_gattObjectMutex);
3295             return CA_STATUS_FAILED;
3296         }
3297
3298         if (!strcmp(setAddress, remoteAddress))
3299         {
3300             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3301             (*env)->DeleteGlobalRef(env, jarrayObj);
3302             jarrayObj = NULL;
3303             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3304             (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3305             if (NULL == u_arraylist_remove(g_gattObjectList, index))
3306             {
3307                 OIC_LOG(ERROR, TAG, "List removal failed.");
3308                 ca_mutex_unlock(g_gattObjectMutex);
3309                 return CA_STATUS_FAILED;
3310             }
3311             ca_mutex_unlock(g_gattObjectMutex);
3312             return CA_STATUS_OK;
3313         }
3314         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3315         (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3316     }
3317
3318     ca_mutex_unlock(g_gattObjectMutex);
3319     OIC_LOG(DEBUG, TAG, "there are no target object");
3320     return CA_STATUS_FAILED;
3321 }
3322
3323 jstring CALEClientGetLEAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
3324 {
3325     OIC_LOG(DEBUG, TAG, "CALEClientGetLEAddressFromBTDevice");
3326
3327     VERIFY_NON_NULL_RET(env, TAG, "env", NULL);
3328     VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice", NULL);
3329
3330     // get Bluetooth Address
3331     jstring jni_btTargetAddress = CALEGetAddressFromBTDevice(env, bluetoothDevice);
3332     if (!jni_btTargetAddress)
3333     {
3334         OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3335         return NULL;
3336     }
3337
3338     const char* targetAddress = (*env)->GetStringUTFChars(env, jni_btTargetAddress, NULL);
3339     if (!targetAddress)
3340     {
3341         OIC_LOG(ERROR, TAG, "targetAddress is not available");
3342         return NULL;
3343     }
3344
3345     // get method ID of getDevice()
3346     jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
3347                                                    "getDevice", METHODID_BT_DEVICE);
3348     if (!jni_mid_getDevice)
3349     {
3350         OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
3351         (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3352         return NULL;
3353     }
3354
3355     ca_mutex_lock(g_gattObjectMutex);
3356
3357     size_t length = u_arraylist_length(g_gattObjectList);
3358     OIC_LOG_V(DEBUG, TAG, "length of gattObjectList : %d", length);
3359     OIC_LOG_V(DEBUG, TAG, "targetAddress : %s", targetAddress);
3360
3361     for (size_t index = 0; index < length; index++)
3362     {
3363         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3364         if (!jarrayObj)
3365         {
3366             ca_mutex_unlock(g_gattObjectMutex);
3367             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3368             (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3369             return NULL;
3370         }
3371
3372         jobject jni_obj_device = (*env)->CallObjectMethod(env, jarrayObj, jni_mid_getDevice);
3373         if (!jni_obj_device)
3374         {
3375             ca_mutex_unlock(g_gattObjectMutex);
3376             OIC_LOG(ERROR, TAG, "jni_obj_device is null");
3377             (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3378             return NULL;
3379         }
3380
3381         jstring jni_btAddress = CALEGetAddressFromBTDevice(env, jni_obj_device);
3382         if (!jni_btAddress)
3383         {
3384             ca_mutex_unlock(g_gattObjectMutex);
3385             OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3386             (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3387             return NULL;
3388         }
3389
3390         const char* btAddress = (*env)->GetStringUTFChars(env, jni_btAddress, NULL);
3391         if (!btAddress)
3392         {
3393             ca_mutex_unlock(g_gattObjectMutex);
3394             OIC_LOG(ERROR, TAG, "btAddress is not available");
3395             (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3396             return NULL;
3397         }
3398
3399         OIC_LOG_V(DEBUG, TAG, "btAddress : %s (idx: %d)", btAddress, index);
3400         if (!strcmp(targetAddress, btAddress))
3401         {
3402             OIC_LOG(DEBUG, TAG, "Found Gatt object from BT device");
3403
3404             // get LE address
3405             jstring jni_LEAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3406             if (!jni_LEAddress)
3407             {
3408                 OIC_LOG(ERROR, TAG, "jni_LEAddress is null");
3409             }
3410             ca_mutex_unlock(g_gattObjectMutex);
3411             (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3412             (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3413             (*env)->DeleteLocalRef(env, jni_btAddress);
3414             (*env)->DeleteLocalRef(env, jni_obj_device);
3415             return jni_LEAddress;
3416         }
3417         (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3418         (*env)->DeleteLocalRef(env, jni_btAddress);
3419         (*env)->DeleteLocalRef(env, jni_obj_device);
3420     }
3421     ca_mutex_unlock(g_gattObjectMutex);
3422
3423     (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3424     OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in gattObjectList", targetAddress);
3425     return NULL;
3426 }
3427
3428 /**
3429  * BT State List
3430  */
3431
3432 CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type,
3433                                        uint16_t target_state)
3434 {
3435     VERIFY_NON_NULL(address, TAG, "address is null");
3436     VERIFY_NON_NULL(address, TAG, "state_type is null");
3437     VERIFY_NON_NULL(address, TAG, "target_state is null");
3438
3439     if (!g_deviceStateList)
3440     {
3441         OIC_LOG(ERROR, TAG, "gdevice_list is null");
3442         return CA_STATUS_FAILED;
3443     }
3444
3445     ca_mutex_lock(g_deviceStateListMutex);
3446
3447     if (CALEClientIsDeviceInList(address))
3448     {
3449         CALEState_t* curState = CALEClientGetStateInfo(address);
3450         if(!curState)
3451         {
3452             OIC_LOG(ERROR, TAG, "curState is null");
3453             ca_mutex_unlock(g_deviceStateListMutex);
3454             return CA_STATUS_FAILED;
3455         }
3456
3457         switch(state_type)
3458         {
3459             case CA_LE_CONNECTION_STATE:
3460                 curState->connectedState = target_state;
3461                 break;
3462             case CA_LE_SEND_STATE:
3463                 curState->sendState = target_state;
3464                 break;
3465             default:
3466                 break;
3467         }
3468         OIC_LOG_V(INFO, TAG, "update state - addr : %s, conn : %d, send : %d, ACFlag : %d",
3469                   curState->address, curState->connectedState, curState->sendState,
3470                   curState->autoConnectFlag);
3471     }
3472     else /** state is added newly **/
3473     {
3474         if (strlen(address) > CA_MACADDR_SIZE)
3475         {
3476             OIC_LOG(ERROR, TAG, "address is not proper");
3477             ca_mutex_unlock(g_deviceStateListMutex);
3478             return CA_STATUS_INVALID_PARAM;
3479         }
3480
3481         CALEState_t *newstate = (CALEState_t*) OICCalloc(1, sizeof(*newstate));
3482         if (!newstate)
3483         {
3484             OIC_LOG(ERROR, TAG, "out of memory");
3485             ca_mutex_unlock(g_deviceStateListMutex);
3486             return CA_MEMORY_ALLOC_FAILED;
3487         }
3488
3489         OICStrcpy(newstate->address, sizeof(newstate->address), address);
3490
3491         switch(state_type)
3492         {
3493             case CA_LE_CONNECTION_STATE:
3494                 newstate->connectedState = target_state;
3495                 newstate->sendState = STATE_SEND_NONE;
3496                 break;
3497             case CA_LE_SEND_STATE:
3498                 newstate->connectedState = STATE_DISCONNECTED;
3499                 newstate->sendState = target_state;
3500                 break;
3501             default:
3502                 break;
3503         }
3504         OIC_LOG_V(INFO, TAG, "add a new state to List - addr : %s, "
3505                   "conn : %d, send : %d, ACFlag : %d",
3506                   newstate->address, newstate->connectedState, newstate->sendState,
3507                   newstate->autoConnectFlag);
3508         u_arraylist_add(g_deviceStateList, newstate); // update new state
3509     }
3510     ca_mutex_unlock(g_deviceStateListMutex);
3511
3512     return CA_STATUS_OK;
3513 }
3514
3515 bool CALEClientIsDeviceInList(const char* remoteAddress)
3516 {
3517     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3518
3519     if (!g_deviceStateList)
3520     {
3521         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3522         return false;
3523     }
3524
3525     uint32_t length = u_arraylist_length(g_deviceStateList);
3526     for (uint32_t index = 0; index < length; index++)
3527     {
3528         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3529         if (!state)
3530         {
3531             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3532             return false;
3533         }
3534
3535         if (!strcmp(remoteAddress, state->address))
3536         {
3537             OIC_LOG(DEBUG, TAG, "the device is already set");
3538             return true;
3539         }
3540         else
3541         {
3542             continue;
3543         }
3544     }
3545
3546     OIC_LOG(DEBUG, TAG, "there are no the device in list.");
3547     return false;
3548 }
3549
3550 CAResult_t CALEClientRemoveAllDeviceState()
3551 {
3552     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllDeviceState");
3553
3554     ca_mutex_lock(g_deviceStateListMutex);
3555     if (!g_deviceStateList)
3556     {
3557         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3558         ca_mutex_unlock(g_deviceStateListMutex);
3559         return CA_STATUS_FAILED;
3560     }
3561
3562     uint32_t length = u_arraylist_length(g_deviceStateList);
3563     for (uint32_t index = 0; index < length; index++)
3564     {
3565         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3566         if (!state)
3567         {
3568             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3569             continue;
3570         }
3571         OICFree(state);
3572     }
3573
3574     OICFree(g_deviceStateList);
3575     g_deviceStateList = NULL;
3576     ca_mutex_unlock(g_deviceStateListMutex);
3577
3578     return CA_STATUS_OK;
3579 }
3580
3581 CAResult_t CALEClientResetDeviceStateForAll()
3582 {
3583     OIC_LOG(DEBUG, TAG, "CALEClientResetDeviceStateForAll");
3584
3585     ca_mutex_lock(g_deviceStateListMutex);
3586     if (!g_deviceStateList)
3587     {
3588         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3589         ca_mutex_unlock(g_deviceStateListMutex);
3590         return CA_STATUS_FAILED;
3591     }
3592
3593     size_t length = u_arraylist_length(g_deviceStateList);
3594     for (size_t index = 0; index < length; index++)
3595     {
3596         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3597         if (!state)
3598         {
3599             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3600             continue;
3601         }
3602
3603         // autoConnectFlag value will be not changed,
3604         // since it has reset only termination case.
3605         state->connectedState = STATE_DISCONNECTED;
3606         state->sendState = STATE_SEND_NONE;
3607     }
3608     ca_mutex_unlock(g_deviceStateListMutex);
3609
3610     return CA_STATUS_OK;
3611 }
3612
3613 CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress)
3614 {
3615     OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceState");
3616     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
3617
3618     if (!g_deviceStateList)
3619     {
3620         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3621         return CA_STATUS_FAILED;
3622     }
3623
3624     uint32_t length = u_arraylist_length(g_deviceStateList);
3625     for (uint32_t index = 0; index < length; index++)
3626     {
3627         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3628         if (!state)
3629         {
3630             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3631             continue;
3632         }
3633
3634         if (!strcmp(state->address, remoteAddress))
3635         {
3636             OIC_LOG_V(DEBUG, TAG, "remove state : %s", state->address);
3637
3638             CALEState_t* targetState  = (CALEState_t*)u_arraylist_remove(g_deviceStateList,
3639                                                                          index);
3640             if (NULL == targetState)
3641             {
3642                 OIC_LOG(ERROR, TAG, "List removal failed.");
3643                 return CA_STATUS_FAILED;
3644             }
3645
3646             OICFree(targetState);
3647             return CA_STATUS_OK;
3648         }
3649     }
3650
3651     return CA_STATUS_OK;
3652 }
3653
3654 CALEState_t* CALEClientGetStateInfo(const char* remoteAddress)
3655 {
3656     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
3657
3658     if (!g_deviceStateList)
3659     {
3660         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3661         return NULL;
3662     }
3663
3664     uint32_t length = u_arraylist_length(g_deviceStateList);
3665     OIC_LOG_V(DEBUG, TAG, "length of deviceStateList : %d", length);
3666     OIC_LOG_V(DEBUG, TAG, "target address : %s", remoteAddress);
3667
3668     for (uint32_t index = 0; index < length; index++)
3669     {
3670         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3671         if (!state)
3672         {
3673             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3674             continue;
3675         }
3676
3677         OIC_LOG_V(DEBUG, TAG, "state address : %s (idx: %d)", state->address, index);
3678
3679         if (!strcmp(state->address, remoteAddress))
3680         {
3681             OIC_LOG(DEBUG, TAG, "found state");
3682             return state;
3683         }
3684     }
3685
3686     OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in deviceStateList", remoteAddress);
3687     return NULL;
3688 }
3689
3690 bool CALEClientIsValidState(const char* remoteAddress, uint16_t state_type,
3691                              uint16_t target_state)
3692 {
3693     OIC_LOG_V(DEBUG, TAG, "CALEClientIsValidState : type[%d], target state[%d]",
3694               state_type, target_state);
3695     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3696
3697     ca_mutex_lock(g_deviceStateListMutex);
3698     if (!g_deviceStateList)
3699     {
3700         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3701         ca_mutex_unlock(g_deviceStateListMutex);
3702         return false;
3703     }
3704
3705     CALEState_t* state = CALEClientGetStateInfo(remoteAddress);
3706     if (NULL == state)
3707     {
3708         OIC_LOG(ERROR, TAG, "state is null");
3709         ca_mutex_unlock(g_deviceStateListMutex);
3710         return false;
3711     }
3712
3713     uint16_t curValue = 0;
3714     switch(state_type)
3715     {
3716         case CA_LE_CONNECTION_STATE:
3717             curValue = state->connectedState;
3718             break;
3719         case CA_LE_SEND_STATE:
3720             curValue = state->sendState;
3721             break;
3722         default:
3723             break;
3724     }
3725
3726     if (target_state == curValue)
3727     {
3728         ca_mutex_unlock(g_deviceStateListMutex);
3729         return true;
3730     }
3731     else
3732     {
3733         ca_mutex_unlock(g_deviceStateListMutex);
3734         return false;
3735     }
3736
3737     ca_mutex_unlock(g_deviceStateListMutex);
3738     return false;
3739 }
3740
3741 void CALEClientCreateDeviceList()
3742 {
3743     OIC_LOG(DEBUG, TAG, "CALEClientCreateDeviceList");
3744
3745     // create new object array
3746     if (!g_gattObjectList)
3747     {
3748         OIC_LOG(DEBUG, TAG, "Create g_gattObjectList");
3749
3750         g_gattObjectList = u_arraylist_create();
3751     }
3752
3753     if (!g_deviceStateList)
3754     {
3755         OIC_LOG(DEBUG, TAG, "Create g_deviceStateList");
3756
3757         g_deviceStateList = u_arraylist_create();
3758     }
3759
3760     if (!g_deviceList)
3761     {
3762         OIC_LOG(DEBUG, TAG, "Create g_deviceList");
3763
3764         g_deviceList = u_arraylist_create();
3765     }
3766 }
3767
3768 /**
3769  * Check Sent Count for remove g_sendBuffer
3770  */
3771 void CALEClientUpdateSendCnt(JNIEnv *env)
3772 {
3773     OIC_LOG(DEBUG, TAG, "CALEClientUpdateSendCnt");
3774
3775     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3776     // mutex lock
3777     ca_mutex_lock(g_threadMutex);
3778
3779     g_currentSentCnt++;
3780
3781     if (g_targetCnt <= g_currentSentCnt)
3782     {
3783         g_targetCnt = 0;
3784         g_currentSentCnt = 0;
3785
3786         if (g_sendBuffer)
3787         {
3788             (*env)->DeleteGlobalRef(env, g_sendBuffer);
3789             g_sendBuffer = NULL;
3790         }
3791         // notity the thread
3792         ca_cond_signal(g_threadCond);
3793
3794         CALEClientSetSendFinishFlag(true);
3795         OIC_LOG(DEBUG, TAG, "set signal for send data");
3796     }
3797     // mutex unlock
3798     ca_mutex_unlock(g_threadMutex);
3799 }
3800
3801 CAResult_t CALEClientInitGattMutexVaraibles()
3802 {
3803     if (NULL == g_bleReqRespClientCbMutex)
3804     {
3805         g_bleReqRespClientCbMutex = ca_mutex_new();
3806         if (NULL == g_bleReqRespClientCbMutex)
3807         {
3808             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3809             return CA_STATUS_FAILED;
3810         }
3811     }
3812
3813     if (NULL == g_bleServerBDAddressMutex)
3814     {
3815         g_bleServerBDAddressMutex = ca_mutex_new();
3816         if (NULL == g_bleServerBDAddressMutex)
3817         {
3818             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3819             return CA_STATUS_FAILED;
3820         }
3821     }
3822
3823     if (NULL == g_threadMutex)
3824     {
3825         g_threadMutex = ca_mutex_new();
3826         if (NULL == g_threadMutex)
3827         {
3828             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3829             return CA_STATUS_FAILED;
3830         }
3831     }
3832
3833     if (NULL == g_threadSendMutex)
3834     {
3835         g_threadSendMutex = ca_mutex_new();
3836         if (NULL == g_threadSendMutex)
3837         {
3838             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3839             return CA_STATUS_FAILED;
3840         }
3841     }
3842
3843     if (NULL == g_deviceListMutex)
3844     {
3845         g_deviceListMutex = ca_mutex_new();
3846         if (NULL == g_deviceListMutex)
3847         {
3848             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3849             return CA_STATUS_FAILED;
3850         }
3851     }
3852
3853     if (NULL == g_gattObjectMutex)
3854     {
3855         g_gattObjectMutex = ca_mutex_new();
3856         if (NULL == g_gattObjectMutex)
3857         {
3858             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3859             return CA_STATUS_FAILED;
3860         }
3861     }
3862
3863     if (NULL == g_deviceStateListMutex)
3864     {
3865         g_deviceStateListMutex = ca_mutex_new();
3866         if (NULL == g_deviceStateListMutex)
3867         {
3868             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3869             return CA_STATUS_FAILED;
3870         }
3871     }
3872
3873     if (NULL == g_SendFinishMutex)
3874     {
3875         g_SendFinishMutex = ca_mutex_new();
3876         if (NULL == g_SendFinishMutex)
3877         {
3878             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3879             return CA_STATUS_FAILED;
3880         }
3881     }
3882
3883     if (NULL == g_threadWriteCharacteristicMutex)
3884     {
3885         g_threadWriteCharacteristicMutex = ca_mutex_new();
3886         if (NULL == g_threadWriteCharacteristicMutex)
3887         {
3888             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3889             return CA_STATUS_FAILED;
3890         }
3891     }
3892
3893     if (NULL == g_deviceScanRetryDelayMutex)
3894     {
3895         g_deviceScanRetryDelayMutex = ca_mutex_new();
3896         if (NULL == g_deviceScanRetryDelayMutex)
3897         {
3898             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3899             return CA_STATUS_FAILED;
3900         }
3901     }
3902
3903     if (NULL == g_threadSendStateMutex)
3904     {
3905         g_threadSendStateMutex = ca_mutex_new();
3906         if (NULL == g_threadSendStateMutex)
3907         {
3908             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3909             return CA_STATUS_FAILED;
3910         }
3911     }
3912
3913     if (NULL == g_threadScanIntervalMutex)
3914     {
3915         g_threadScanIntervalMutex = ca_mutex_new();
3916         if (NULL == g_threadScanIntervalMutex)
3917         {
3918             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3919             return CA_STATUS_FAILED;
3920         }
3921     }
3922
3923     return CA_STATUS_OK;
3924 }
3925
3926 void CALEClientTerminateGattMutexVariables()
3927 {
3928     ca_mutex_free(g_bleReqRespClientCbMutex);
3929     g_bleReqRespClientCbMutex = NULL;
3930
3931     ca_mutex_free(g_bleServerBDAddressMutex);
3932     g_bleServerBDAddressMutex = NULL;
3933
3934     ca_mutex_free(g_threadMutex);
3935     g_threadMutex = NULL;
3936
3937     ca_mutex_free(g_threadSendMutex);
3938     g_threadSendMutex = NULL;
3939
3940     ca_mutex_free(g_deviceListMutex);
3941     g_deviceListMutex = NULL;
3942
3943     ca_mutex_free(g_SendFinishMutex);
3944     g_SendFinishMutex = NULL;
3945
3946     ca_mutex_free(g_threadWriteCharacteristicMutex);
3947     g_threadWriteCharacteristicMutex = NULL;
3948
3949     ca_mutex_free(g_deviceScanRetryDelayMutex);
3950     g_deviceScanRetryDelayMutex = NULL;
3951
3952     ca_mutex_free(g_threadSendStateMutex);
3953     g_threadSendStateMutex = NULL;
3954
3955     ca_mutex_free(g_threadScanIntervalMutex);
3956     g_threadScanIntervalMutex = NULL;
3957 }
3958
3959 void CALEClientSetSendFinishFlag(bool flag)
3960 {
3961     OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag);
3962
3963     ca_mutex_lock(g_SendFinishMutex);
3964     g_isFinishedSendData = flag;
3965     ca_mutex_unlock(g_SendFinishMutex);
3966 }
3967
3968 /**
3969  * adapter common
3970  */
3971
3972 CAResult_t CAStartLEGattClient()
3973 {
3974     // init mutex for send logic
3975     if (!g_deviceDescCond)
3976     {
3977         g_deviceDescCond = ca_cond_new();
3978     }
3979
3980     if (!g_threadCond)
3981     {
3982         g_threadCond = ca_cond_new();
3983     }
3984
3985     if (!g_threadWriteCharacteristicCond)
3986     {
3987         g_threadWriteCharacteristicCond = ca_cond_new();
3988     }
3989
3990     if (!g_threadScanIntervalCond)
3991     {
3992         g_threadScanIntervalCond = ca_cond_new();
3993     }
3994
3995     CAResult_t ret = CALEClientStartScanWithInterval();
3996     if (CA_STATUS_OK != ret)
3997     {
3998         OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed");
3999         return ret;
4000     }
4001
4002     g_isStartedLEClient = true;
4003     return CA_STATUS_OK;
4004 }
4005
4006 void CAStopLEGattClient()
4007 {
4008     OIC_LOG(DEBUG, TAG, "CAStopBLEGattClient");
4009
4010     if (!g_jvm)
4011     {
4012         OIC_LOG(ERROR, TAG, "g_jvm is null");
4013         return;
4014     }
4015
4016     bool isAttached = false;
4017     JNIEnv* env = NULL;
4018     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
4019     if (JNI_OK != res)
4020     {
4021         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
4022         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
4023
4024         if (JNI_OK != res)
4025         {
4026             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
4027             return;
4028         }
4029         isAttached = true;
4030     }
4031
4032     CAResult_t ret = CALEClientDisconnectAll(env);
4033     if (CA_STATUS_OK != ret)
4034     {
4035         OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
4036     }
4037
4038     CALEClientStopScanWithInterval();
4039
4040     ca_mutex_lock(g_threadMutex);
4041     OIC_LOG(DEBUG, TAG, "signal - connection cond");
4042     ca_cond_signal(g_threadCond);
4043     CALEClientSetSendFinishFlag(true);
4044     ca_mutex_unlock(g_threadMutex);
4045
4046     ca_mutex_lock(g_threadWriteCharacteristicMutex);
4047     OIC_LOG(DEBUG, TAG, "signal - WriteCharacteristic cond");
4048     ca_cond_signal(g_threadWriteCharacteristicCond);
4049     ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4050
4051     ca_mutex_lock(g_deviceScanRetryDelayMutex);
4052     OIC_LOG(DEBUG, TAG, "signal - delay cond");
4053     ca_cond_signal(g_deviceScanRetryDelayCond);
4054     ca_mutex_unlock(g_deviceScanRetryDelayMutex);
4055
4056     ca_mutex_lock(g_threadScanIntervalMutex);
4057     OIC_LOG(DEBUG, TAG, "signal - delay cond");
4058     ca_cond_signal(g_threadScanIntervalCond);
4059     ca_mutex_unlock(g_threadScanIntervalMutex);
4060
4061     ca_cond_free(g_deviceDescCond);
4062     ca_cond_free(g_threadCond);
4063     ca_cond_free(g_threadWriteCharacteristicCond);
4064     ca_cond_free(g_deviceScanRetryDelayCond);
4065     ca_cond_free(g_threadScanIntervalCond);
4066
4067     g_deviceDescCond = NULL;
4068     g_threadCond = NULL;
4069     g_threadWriteCharacteristicCond = NULL;
4070     g_deviceScanRetryDelayCond = NULL;
4071     g_threadScanIntervalCond = NULL;
4072
4073     if (isAttached)
4074     {
4075         (*g_jvm)->DetachCurrentThread(g_jvm);
4076     }
4077
4078 }
4079
4080 CAResult_t CAInitializeLEGattClient()
4081 {
4082     OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
4083     CALEClientInitialize();
4084     return CA_STATUS_OK;
4085 }
4086
4087 void CATerminateLEGattClient()
4088 {
4089     OIC_LOG(DEBUG, TAG, "Terminate GATT Client");
4090     CAStopLEGattClient();
4091     CALEClientTerminate();
4092 }
4093
4094 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t  *data,
4095                                                uint32_t dataLen, CALETransferType_t type,
4096                                                int32_t position)
4097 {
4098     OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage");
4099     VERIFY_NON_NULL(data, TAG, "data is null");
4100     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
4101
4102     if (LE_UNICAST != type || position < 0)
4103     {
4104         OIC_LOG(ERROR, TAG, "this request is not unicast");
4105         return CA_STATUS_INVALID_PARAM;
4106     }
4107
4108     return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
4109 }
4110
4111 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
4112 {
4113     OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
4114     VERIFY_NON_NULL(data, TAG, "data is null");
4115
4116     return CALEClientSendMulticastMessage(data, dataLen);
4117 }
4118
4119 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
4120 {
4121     ca_mutex_lock(g_bleReqRespClientCbMutex);
4122     g_CABLEClientDataReceivedCallback = callback;
4123     ca_mutex_unlock(g_bleReqRespClientCbMutex);
4124 }
4125
4126 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
4127 {
4128     g_threadPoolHandle = handle;
4129 }
4130
4131 CAResult_t CAGetLEAddress(char **local_address)
4132 {
4133     VERIFY_NON_NULL(local_address, TAG, "local_address");
4134     OIC_LOG(INFO, TAG, "CAGetLEAddress is not support");
4135     return CA_NOT_SUPPORTED;
4136 }
4137
4138 JNIEXPORT void JNICALL
4139 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
4140                                                                     jobject callback)
4141 {
4142     OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
4143     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4144     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4145     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
4146
4147     g_leScanCallback = (*env)->NewGlobalRef(env, callback);
4148 }
4149
4150 JNIEXPORT void JNICALL
4151 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
4152                                                                   jobject callback)
4153 {
4154     OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
4155     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4156     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4157     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
4158
4159     g_leGattCallback = (*env)->NewGlobalRef(env, callback);
4160 }
4161
4162 JNIEXPORT void JNICALL
4163 Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
4164                                                           jobject device)
4165 {
4166     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4167     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4168     VERIFY_NON_NULL_VOID(device, TAG, "device is null");
4169
4170     CAResult_t res = CALEClientAddScanDeviceToList(env, device);
4171     if (CA_STATUS_OK != res)
4172     {
4173         OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
4174     }
4175 }
4176
4177 /*
4178  * Class:     org_iotivity_ca_jar_caleinterface
4179  * Method:    CALeGattConnectionStateChangeCallback
4180  * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
4181  */
4182 JNIEXPORT void JNICALL
4183 Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
4184                                                                                jobject obj,
4185                                                                                jobject gatt,
4186                                                                                jint status,
4187                                                                                jint newstate)
4188 {
4189     OIC_LOG_V(INFO, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
4190               newstate);
4191     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4192     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4193     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4194
4195     jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
4196
4197     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4198     if (!jni_address)
4199     {
4200         OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
4201         goto error_exit;
4202     }
4203
4204     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4205     if (!address)
4206     {
4207         OIC_LOG(ERROR, TAG, "address is null");
4208         goto error_exit;
4209     }
4210     OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address);
4211
4212     if (state_connected == newstate)
4213     {
4214         OIC_LOG(DEBUG, TAG, "LE is connected");
4215         if (GATT_SUCCESS == status)
4216         {
4217             CAResult_t res = CALEClientUpdateDeviceState(address,
4218                                                          CA_LE_CONNECTION_STATE,
4219                                                          STATE_CONNECTED);
4220             (*env)->ReleaseStringUTFChars(env, jni_address, address);
4221             if (CA_STATUS_OK != res)
4222             {
4223                 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4224                 goto error_exit;
4225             }
4226
4227             res = CALEClientAddGattobjToList(env, gatt);
4228             if (CA_STATUS_OK != res)
4229             {
4230                 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
4231                 goto error_exit;
4232             }
4233
4234             res = CALEClientDiscoverServices(env, gatt);
4235             if (CA_STATUS_OK != res)
4236             {
4237                 OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
4238                 goto error_exit;
4239             }
4240         }
4241         else
4242         {
4243             OIC_LOG(INFO, TAG, "unknown status");
4244             (*env)->ReleaseStringUTFChars(env, jni_address, address);
4245         }
4246     }
4247     else // STATE_DISCONNECTED == newstate
4248     {
4249         OIC_LOG(DEBUG, TAG, "LE is disconnected");
4250
4251         CAResult_t res = CALEClientUpdateDeviceState(address,
4252                                                      CA_LE_CONNECTION_STATE,
4253                                                      STATE_DISCONNECTED);
4254         (*env)->ReleaseStringUTFChars(env, jni_address, address);
4255         if (CA_STATUS_OK != res)
4256         {
4257             OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4258             goto error_exit;
4259         }
4260
4261         res = CALEClientGattClose(env, gatt);
4262         if (CA_STATUS_OK != res)
4263         {
4264             OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
4265         }
4266
4267         if (CALECheckConnectionStateValue(status))
4268         {
4269             // this state is unexpected reason to disconnect
4270             // if the reason is suitable, connection logic of the device will be destroyed.
4271             OIC_LOG(INFO, TAG, "connection logic destroy");
4272             goto error_exit;
4273         }
4274         else
4275         {
4276             // other reason except for gatt_success is expected to running
4277             // background connection in BT platform.
4278             OIC_LOG(INFO, TAG, "unknown status or manual disconnected state");
4279             CALEClientUpdateSendCnt(env);
4280             return;
4281         }
4282
4283         if (g_sendBuffer)
4284         {
4285             (*env)->DeleteGlobalRef(env, g_sendBuffer);
4286             g_sendBuffer = NULL;
4287         }
4288     }
4289     return;
4290
4291     // error label.
4292 error_exit:
4293     CALEClientSendFinish(env, gatt);
4294     return;
4295 }
4296
4297 /*
4298  * Class:     org_iotivity_ca_jar_caleinterface
4299  * Method:    CALeGattServicesDiscoveredCallback
4300  * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
4301  */
4302 JNIEXPORT void JNICALL
4303 Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
4304                                                                             jobject obj,
4305                                                                             jobject gatt,
4306                                                                             jint status)
4307 {
4308     OIC_LOG_V(INFO, TAG, "CALeGattServicesDiscoveredCallback - status %d", status);
4309     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4310     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4311     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4312
4313     if (GATT_SUCCESS != status) // discovery error
4314     {
4315         CALEClientSendFinish(env, gatt);
4316         return;
4317     }
4318
4319     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4320     if (!jni_address)
4321     {
4322         CALEClientSendFinish(env, gatt);
4323         return;
4324     }
4325
4326     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4327     if (!address)
4328     {
4329         CALEClientSendFinish(env, gatt);
4330         return;
4331     }
4332
4333     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
4334     if (!jni_uuid)
4335     {
4336         OIC_LOG(ERROR, TAG, "jni_uuid is null");
4337         goto error_exit;
4338     }
4339
4340     jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
4341     if (!jni_obj_GattCharacteristic)
4342     {
4343         OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
4344         goto error_exit;
4345     }
4346
4347     CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
4348                                                              jni_obj_GattCharacteristic);
4349     if (CA_STATUS_OK != res)
4350     {
4351         OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
4352         goto error_exit;
4353     }
4354
4355     res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
4356     if (CA_STATUS_OK != res)
4357     {
4358         OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
4359
4360         res = CALEClientSetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_FALSE);
4361         if (CA_STATUS_OK != res)
4362         {
4363             OIC_LOG(ERROR, TAG, "CALEClientSetFlagToState has failed");
4364             goto error_exit;
4365         }
4366
4367         res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
4368                                           STATE_SERVICE_CONNECTED);
4369         if (CA_STATUS_OK != res)
4370         {
4371             OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4372             goto error_exit;
4373         }
4374
4375         if (g_sendBuffer)
4376         {
4377             CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4378             if (CA_STATUS_OK != res)
4379             {
4380                 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
4381                 goto error_exit;
4382             }
4383         }
4384     }
4385     else
4386     {
4387         res = CALEClientSetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_TRUE);
4388         if (CA_STATUS_OK != res)
4389         {
4390             OIC_LOG(ERROR, TAG, "CALEClientSetFlagToState has failed");
4391             goto error_exit;
4392         }
4393     }
4394
4395     OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
4396     (*env)->ReleaseStringUTFChars(env, jni_address, address);
4397     return;
4398
4399     // error label.
4400 error_exit:
4401     OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
4402     (*env)->ReleaseStringUTFChars(env, jni_address, address);
4403     CALEClientSendFinish(env, gatt);
4404     return;
4405 }
4406
4407 /*
4408  * Class:     org_iotivity_ca_jar_caleinterface
4409  * Method:    CALeGattCharacteristicWritjclasseCallback
4410  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
4411  */
4412 JNIEXPORT void JNICALL
4413 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
4414         JNIEnv *env, jobject obj, jobject gatt, jbyteArray data, jint status)
4415 {
4416     OIC_LOG_V(INFO, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
4417     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4418     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4419     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4420
4421     // send success & signal
4422     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4423     if (!jni_address)
4424     {
4425         goto error_exit;
4426     }
4427
4428     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4429     if (!address)
4430     {
4431         goto error_exit;
4432     }
4433
4434     if (GATT_SUCCESS != status) // error case
4435     {
4436         OIC_LOG(ERROR, TAG, "send failure");
4437
4438         // retry to write
4439         CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4440         if (CA_STATUS_OK != res)
4441         {
4442             OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
4443             ca_mutex_lock(g_threadWriteCharacteristicMutex);
4444             g_isSignalSetFlag = true;
4445             ca_cond_signal(g_threadWriteCharacteristicCond);
4446             ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4447
4448             CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
4449                                                          STATE_SEND_FAIL);
4450             if (CA_STATUS_OK != res)
4451             {
4452                 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4453             }
4454
4455             if (g_clientErrorCallback)
4456             {
4457                 jint length = (*env)->GetArrayLength(env, data);
4458                 g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
4459             }
4460
4461             (*env)->ReleaseStringUTFChars(env, jni_address, address);
4462             goto error_exit;
4463         }
4464     }
4465     else
4466     {
4467         OIC_LOG(DEBUG, TAG, "send success");
4468         CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
4469                                                      STATE_SEND_SUCCESS);
4470         if (CA_STATUS_OK != res)
4471         {
4472             OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4473         }
4474
4475         ca_mutex_lock(g_threadWriteCharacteristicMutex);
4476         OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
4477         g_isSignalSetFlag = true;
4478         ca_cond_signal(g_threadWriteCharacteristicCond);
4479         ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4480
4481         CALEClientUpdateSendCnt(env);
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 }