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