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