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