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