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