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