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