9977465cbf684e6dc55e27653fec7ae0e847d97f
[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_bleServerBDAddressMutex = NULL;
96
97 static oc_mutex g_deviceListMutex = NULL;
98 static oc_mutex g_gattObjectMutex = NULL;
99 static oc_mutex g_deviceStateListMutex = NULL;
100
101 static oc_mutex g_deviceScanRetryDelayMutex = NULL;
102 static oc_cond g_deviceScanRetryDelayCond = NULL;
103
104 static oc_mutex g_threadScanIntervalMutex = NULL;
105 static oc_cond g_threadScanIntervalCond = NULL;
106
107 static oc_mutex g_threadSendStateMutex = NULL;
108 static oc_mutex g_setValueMutex = NULL;
109
110 static int32_t g_scanIntervalTime = WAIT_TIME_SCAN_INTERVAL_DEFAULT;
111 static int32_t g_scanIntervalTimePrev = WAIT_TIME_SCAN_INTERVAL_DEFAULT;
112 static int32_t g_intervalCount = 0;
113 static bool g_isWorkingScanThread = false;
114 static CALEScanState_t g_curScanningStep = BLE_SCAN_NONE;
115 static CALEScanState_t g_nextScanningStep = BLE_SCAN_ENABLE;
116
117 static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
118 static int32_t g_jniIntSdk = -1;
119
120 static bool g_setHighQoS = true;
121 static bool g_setFullScanFlag = true;
122 jclass g_LEInterface = NULL;
123 /**
124  * check if retry logic for connection routine has to be stopped or not.
125  * in case of error value including this method, connection routine has to be stopped.
126  * since there is no retry logic for this error reason in this client.
127  * @param state constant value of bluetoothgatt.
128  * @return true - waiting for background connection in BT platform.
129  *         false - connection routine has to be stopped.
130  */
131 static bool CALECheckConnectionStateValue(jint state)
132 {
133     switch(state)
134     {
135         case GATT_CONNECTION_PRIORITY_BALANCED:
136         case GATT_FAILURE:
137         case GATT_INSUFFICIENT_AUTHENTICATION:
138         case GATT_INSUFFICIENT_ENCRYPTION:
139         case GATT_INVALID_ATTRIBUTE_LENGTH:
140         case GATT_INVALID_OFFSET:
141         case GATT_READ_NOT_PERMITTED:
142         case GATT_REQUEST_NOT_SUPPORTED:
143         case GATT_WRITE_NOT_PERMITTED:
144             return true;
145         default:
146             return false;
147     }
148 }
149
150 /**
151  * delete global reference for g_sendBuffer
152  * @param[in]   env                   JNI interface pointer.
153  */
154 static void CALEDeleteSendBuffer(JNIEnv *env)
155 {
156     OIC_LOG(INFO, TAG, "CALEDeleteSendBuffer");
157     oc_mutex_lock(g_setValueMutex);
158     if (g_sendBuffer)
159     {
160         OIC_LOG(INFO, TAG, "delete send buffer");
161         (*env)->DeleteGlobalRef(env, g_sendBuffer);
162         g_sendBuffer = NULL;
163     }
164     oc_mutex_unlock(g_setValueMutex);
165 }
166
167 void CALEClientSetScanInterval(int32_t intervalTime, int32_t workingCount,
168                                CALEScanState_t nextScanningStep)
169 {
170     OIC_LOG_V(DEBUG, TAG, "CALEClientSetScanInterval : %d -> %d, next scan state will be %d",
171               g_scanIntervalTime, intervalTime, nextScanningStep);
172
173     // previous time should be stored.
174     if (0 < workingCount)
175     {
176         g_scanIntervalTimePrev = g_scanIntervalTime;
177     }
178     g_scanIntervalTime = intervalTime;
179     g_intervalCount = workingCount;
180     g_nextScanningStep = nextScanningStep;
181 }
182
183 void CALERestartScanWithInterval(int32_t intervalTime, int32_t workingCount,
184                                  CALEScanState_t nextScanningStep)
185 {
186     if (intervalTime == g_scanIntervalTime
187             && workingCount == g_intervalCount
188             && nextScanningStep == g_nextScanningStep)
189     {
190         OIC_LOG(DEBUG, TAG, "setting duplicate interval time");
191         return;
192     }
193
194     oc_mutex_lock(g_threadScanIntervalMutex);
195     CALEClientSetScanInterval(intervalTime, workingCount, nextScanningStep);
196     oc_cond_signal(g_threadScanIntervalCond);
197     oc_mutex_unlock(g_threadScanIntervalMutex);
198 }
199
200 static void CALEScanThread(void* object)
201 {
202     (void)object;
203
204     bool isAttached = false;
205     JNIEnv* env = NULL;
206     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
207     if (JNI_OK != res)
208     {
209         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
210
211         if (JNI_OK != res)
212         {
213             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
214             return;
215         }
216         isAttached = true;
217     }
218
219     oc_mutex_lock(g_threadScanIntervalMutex);
220     while(g_isWorkingScanThread)
221     {
222         OIC_LOG(DEBUG, TAG, "scan waiting time out");
223         if (BLE_SCAN_ENABLE == g_curScanningStep)
224         {
225             //stop scan
226             CAResult_t ret = CALEClientStopScan();
227             if (CA_STATUS_OK != ret)
228             {
229                 OIC_LOG(INFO, TAG, "CALEClientStopScan has failed");
230             }
231         }
232         else if (BLE_SCAN_DISABLE == g_curScanningStep)
233         {
234             //start scan
235             CAResult_t ret = CALEClientStartScan();
236             if (CA_STATUS_OK != ret)
237             {
238                 OIC_LOG(INFO, TAG, "CALEClientStartScan has failed");
239             }
240         }
241         else
242         {
243             OIC_LOG(DEBUG, TAG, "scan thread is started");
244             // standby scanning
245             CALEClientSetScanInterval(0, 0, BLE_SCAN_DISABLE);
246         }
247
248         OIC_LOG_V(DEBUG, TAG, "wait for Scan Interval Time during %d sec", g_scanIntervalTime);
249         if (OC_WAIT_SUCCESS == oc_cond_wait_for(g_threadScanIntervalCond,
250                                                 g_threadScanIntervalMutex,
251                                                 g_scanIntervalTime * MICROSECS_PER_SEC))
252         {
253             // called signal scan thread will be terminated
254             OIC_LOG(DEBUG, TAG, "signal scanInterval waiting");
255             if (BLE_SCAN_DISABLE == g_nextScanningStep)
256             {
257                 g_curScanningStep = BLE_SCAN_ENABLE;
258             }
259             else
260             {
261                 g_curScanningStep = BLE_SCAN_DISABLE;
262             }
263         }
264         else
265         {
266            if (BLE_SCAN_ENABLE == g_curScanningStep)
267            {
268                if (g_intervalCount > 0)
269                {
270                    if (g_intervalCount == 1)
271                    {
272                        OIC_LOG(DEBUG, TAG, "reset default time");
273                        CALEClientSetScanInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE);
274                    }
275                    g_intervalCount--;
276                    OIC_LOG_V(DEBUG, TAG, "interval count : %d", g_intervalCount);
277                }
278                g_curScanningStep = BLE_SCAN_DISABLE;
279            }
280            else
281            {
282                g_curScanningStep = BLE_SCAN_ENABLE;
283            }
284         }
285     }
286     oc_mutex_unlock(g_threadScanIntervalMutex);
287
288     if (isAttached)
289     {
290         (*g_jvm)->DetachCurrentThread(g_jvm);
291     }
292 }
293
294 CAResult_t CALEClientStartScanWithInterval()
295 {
296     if (g_isWorkingScanThread)
297     {
298         OIC_LOG(DEBUG, TAG, "scan interval logic already running");
299         return CA_STATUS_OK;
300     }
301
302     // initialize scan flags
303     g_curScanningStep = BLE_SCAN_NONE;
304     g_isWorkingScanThread = true;
305     g_intervalCount = 0;
306     g_scanIntervalTime = g_scanIntervalTimePrev;
307     g_nextScanningStep = BLE_SCAN_ENABLE;
308
309     if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CALEScanThread, NULL, NULL))
310     {
311         OIC_LOG(ERROR, TAG, "Failed to create read thread!");
312         g_isWorkingScanThread = false;
313         return CA_STATUS_FAILED;
314     }
315
316     return CA_STATUS_OK;
317 }
318
319 void CALEClientStopScanWithInterval()
320 {
321     g_isWorkingScanThread = false;
322     oc_cond_signal(g_threadScanIntervalCond);
323 }
324
325 //getting jvm
326 void CALEClientJniInit()
327 {
328     OIC_LOG(DEBUG, TAG, "CALEClientJniInit");
329     g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
330 }
331
332 void CALEClientJNISetContext()
333 {
334     OIC_LOG(DEBUG, TAG, "CALEClientJNISetContext");
335     g_context = (jobject) CANativeJNIGetContext();
336 }
337
338 CAResult_t CALECreateJniInterfaceObject()
339 {
340     OIC_LOG(DEBUG, TAG, "CALECreateJniInterfaceObject");
341
342     if (!g_context)
343     {
344         OIC_LOG(ERROR, TAG, "g_context is null");
345         return CA_STATUS_FAILED;
346     }
347
348     if (!g_jvm)
349     {
350         OIC_LOG(ERROR, TAG, "g_jvm is null");
351         return CA_STATUS_FAILED;
352     }
353
354     bool isAttached = false;
355     JNIEnv* env = NULL;
356     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
357     if (JNI_OK != res)
358     {
359         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
360
361         if (JNI_OK != res)
362         {
363             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
364             return CA_STATUS_FAILED;
365         }
366         isAttached = true;
367     }
368
369     jmethodID mid_getApplicationContext = CAGetJNIMethodID(env, "android/content/Context",
370                                                            "getApplicationContext",
371                                                            "()Landroid/content/Context;");
372
373     if (!mid_getApplicationContext)
374     {
375         OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
376         return CA_STATUS_FAILED;
377     }
378
379     jobject jApplicationContext = (*env)->CallObjectMethod(env, g_context,
380                                                            mid_getApplicationContext);
381     if (!jApplicationContext)
382     {
383         OIC_LOG(ERROR, TAG, "Could not get application context");
384         goto error_exit;
385     }
386
387     jclass jni_LEInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
388     if (!jni_LEInterface)
389     {
390         OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
391         goto error_exit;
392     }
393     g_LEInterface = (jclass)((*env)->NewGlobalRef(env, jni_LEInterface));
394
395     jmethodID LeInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_LEInterface, "<init>",
396                                                                  "(Landroid/content/Context;)V");
397     if (!LeInterfaceConstructorMethod)
398     {
399         OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface constructor method");
400         goto error_exit;
401     }
402
403     (*env)->NewObject(env, jni_LEInterface, LeInterfaceConstructorMethod, jApplicationContext);
404     OIC_LOG(DEBUG, TAG, "Create instance for CaLeClientInterface");
405
406     if (isAttached)
407     {
408         (*g_jvm)->DetachCurrentThread(g_jvm);
409     }
410
411     return CA_STATUS_OK;
412
413 error_exit:
414     CACheckJNIException(env);
415     if (isAttached)
416     {
417         (*g_jvm)->DetachCurrentThread(g_jvm);
418     }
419
420     return CA_STATUS_FAILED;
421 }
422
423 CAResult_t CALEClientInitialize()
424 {
425     OIC_LOG(DEBUG, TAG, "CALEClientInitialize");
426
427     CALEClientJniInit();
428
429     if (!g_jvm)
430     {
431         OIC_LOG(ERROR, TAG, "g_jvm is null");
432         return CA_STATUS_FAILED;
433     }
434
435     bool isAttached = false;
436     JNIEnv* env = NULL;
437     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
438     if (JNI_OK != res)
439     {
440         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
441
442         if (JNI_OK != res)
443         {
444             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
445             return CA_STATUS_FAILED;
446         }
447         isAttached = true;
448     }
449
450     g_jniIntSdk = CALEGetBuildVersion(env);
451     if (g_jniIntSdk < BLE_MIN_API_LEVEL)
452     {
453         OIC_LOG(ERROR, TAG, "it is not supported");
454
455         if (isAttached)
456         {
457             (*g_jvm)->DetachCurrentThread(g_jvm);
458         }
459         return CA_STATUS_FAILED;
460     }
461
462     CAResult_t ret = CALEClientInitGattMutexVaraibles();
463     if (CA_STATUS_OK != ret)
464     {
465         OIC_LOG(ERROR, TAG, "CALEClientInitGattMutexVaraibles has failed!");
466         CALEClientTerminateGattMutexVariables();
467
468         if (isAttached)
469         {
470             (*g_jvm)->DetachCurrentThread(g_jvm);
471         }
472
473         return ret;
474     }
475
476     g_deviceDescCond = oc_cond_new();
477
478     // init mutex for send logic
479     g_threadCond = oc_cond_new();
480     g_threadWriteCharacteristicCond = oc_cond_new();
481     g_deviceScanRetryDelayCond = oc_cond_new();
482     g_threadScanIntervalCond =  oc_cond_new();
483
484     CALEClientCreateDeviceList();
485     CALEClientJNISetContext();
486
487     ret = CALEClientCreateUUIDList();
488     if (CA_STATUS_OK != ret)
489     {
490         OIC_LOG(ERROR, TAG, "CALEClientCreateUUIDList has failed");
491
492         if (isAttached)
493         {
494             (*g_jvm)->DetachCurrentThread(g_jvm);
495         }
496
497         return ret;
498     }
499
500     ret = CALECreateJniInterfaceObject(); /* create java caleinterface instance*/
501     if (CA_STATUS_OK != ret)
502     {
503         OIC_LOG(ERROR, TAG, "CALECreateJniInterfaceObject has failed");
504
505         if (isAttached)
506         {
507             (*g_jvm)->DetachCurrentThread(g_jvm);
508         }
509
510         return ret;
511     }
512     g_isStartedLEClient = true;
513
514     if (isAttached)
515     {
516         (*g_jvm)->DetachCurrentThread(g_jvm);
517     }
518
519     return CA_STATUS_OK;
520 }
521
522 void CALEClientTerminate()
523 {
524     OIC_LOG(DEBUG, TAG, "CALEClientTerminate");
525
526     if (!g_jvm)
527     {
528         OIC_LOG(ERROR, TAG, "g_jvm is null");
529         return;
530     }
531
532     bool isAttached = false;
533     JNIEnv* env = NULL;
534     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
535     if (JNI_OK != res)
536     {
537         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
538
539         if (JNI_OK != res)
540         {
541             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
542             return;
543         }
544         isAttached = true;
545     }
546
547     // stop scan
548     CAResult_t ret = CALEClientStopScan();
549     if (CA_STATUS_OK != ret)
550     {
551         OIC_LOG(INFO, TAG, "CALEClientStopScan has failed");
552     }
553
554     if (g_leScanCallback)
555     {
556         (*env)->DeleteGlobalRef(env, g_leScanCallback);
557         g_leScanCallback = NULL;
558     }
559
560     if (g_leGattCallback)
561     {
562         (*env)->DeleteGlobalRef(env, g_leGattCallback);
563         g_leGattCallback = NULL;
564     }
565
566     if (g_LEInterface)
567     {
568         (*env)->DeleteGlobalRef(env, g_LEInterface);
569         g_LEInterface = NULL;
570     }
571
572     CALEDeleteSendBuffer(env);
573
574     if (g_uuidList)
575     {
576         (*env)->DeleteGlobalRef(env, g_uuidList);
577         g_uuidList = NULL;
578     }
579
580     ret = CALERemoveAllDeviceState(g_deviceStateList,
581                                    g_deviceStateListMutex);
582     if (CA_STATUS_OK != ret)
583     {
584         OIC_LOG(ERROR, TAG, "CALERemoveAllDeviceState has failed");
585     }
586
587     oc_mutex_lock(g_deviceStateListMutex);
588     OICFree(g_deviceStateList);
589     g_deviceStateList = NULL;
590     oc_mutex_unlock(g_deviceStateListMutex);
591
592     ret = CALEClientRemoveAllScanDevices(env);
593     if (CA_STATUS_OK != ret)
594     {
595         OIC_LOG(ERROR, TAG, "CALEClientRemoveAllScanDevices has failed");
596     }
597
598     ret = CALEClientRemoveAllGattObjs(env);
599     if (CA_STATUS_OK != ret)
600     {
601         OIC_LOG(ERROR, TAG, "CALEClientRemoveAllGattObjs has failed");
602     }
603
604     CALEClientSetSendFinishFlag(true);
605
606     CALEClientTerminateGattMutexVariables();
607     CALEClientDestroyJniInterface();
608
609     oc_cond_free(g_deviceDescCond);
610     oc_cond_free(g_threadCond);
611     oc_cond_free(g_threadWriteCharacteristicCond);
612     oc_cond_free(g_deviceScanRetryDelayCond);
613     oc_cond_free(g_threadScanIntervalCond);
614
615     g_deviceDescCond = NULL;
616     g_threadCond = NULL;
617     g_threadWriteCharacteristicCond = NULL;
618     g_deviceScanRetryDelayCond = NULL;
619     g_threadScanIntervalCond = NULL;
620
621     g_isSignalSetFlag = false;
622
623     // stop scanning
624     CALEClientStopScanWithInterval();
625
626     if (isAttached)
627     {
628         (*g_jvm)->DetachCurrentThread(g_jvm);
629     }
630 }
631
632 jobject CALEClientHiddenConnectGatt(jobject btDevice, const char* address, jboolean autoconnect)
633 {
634     OIC_LOG(INFO, TAG, "IN - CALEClientHiddenConnectGatt");
635
636     if (!g_jvm)
637     {
638         OIC_LOG(ERROR, TAG, "g_jvm is null");
639         return NULL;
640     }
641
642     bool isAttached = false;
643     JNIEnv* env = NULL;
644     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
645     if (JNI_OK != res)
646     {
647         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
648
649         if (JNI_OK != res)
650         {
651             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
652             return NULL;
653         }
654         isAttached = true;
655     }
656
657     jstring jni_address = (*env)->NewStringUTF(env, address);
658     jmethodID jni_connectGattHiddenMethod = (*env)->GetStaticMethodID(env, g_LEInterface,
659                                                                      "connectGattforHidden",
660                                                                      "(Landroid/bluetooth/BluetoothDevice;"
661                                                                      "Ljava/lang/String;Z)"
662                                                                      "Landroid/bluetooth/BluetoothGatt;");
663     if (!jni_connectGattHiddenMethod)
664     {
665         OIC_LOG(ERROR, TAG, "Could not get jni_connectGatt Hidden Method");
666         goto error_exit;
667     }
668
669     jobject gatt = (*env)->CallStaticObjectMethod(env, g_LEInterface,
670                                                   jni_connectGattHiddenMethod,
671                                                   btDevice, jni_address, autoconnect);
672
673     if (CACheckJNIException(env))
674     {
675         OIC_LOG(ERROR, TAG, "connectGattforHidden has failed");
676         goto detach_thread;
677     }
678
679     OIC_LOG(INFO, TAG, "OUT - CALEClientHiddenConnectGatt");
680
681     if (isAttached)
682     {
683         (*g_jvm)->DetachCurrentThread(g_jvm);
684     }
685
686     return gatt;
687
688 error_exit:
689     CACheckJNIException(env);
690
691 detach_thread:
692     if (isAttached)
693     {
694         (*g_jvm)->DetachCurrentThread(g_jvm);
695     }
696
697     return NULL;
698 }
699
700 CAResult_t CALEClientDestroyJniInterface()
701 {
702     OIC_LOG(DEBUG, TAG, "CALEClientDestroyJniInterface");
703
704     if (!g_jvm)
705     {
706         OIC_LOG(ERROR, TAG, "g_jvm is null");
707         return CA_STATUS_FAILED;
708     }
709
710     bool isAttached = false;
711     JNIEnv* env = NULL;
712     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
713     if (JNI_OK != res)
714     {
715         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
716
717         if (JNI_OK != res)
718         {
719             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
720             return CA_STATUS_FAILED;
721         }
722         isAttached = true;
723     }
724
725     jclass jni_LeInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
726     if (!jni_LeInterface)
727     {
728         OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
729         goto error_exit;
730     }
731
732     jmethodID jni_InterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_LeInterface,
733                                                                      "destroyLeInterface",
734                                                                      "()V");
735     if (!jni_InterfaceDestroyMethod)
736     {
737         OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface destroy method");
738         goto error_exit;
739     }
740
741     (*env)->CallStaticVoidMethod(env, jni_LeInterface, jni_InterfaceDestroyMethod);
742
743     if (CACheckJNIException(env))
744     {
745         OIC_LOG(ERROR, TAG, "destroyLeInterface has failed");
746         goto detach_thread;
747     }
748
749     OIC_LOG(DEBUG, TAG, "Destroy instance for CaLeClientInterface");
750
751     if (isAttached)
752     {
753         (*g_jvm)->DetachCurrentThread(g_jvm);
754     }
755
756     return CA_STATUS_OK;
757
758 error_exit:
759     CACheckJNIException(env);
760
761 detach_thread:
762     if (isAttached)
763     {
764         (*g_jvm)->DetachCurrentThread(g_jvm);
765     }
766
767     return CA_STATUS_FAILED;
768 }
769
770 void CALEClientSendFinish(JNIEnv *env, jobject gatt)
771 {
772     OIC_LOG(DEBUG, TAG, "CALEClientSendFinish");
773     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
774
775     if (gatt)
776     {
777         CAResult_t res = CALEClientDisconnect(env, gatt);
778         if (CA_STATUS_OK != res)
779         {
780             OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
781         }
782     }
783     CALEClientUpdateSendCnt(env);
784 }
785
786 CAResult_t CALEClientSendNegotiationMessage(const char* address)
787 {
788     VERIFY_NON_NULL(address, TAG, "address is null");
789
790     return CALEClientSendUnicastMessageImpl(address, NULL, 0);
791 }
792
793 CAResult_t CALEClientSendUnicastMessage(const char* address,
794                                         const uint8_t* data,
795                                         const uint32_t dataLen)
796 {
797     VERIFY_NON_NULL(address, TAG, "address is null");
798     VERIFY_NON_NULL(data, TAG, "data is null");
799
800     return CALEClientSendUnicastMessageImpl(address, data, dataLen);
801 }
802
803 CAResult_t CALEClientSendMulticastMessage(const uint8_t* data,
804                                           const uint32_t dataLen)
805 {
806     OIC_LOG_V(DEBUG, TAG, "CALEClientSendMulticastMessage(%p)", data);
807     VERIFY_NON_NULL(data, TAG, "data is null");
808
809     if (!g_jvm)
810     {
811         OIC_LOG(ERROR, TAG, "g_jvm is null");
812         return CA_STATUS_FAILED;
813     }
814
815     bool isAttached = false;
816     JNIEnv* env = NULL;
817     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
818     if (JNI_OK != res)
819     {
820         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
821
822         if (JNI_OK != res)
823         {
824             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
825             return CA_STATUS_FAILED;
826         }
827         isAttached = true;
828     }
829
830     CAResult_t ret = CALEClientSendMulticastMessageImpl(env, data, dataLen);
831     if (CA_STATUS_OK != ret)
832     {
833         OIC_LOG(ERROR, TAG, "CALEClientSendMulticastMessageImpl has failed");
834     }
835
836     if (isAttached)
837     {
838         (*g_jvm)->DetachCurrentThread(g_jvm);
839     }
840
841     return ret;
842 }
843
844 CAResult_t CALEClientStartUnicastServer(const char* address)
845 {
846 #ifndef TB_LOG
847     (void)address;
848 #endif
849     OIC_LOG_V(DEBUG, TAG, "it is not needed in this platform (%s)", address);
850
851     return CA_NOT_SUPPORTED;
852 }
853
854 CAResult_t CALEClientStartMulticastServer()
855 {
856     OIC_LOG(DEBUG, TAG, "it is not needed in this platform");
857
858     return CA_NOT_SUPPORTED;
859 }
860
861 void CALEClientStopUnicastServer()
862 {
863     OIC_LOG(DEBUG, TAG, "CALEClientStopUnicastServer");
864 }
865
866 void CALEClientStopMulticastServer()
867 {
868     OIC_LOG(DEBUG, TAG, "CALEClientStopMulticastServer");
869 }
870
871 void CALEClientSetCallback(CAPacketReceiveCallback callback)
872 {
873     g_packetReceiveCallback = callback;
874 }
875
876 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
877 {
878     g_clientErrorCallback = callback;
879 }
880
881 CAResult_t CALEClientIsThereScannedDevices(JNIEnv *env, const char* address)
882 {
883     VERIFY_NON_NULL(env, TAG, "env");
884
885     if (!g_deviceList)
886     {
887         OIC_LOG(ERROR, TAG, "g_deviceList is not available");
888         return CA_STATUS_FAILED;
889     }
890
891     if (0 == u_arraylist_length(g_deviceList) // multicast
892             || (address && !CALEClientIsDeviceInScanDeviceList(env, address))) // unicast
893     {
894         // Wait for LE peripherals to be discovered.
895
896         // Number of times to wait for discovery to complete.
897         static size_t const RETRIES = 5;
898
899         static uint64_t const TIMEOUT =
900             2 * MICROSECS_PER_SEC;  // Microseconds
901
902         // set scan interval and start scan
903         CALERestartScanWithInterval(WAIT_TIME_SCANNED_CHECKING, 1, BLE_SCAN_ENABLE);
904
905         bool devicesDiscovered = false;
906         for (size_t i = 0; i < RETRIES; ++i)
907         {
908             OIC_LOG(DEBUG, TAG, "waiting for target device");
909             if (oc_cond_wait_for(g_deviceDescCond,
910                                  g_threadSendMutex,
911                                  TIMEOUT) == OC_WAIT_SUCCESS)
912             {
913                 OIC_LOG(DEBUG, TAG, "time out");
914                 oc_mutex_lock(g_deviceListMutex);
915                 size_t scannedDeviceLen = u_arraylist_length(g_deviceList);
916                 oc_mutex_unlock(g_deviceListMutex);
917
918                 if (0 < scannedDeviceLen)
919                 {
920                     if (!address  // multicast
921                         || (address && CALEClientIsDeviceInScanDeviceList(env, address))) // unicast
922                     {
923                       devicesDiscovered = true;
924                       break;
925                     }
926                     else
927                     {
928                         if (address)
929                         {
930                             OIC_LOG(INFO, TAG, "waiting..");
931
932                             oc_mutex_lock(g_deviceScanRetryDelayMutex);
933                             if (oc_cond_wait_for(g_deviceScanRetryDelayCond,
934                                                  g_deviceScanRetryDelayMutex,
935                                                  MICROSECS_PER_SEC) == OC_WAIT_SUCCESS)
936                             {
937                                 OIC_LOG(INFO, TAG, "finish to waiting for target device");
938                                 oc_mutex_unlock(g_deviceScanRetryDelayMutex);
939                                 break;
940                             }
941                             oc_mutex_unlock(g_deviceScanRetryDelayMutex);
942                             // time out
943
944                             // checking whether a target device is found while waiting for time-out.
945                             if (CALEClientIsDeviceInScanDeviceList(env, address))
946                             {
947                                 devicesDiscovered = true;
948                                 break;
949                             }
950                         }
951                     }
952                 }
953             }
954         }
955
956         // reset scan interval time after checking scanned devices
957         CALERestartScanWithInterval(0, 0, BLE_SCAN_DISABLE);
958
959         // time out for scanning devices
960         if (!devicesDiscovered)
961         {
962             return CA_STATUS_FAILED;
963         }
964     }
965     else
966     {
967         OIC_LOG(DEBUG, TAG, "there is a target device in the scanned devices");
968     }
969
970     return CA_STATUS_OK;
971 }
972
973
974 CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* data,
975                                             const uint32_t dataLen)
976 {
977     OIC_LOG(INFO, TAG, "CALEClientSendUnicastMessageImpl in");
978     OIC_LOG_V(DEBUG, 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_bleServerBDAddressMutex)
4444     {
4445         g_bleServerBDAddressMutex = oc_mutex_new();
4446         if (NULL == g_bleServerBDAddressMutex)
4447         {
4448             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4449             return CA_STATUS_FAILED;
4450         }
4451     }
4452
4453     if (NULL == g_threadMutex)
4454     {
4455         g_threadMutex = oc_mutex_new();
4456         if (NULL == g_threadMutex)
4457         {
4458             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4459             return CA_STATUS_FAILED;
4460         }
4461     }
4462
4463     if (NULL == g_threadSendMutex)
4464     {
4465         g_threadSendMutex = oc_mutex_new();
4466         if (NULL == g_threadSendMutex)
4467         {
4468             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4469             return CA_STATUS_FAILED;
4470         }
4471     }
4472
4473     if (NULL == g_deviceListMutex)
4474     {
4475         g_deviceListMutex = oc_mutex_new();
4476         if (NULL == g_deviceListMutex)
4477         {
4478             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4479             return CA_STATUS_FAILED;
4480         }
4481     }
4482
4483     if (NULL == g_gattObjectMutex)
4484     {
4485         g_gattObjectMutex = oc_mutex_new();
4486         if (NULL == g_gattObjectMutex)
4487         {
4488             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4489             return CA_STATUS_FAILED;
4490         }
4491     }
4492
4493     if (NULL == g_deviceStateListMutex)
4494     {
4495         g_deviceStateListMutex = oc_mutex_new();
4496         if (NULL == g_deviceStateListMutex)
4497         {
4498             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4499             return CA_STATUS_FAILED;
4500         }
4501     }
4502
4503     if (NULL == g_SendFinishMutex)
4504     {
4505         g_SendFinishMutex = oc_mutex_new();
4506         if (NULL == g_SendFinishMutex)
4507         {
4508             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4509             return CA_STATUS_FAILED;
4510         }
4511     }
4512
4513     if (NULL == g_threadWriteCharacteristicMutex)
4514     {
4515         g_threadWriteCharacteristicMutex = oc_mutex_new();
4516         if (NULL == g_threadWriteCharacteristicMutex)
4517         {
4518             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4519             return CA_STATUS_FAILED;
4520         }
4521     }
4522
4523     if (NULL == g_deviceScanRetryDelayMutex)
4524     {
4525         g_deviceScanRetryDelayMutex = oc_mutex_new();
4526         if (NULL == g_deviceScanRetryDelayMutex)
4527         {
4528             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4529             return CA_STATUS_FAILED;
4530         }
4531     }
4532
4533     if (NULL == g_threadSendStateMutex)
4534     {
4535         g_threadSendStateMutex = oc_mutex_new();
4536         if (NULL == g_threadSendStateMutex)
4537         {
4538             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4539             return CA_STATUS_FAILED;
4540         }
4541     }
4542
4543     if (NULL == g_threadScanIntervalMutex)
4544     {
4545         g_threadScanIntervalMutex = oc_mutex_new();
4546         if (NULL == g_threadScanIntervalMutex)
4547         {
4548             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4549             return CA_STATUS_FAILED;
4550         }
4551     }
4552
4553     if (NULL == g_setValueMutex)
4554     {
4555         g_setValueMutex = oc_mutex_new();
4556         if (NULL == g_setValueMutex)
4557         {
4558             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
4559             return CA_STATUS_FAILED;
4560         }
4561     }
4562
4563     return CA_STATUS_OK;
4564 }
4565
4566 void CALEClientTerminateGattMutexVariables()
4567 {
4568    
4569     oc_mutex_free(g_bleServerBDAddressMutex);
4570     g_bleServerBDAddressMutex = NULL;
4571
4572     oc_mutex_free(g_threadMutex);
4573     g_threadMutex = NULL;
4574
4575     oc_mutex_free(g_threadSendMutex);
4576     g_threadSendMutex = NULL;
4577
4578     oc_mutex_free(g_deviceListMutex);
4579     g_deviceListMutex = NULL;
4580
4581     oc_mutex_free(g_SendFinishMutex);
4582     g_SendFinishMutex = NULL;
4583
4584     oc_mutex_free(g_threadWriteCharacteristicMutex);
4585     g_threadWriteCharacteristicMutex = NULL;
4586
4587     oc_mutex_free(g_deviceScanRetryDelayMutex);
4588     g_deviceScanRetryDelayMutex = NULL;
4589
4590     oc_mutex_free(g_threadSendStateMutex);
4591     g_threadSendStateMutex = NULL;
4592
4593     oc_mutex_free(g_threadScanIntervalMutex);
4594     g_threadScanIntervalMutex = NULL;
4595
4596     oc_mutex_free(g_gattObjectMutex);
4597     g_gattObjectMutex = NULL;
4598
4599     oc_mutex_free(g_deviceStateListMutex);
4600     g_deviceStateListMutex = NULL;
4601
4602     oc_mutex_free(g_setValueMutex);
4603     g_setValueMutex = NULL;
4604 }
4605
4606 void CALEClientSetSendFinishFlag(bool flag)
4607 {
4608     OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag);
4609
4610     oc_mutex_lock(g_SendFinishMutex);
4611     g_isFinishedSendData = flag;
4612     oc_mutex_unlock(g_SendFinishMutex);
4613 }
4614
4615 /**
4616  * adapter common
4617  */
4618
4619 CAResult_t CAStartLEGattClient()
4620 {
4621     // init mutex for send logic
4622     if (!g_deviceDescCond)
4623     {
4624         g_deviceDescCond = oc_cond_new();
4625     }
4626
4627     if (!g_threadCond)
4628     {
4629         g_threadCond = oc_cond_new();
4630     }
4631
4632     if (!g_threadWriteCharacteristicCond)
4633     {
4634         g_threadWriteCharacteristicCond = oc_cond_new();
4635     }
4636
4637     if (!g_threadScanIntervalCond)
4638     {
4639         g_threadScanIntervalCond = oc_cond_new();
4640     }
4641
4642     CAResult_t ret = CALEClientStartScanWithInterval();
4643     if (CA_STATUS_OK != ret)
4644     {
4645         OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed");
4646         return ret;
4647     }
4648
4649     g_isStartedLEClient = true;
4650     return CA_STATUS_OK;
4651 }
4652
4653 void CAStopLEGattClient()
4654 {
4655     OIC_LOG(DEBUG, TAG, "CAStopBLEGattClient");
4656
4657     if (!g_jvm)
4658     {
4659         OIC_LOG(ERROR, TAG, "g_jvm is null");
4660         return;
4661     }
4662
4663     bool isAttached = false;
4664     JNIEnv* env = NULL;
4665     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
4666     if (JNI_OK != res)
4667     {
4668         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
4669
4670         if (JNI_OK != res)
4671         {
4672             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
4673             return;
4674         }
4675         isAttached = true;
4676     }
4677
4678     CAResult_t ret = CALEClientDisconnectAll(env);
4679     if (CA_STATUS_OK != ret)
4680     {
4681         OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
4682     }
4683
4684     CALEClientStopScanWithInterval();
4685
4686     oc_mutex_lock(g_threadWriteCharacteristicMutex);
4687     OIC_LOG(DEBUG, TAG, "signal - WriteCharacteristic cond");
4688     oc_cond_signal(g_threadWriteCharacteristicCond);
4689     oc_mutex_unlock(g_threadWriteCharacteristicMutex);
4690
4691     CALEClientSetSendFinishFlag(true);
4692     oc_mutex_lock(g_threadMutex);
4693     OIC_LOG(DEBUG, TAG, "signal - g_threadCond cond");
4694     oc_cond_signal(g_threadCond);
4695     oc_mutex_unlock(g_threadMutex);
4696
4697     oc_mutex_lock(g_deviceScanRetryDelayMutex);
4698     OIC_LOG(DEBUG, TAG, "signal - delay cond");
4699     oc_cond_signal(g_deviceScanRetryDelayCond);
4700     oc_mutex_unlock(g_deviceScanRetryDelayMutex);
4701
4702     oc_mutex_lock(g_threadScanIntervalMutex);
4703     OIC_LOG(DEBUG, TAG, "signal - delay cond");
4704     oc_cond_signal(g_threadScanIntervalCond);
4705     oc_mutex_unlock(g_threadScanIntervalMutex);
4706
4707     oc_mutex_lock(g_threadSendMutex);
4708     OIC_LOG(DEBUG, TAG, "signal - g_deviceDesc cond");
4709     oc_cond_signal(g_deviceDescCond);
4710     oc_mutex_unlock(g_threadSendMutex);
4711
4712     oc_cond_free(g_deviceDescCond);
4713     oc_cond_free(g_threadCond);
4714     oc_cond_free(g_threadWriteCharacteristicCond);
4715     oc_cond_free(g_deviceScanRetryDelayCond);
4716     oc_cond_free(g_threadScanIntervalCond);
4717
4718     g_deviceDescCond = NULL;
4719     g_threadCond = NULL;
4720     g_threadWriteCharacteristicCond = NULL;
4721     g_deviceScanRetryDelayCond = NULL;
4722     g_threadScanIntervalCond = NULL;
4723
4724     if (isAttached)
4725     {
4726         (*g_jvm)->DetachCurrentThread(g_jvm);
4727     }
4728
4729 }
4730
4731 CAResult_t CAInitializeLEGattClient()
4732 {
4733     OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
4734     CALEClientInitialize();
4735     return CA_STATUS_OK;
4736 }
4737
4738 void CATerminateLEGattClient()
4739 {
4740     OIC_LOG(INFO, TAG, "IN - Terminate GATT Client");
4741     CAStopLEGattClient();
4742     CALEClientTerminate();
4743     OIC_LOG(INFO, TAG, "OUT - Terminate GATT Client");
4744 }
4745
4746 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t  *data,
4747                                                uint32_t dataLen, CALETransferType_t type,
4748                                                int32_t position)
4749 {
4750     OIC_LOG(INFO, TAG, "call CALEClientSendUnicastMessage");
4751     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
4752
4753     if (LE_UNICAST != type || position < 0)
4754     {
4755         OIC_LOG(ERROR, TAG, "this request is not unicast");
4756         return CA_STATUS_INVALID_PARAM;
4757     }
4758
4759     return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
4760 }
4761
4762 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
4763 {
4764     OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
4765     VERIFY_NON_NULL(data, TAG, "data is null");
4766
4767     return CALEClientSendMulticastMessage(data, dataLen);
4768 }
4769
4770 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
4771 {
4772     
4773     g_CABLEClientDataReceivedCallback = callback;
4774     
4775 }
4776
4777 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
4778 {
4779     g_threadPoolHandle = handle;
4780 }
4781
4782 CAResult_t CAGetLEAddress(char **local_address)
4783 {
4784     VERIFY_NON_NULL(local_address, TAG, "local_address");
4785     return CA_NOT_SUPPORTED;
4786 }
4787
4788 JNIEXPORT void JNICALL
4789 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
4790                                                                     jobject callback)
4791 {
4792     OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
4793     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4794     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4795     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
4796
4797     g_leScanCallback = (*env)->NewGlobalRef(env, callback);
4798     CACheckJNIException(env);
4799 }
4800
4801 JNIEXPORT void JNICALL
4802 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallbackForV21(JNIEnv *env,
4803                                                                           jobject obj,
4804                                                                           jobject callback)
4805 {
4806     OIC_LOG(DEBUG, TAG, "caLeRegisterLeScanCallbackForV21");
4807     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4808     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4809     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
4810
4811     g_leScanCallback = (*env)->NewGlobalRef(env, callback);
4812     CACheckJNIException(env);
4813 }
4814
4815 JNIEXPORT void JNICALL
4816 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
4817                                                                   jobject callback)
4818 {
4819     OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
4820     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4821     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4822     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
4823
4824     g_leGattCallback = (*env)->NewGlobalRef(env, callback);
4825     CACheckJNIException(env);
4826 }
4827
4828 JNIEXPORT void JNICALL
4829 Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
4830                                                           jobject device)
4831 {
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(device, TAG, "device is null");
4835
4836     CAResult_t res = CALEClientAddScanDeviceToList(env, device);
4837     if (CA_STATUS_OK != res)
4838     {
4839         OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
4840     }
4841 }
4842
4843 JNIEXPORT void JNICALL
4844 Java_org_iotivity_ca_CaLeClientInterface_caLeScanFailedCallback(JNIEnv *env, jobject obj,
4845                                                                 jint errorCode)
4846 {
4847     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4848     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4849
4850     switch (errorCode)
4851     {
4852         case 1:
4853             OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_ALREADY_STARTED");
4854             break;
4855
4856         case 2:
4857             OIC_LOG(ERROR, TAG,
4858                     "BLE scan has failed, error is SCAN_FAILED_APPLICATION_REGISTRATION_FAILED");
4859             break;
4860
4861         case 3:
4862             OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_INTERNAL_ERROR");
4863             break;
4864
4865         case 4:
4866             OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_FEATURE_UNSUPPORTED");
4867             break;
4868
4869         default:
4870             OIC_LOG(ERROR, TAG, "BLE scan has failed with unknown error");
4871             break;
4872     }
4873 }
4874
4875 /*
4876  * Class:     org_iotivity_ca_jar_caleinterface
4877  * Method:    CALeGattConnectionStateChangeCallback
4878  * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
4879  */
4880 JNIEXPORT void JNICALL
4881 Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
4882                                                                                jobject obj,
4883                                                                                jobject gatt,
4884                                                                                jint status,
4885                                                                                jint newstate)
4886 {
4887     OIC_LOG_V(INFO, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
4888               newstate);
4889     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4890     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4891     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4892
4893     jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
4894
4895     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4896     if (!jni_address)
4897     {
4898         OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
4899         goto error_exit;
4900     }
4901
4902     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4903     if (!address)
4904     {
4905         OIC_LOG(ERROR, TAG, "address is null");
4906         CACheckJNIException(env);
4907         goto error_exit;
4908     }
4909     OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address);
4910
4911     if (state_connected == newstate)
4912     {
4913         OIC_LOG(DEBUG, TAG, "LE is connected");
4914         if (GATT_SUCCESS == status)
4915         {
4916             CAResult_t res = CALEUpdateDeviceState(address,
4917                                                    CA_LE_CONNECTION_STATE,
4918                                                    STATE_CONNECTED,
4919                                                    g_deviceStateList,
4920                                                    g_deviceStateListMutex);
4921             (*env)->ReleaseStringUTFChars(env, jni_address, address);
4922             if (CA_STATUS_OK != res)
4923             {
4924                 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
4925                 goto error_exit;
4926             }
4927
4928             res = CALEClientAddGattobjToList(env, gatt);
4929             if (CA_STATUS_OK != res)
4930             {
4931                 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
4932                 goto error_exit;
4933             }
4934
4935             res = CALEClientDiscoverServices(env, gatt);
4936             if (CA_STATUS_OK != res)
4937             {
4938                 OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
4939                 goto error_exit;
4940             }
4941         }
4942         else
4943         {
4944             OIC_LOG(INFO, TAG, "unknown status");
4945             (*env)->ReleaseStringUTFChars(env, jni_address, address);
4946         }
4947     }
4948     else // STATE_DISCONNECTED == newstate
4949     {
4950         OIC_LOG(DEBUG, TAG, "LE is disconnected");
4951
4952         if (CALEIsValidState(address, CA_LE_SEND_STATE, STATE_SEND_PREPARING,
4953                              g_deviceStateList, g_deviceStateListMutex))
4954         {
4955             OIC_LOG(INFO, TAG, "current state is STATE_SEND_PREPARING");
4956             CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
4957                                                    STATE_SEND_FAIL,
4958                                                    g_deviceStateList,
4959                                                    g_deviceStateListMutex);
4960             if (CA_STATUS_OK != res)
4961             {
4962                 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
4963             }
4964         }
4965
4966         CAResult_t res = CALEUpdateDeviceState(address,
4967                                                CA_LE_CONNECTION_STATE,
4968                                                STATE_DISCONNECTED,
4969                                                g_deviceStateList,
4970                                                g_deviceStateListMutex);
4971         if (CA_STATUS_OK != res)
4972         {
4973             OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
4974         }
4975         (*env)->ReleaseStringUTFChars(env, jni_address, address);
4976
4977         res = CALEClientGattClose(env, gatt);
4978         if (CA_STATUS_OK != res)
4979         {
4980             OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
4981         }
4982
4983         if (CALECheckConnectionStateValue(status))
4984         {
4985             // this state is unexpected reason to disconnect
4986             // if the reason is suitable, connection logic of the device will be destroyed.
4987             OIC_LOG(INFO, TAG, "connection logic destroy");
4988         }
4989         else
4990         {
4991             // other reason except for gatt_success is expected to running
4992             // background connection in BT platform.
4993             OIC_LOG(INFO, TAG, "unknown status or manual disconnected state");
4994         }
4995         CALEClientUpdateSendCnt(env);
4996     }
4997     return;
4998
4999     // error label.
5000 error_exit:
5001     CALEClientSendFinish(env, gatt);
5002     return;
5003 }
5004
5005 /*
5006  * Class:     org_iotivity_ca_jar_caleinterface
5007  * Method:    CALeGattServicesDiscoveredCallback
5008  * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
5009  */
5010 JNIEXPORT void JNICALL
5011 Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
5012                                                                             jobject obj,
5013                                                                             jobject gatt,
5014                                                                             jint status)
5015 {
5016     OIC_LOG_V(INFO, TAG, "CALeGattServicesDiscoveredCallback - status %d", status);
5017     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
5018     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
5019     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
5020
5021     if (GATT_SUCCESS != status) // discovery error
5022     {
5023         CALEClientSendFinish(env, gatt);
5024         return;
5025     }
5026
5027     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
5028     if (!jni_address)
5029     {
5030         CALEClientSendFinish(env, gatt);
5031         return;
5032     }
5033
5034     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
5035     if (!address)
5036     {
5037         CACheckJNIException(env);
5038         CALEClientSendFinish(env, gatt);
5039         return;
5040     }
5041
5042     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
5043     if (!jni_uuid)
5044     {
5045         OIC_LOG(ERROR, TAG, "jni_uuid is null");
5046         goto error_exit;
5047     }
5048
5049     jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
5050     if (!jni_obj_GattCharacteristic)
5051     {
5052         OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
5053         goto error_exit;
5054     }
5055
5056     CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
5057                                                              jni_obj_GattCharacteristic);
5058     if (CA_STATUS_OK != res)
5059     {
5060         OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
5061         goto error_exit;
5062     }
5063
5064     res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
5065     if (CA_STATUS_OK != res)
5066     {
5067         OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
5068
5069         res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_FALSE,
5070                                  g_deviceStateList, g_deviceStateListMutex);
5071         if (CA_STATUS_OK != res)
5072         {
5073             OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed");
5074             goto error_exit;
5075         }
5076
5077         res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
5078                                     STATE_SERVICE_CONNECTED,
5079                                     g_deviceStateList,
5080                                     g_deviceStateListMutex);
5081         if (CA_STATUS_OK != res)
5082         {
5083             OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
5084             goto error_exit;
5085         }
5086
5087         res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE);
5088         if (CA_STATUS_OK != res)
5089         {
5090             OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed");
5091             goto error_exit;
5092         }
5093     }
5094     else
5095     {
5096         res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_TRUE,
5097                                  g_deviceStateList, g_deviceStateListMutex);
5098         if (CA_STATUS_OK != res)
5099         {
5100             OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed");
5101             goto error_exit;
5102         }
5103     }
5104
5105 #ifdef SCAN_INTERVAL
5106     // reset interval scan logic
5107     CALERestartScanWithInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE);
5108 #endif
5109
5110     OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
5111     (*env)->ReleaseStringUTFChars(env, jni_address, address);
5112     return;
5113
5114     // error label.
5115 error_exit:
5116     OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
5117     (*env)->ReleaseStringUTFChars(env, jni_address, address);
5118     CALEClientSendFinish(env, gatt);
5119     return;
5120 }
5121
5122 /*
5123  * Class:     org_iotivity_ca_jar_caleinterface
5124  * Method:    CALeGattCharacteristicWritjclasseCallback
5125  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
5126  */
5127 JNIEXPORT void JNICALL
5128 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
5129         JNIEnv *env, jobject obj, jobject gatt, jbyteArray data, jint status)
5130 {
5131     OIC_LOG_V(INFO, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
5132     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
5133     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
5134     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
5135
5136     // send success & signal
5137     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
5138     if (!jni_address)
5139     {
5140         goto error_exit;
5141     }
5142
5143     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
5144     if (!address)
5145     {
5146         CACheckJNIException(env);
5147         goto error_exit;
5148     }
5149
5150     if (GATT_SUCCESS != status) // error case
5151     {
5152         OIC_LOG(ERROR, TAG, "send failure");
5153
5154         // retry to write
5155         CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
5156         if (CA_STATUS_OK != res)
5157         {
5158             OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
5159             oc_mutex_lock(g_threadWriteCharacteristicMutex);
5160             g_isSignalSetFlag = true;
5161             oc_cond_signal(g_threadWriteCharacteristicCond);
5162             oc_mutex_unlock(g_threadWriteCharacteristicMutex);
5163
5164             CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
5165                                                    STATE_SEND_FAIL,
5166                                                    g_deviceStateList,
5167                                                    g_deviceStateListMutex);
5168             if (CA_STATUS_OK != res)
5169             {
5170                 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
5171             }
5172
5173             if (g_clientErrorCallback)
5174             {
5175                 jint length = (*env)->GetArrayLength(env, data);
5176                 CACheckJNIException(env);
5177                 g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
5178                 CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0, length,
5179                                    false, "writeChar failure");
5180             }
5181
5182             (*env)->ReleaseStringUTFChars(env, jni_address, address);
5183             goto error_exit;
5184         }
5185     }
5186     else
5187     {
5188         OIC_LOG(DEBUG, TAG, "send success");
5189         CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
5190                                                STATE_SEND_SUCCESS,
5191                                                g_deviceStateList,
5192                                                g_deviceStateListMutex);
5193         if (CA_STATUS_OK != res)
5194         {
5195             OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
5196         }
5197
5198         oc_mutex_lock(g_threadWriteCharacteristicMutex);
5199         OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
5200         g_isSignalSetFlag = true;
5201         oc_cond_signal(g_threadWriteCharacteristicCond);
5202         oc_mutex_unlock(g_threadWriteCharacteristicMutex);
5203
5204         CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0,
5205                            (*env)->GetArrayLength(env, data),
5206                            true, "writeChar success");
5207     }
5208
5209     (*env)->ReleaseStringUTFChars(env, jni_address, address);
5210     return;
5211
5212     // error label.
5213 error_exit:
5214
5215     CALEClientSendFinish(env, gatt);
5216     return;
5217 }
5218
5219 /*
5220  * Class:     org_iotivity_ca_jar_caleinterface
5221  * Method:    CALeGattCharacteristicChangedCallback
5222  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
5223  */
5224 JNIEXPORT void JNICALL
5225 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
5226         JNIEnv *env, jobject obj, jobject gatt, jbyteArray data)
5227 {
5228     OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicChangedCallback");
5229     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
5230     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
5231     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
5232     VERIFY_NON_NULL_VOID(data, TAG, "data is null");
5233
5234     // get Byte Array and convert to uint8_t*
5235     jint length = (*env)->GetArrayLength(env, data);
5236
5237     jboolean isCopy;
5238     jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
5239     CACheckJNIException(env);
5240
5241     uint8_t* receivedData = OICMalloc(length);
5242     if (!receivedData)
5243     {
5244         OIC_LOG(ERROR, TAG, "receivedData is null");
5245         return;
5246     }
5247
5248     memcpy(receivedData, jni_byte_responseData, length);
5249     (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
5250
5251     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
5252     if (!jni_address)
5253     {
5254         OIC_LOG(ERROR, TAG, "jni_address is null");
5255         OICFree(receivedData);
5256         return;
5257     }
5258
5259     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
5260     if (!address)
5261     {
5262         OIC_LOG(ERROR, TAG, "address is null");
5263         CACheckJNIException(env);
5264         OICFree(receivedData);
5265         return;
5266     }
5267
5268     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
5269               receivedData, length);
5270
5271     uint32_t sentLength = 0;
5272     oc_mutex_lock(g_bleServerBDAddressMutex);
5273     g_CABLEClientDataReceivedCallback(address, receivedData, length, &sentLength);
5274     oc_mutex_unlock(g_bleServerBDAddressMutex);
5275
5276     (*env)->ReleaseStringUTFChars(env, jni_address, address);
5277 }
5278
5279 /*
5280  * Class:     org_iotivity_ca_jar_caleinterface
5281  * Method:    CALeGattDescriptorWriteCallback
5282  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
5283  */
5284 JNIEXPORT void JNICALL
5285 Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
5286                                                                          jobject gatt,
5287                                                                          jint status)
5288 {
5289     OIC_LOG_V(INFO, TAG, "CALeGattDescriptorWriteCallback - status %d", status);
5290     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
5291     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
5292     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
5293
5294     if (GATT_SUCCESS != status) // error
5295     {
5296         goto error_exit;
5297     }
5298
5299     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
5300     if (!jni_address)
5301     {
5302         goto error_exit;
5303     }
5304
5305     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
5306     if (!address)
5307     {
5308         CACheckJNIException(env);
5309         goto error_exit;
5310     }
5311
5312     CAResult_t res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
5313                                            STATE_SERVICE_CONNECTED,
5314                                            g_deviceStateList,
5315                                            g_deviceStateListMutex);
5316     (*env)->ReleaseStringUTFChars(env, jni_address, address);
5317     if (CA_STATUS_OK != res)
5318     {
5319         OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
5320         goto error_exit;
5321     }
5322
5323     res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE);
5324     if (CA_STATUS_OK != res)
5325     {
5326         OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed");
5327         goto error_exit;
5328     }
5329     return;
5330
5331 // error label.
5332 error_exit:
5333
5334     CALEClientSendFinish(env, gatt);
5335     return;
5336 }
5337
5338 JNIEXPORT void JNICALL
5339 Java_org_iotivity_ca_CaLeClientInterface_caLeGattMtuChangedCallback(JNIEnv *env,
5340                                                                     jobject obj,
5341                                                                     jobject gatt,
5342                                                                     jint mtu,
5343                                                                     jint status)
5344 {
5345     OIC_LOG_V(INFO, TAG, "caLeGattMtuChangedCallback - status %d, "
5346               "mtu[%d-including Header size 3 byte]", status, mtu);
5347
5348     (void)obj;
5349
5350     if (0 == status || 133 == status)
5351     {
5352         if (g_sendBuffer)
5353         {
5354             CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
5355             if (CA_STATUS_OK != res)
5356             {
5357                 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
5358             }
5359         }
5360         else
5361         {
5362             OIC_LOG(INFO, TAG, "mtu nego is done");
5363             jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
5364             if (!jni_address)
5365             {
5366                 CALEClientSendFinish(env, gatt);
5367                 return;
5368             }
5369
5370             const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
5371             if (!address)
5372             {
5373                 CACheckJNIException(env);
5374                 (*env)->DeleteLocalRef(env, jni_address);
5375                 CALEClientSendFinish(env, gatt);
5376                 return;
5377             }
5378
5379             // update mtu size
5380             CAResult_t res = CALESetMtuSize(address, mtu - CA_BLE_MTU_HEADER_SIZE,
5381                                             g_deviceStateList, g_deviceStateListMutex);
5382             if (CA_STATUS_OK != res)
5383             {
5384                 OIC_LOG(ERROR, TAG, "CALESetMtuSize has failed");
5385             }
5386
5387             res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
5388                                         STATE_SEND_MTU_NEGO_SUCCESS,
5389                                         g_deviceStateList,
5390                                         g_deviceStateListMutex);
5391             if (CA_STATUS_OK != res)
5392             {
5393                 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
5394             }
5395             CALEClientUpdateSendCnt(env);
5396             (*env)->ReleaseStringUTFChars(env, jni_address, address);
5397             (*env)->DeleteLocalRef(env, jni_address);
5398         }
5399     }
5400 }