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