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