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