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
745                 // connect to gatt server
746                 ret = CALEClientStopScan();
747                 if (CA_STATUS_OK != ret)
748                 {
749                     OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
750                     goto error_exit;
751                 }
752
753                 if (g_sendBuffer)
754                 {
755                     (*env)->DeleteGlobalRef(env, g_sendBuffer);
756                     g_sendBuffer = NULL;
757                 }
758                 jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
759                 (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
760                 g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
761
762                 // Target device to send message is just one.
763                 g_targetCnt = 1;
764
765                 ret = CALEClientSendData(env, jarrayObj);
766                 if (CA_STATUS_OK != ret)
767                 {
768                     OIC_LOG(ERROR, TAG, "CALEClientSendData in unicast is failed");
769                     goto error_exit;
770                 }
771
772                 OIC_LOG(INFO, TAG, "wake up");
773                 break;
774             }
775             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
776         }
777     }
778
779     OIC_LOG(DEBUG, TAG, "connection routine is finished for unicast");
780
781     // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
782     // if there is no connection state.
783     ca_mutex_lock(g_threadMutex);
784     if (!g_isFinishedSendData)
785     {
786         OIC_LOG(DEBUG, TAG, "waiting send finish signal");
787         ca_cond_wait(g_threadCond, g_threadMutex);
788         OIC_LOG(DEBUG, TAG, "the data was sent");
789     }
790     ca_mutex_unlock(g_threadMutex);
791
792     if (isAttached)
793     {
794         (*g_jvm)->DetachCurrentThread(g_jvm);
795     }
796
797     // start LE Scan again
798     ret = CALEClientStartScan();
799     if (CA_STATUS_OK != ret)
800     {
801         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
802         ca_mutex_unlock(g_threadSendMutex);
803         return ret;
804     }
805
806     ca_mutex_unlock(g_threadSendMutex);
807     OIC_LOG(INFO, TAG, "unicast - send logic has finished");
808     if (CALEClientIsValidState(address, CA_LE_SEND_STATE,
809                                STATE_SEND_SUCCESS))
810     {
811         ret = CA_STATUS_OK;
812     }
813     else
814     {
815         ret = CA_SEND_FAILED;
816     }
817
818     // reset send state
819     ret = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
820                                       STATE_SEND_NONE);
821     if (CA_STATUS_OK != ret)
822     {
823         OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
824     }
825
826     return ret;
827
828     // error label.
829 error_exit:
830
831     // start LE Scan again
832     ret = CALEClientStartScan();
833     if (CA_STATUS_OK != ret)
834     {
835         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
836         ca_mutex_unlock(g_threadSendMutex);
837         if (isAttached)
838         {
839             (*g_jvm)->DetachCurrentThread(g_jvm);
840         }
841         return ret;
842     }
843
844     if (isAttached)
845     {
846         (*g_jvm)->DetachCurrentThread(g_jvm);
847     }
848
849     ca_mutex_unlock(g_threadSendMutex);
850     return CA_SEND_FAILED;
851 }
852
853 CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data,
854                                               const uint32_t dataLen)
855 {
856     OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %p, %u", data, dataLen);
857     VERIFY_NON_NULL(data, TAG, "data is null");
858     VERIFY_NON_NULL(env, TAG, "env is null");
859
860     if (!g_deviceList)
861     {
862         OIC_LOG(ERROR, TAG, "g_deviceList is null");
863         return CA_STATUS_FAILED;
864     }
865
866     ca_mutex_lock(g_threadSendMutex);
867
868     CALEClientSetSendFinishFlag(false);
869
870     OIC_LOG(DEBUG, TAG, "set byteArray for data");
871     if (g_sendBuffer)
872     {
873         (*env)->DeleteGlobalRef(env, g_sendBuffer);
874         g_sendBuffer = NULL;
875     }
876
877     CAResult_t res = CALEClientIsThereScannedDevices(env, NULL);
878     if (CA_STATUS_OK != res)
879     {
880         OIC_LOG(INFO, TAG, "there is no scanned device");
881         goto error_exit;
882     }
883
884     // connect to gatt server
885     res = CALEClientStopScan();
886     if (CA_STATUS_OK != res)
887     {
888         OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
889         ca_mutex_unlock(g_threadSendMutex);
890         return res;
891     }
892     uint32_t length = u_arraylist_length(g_deviceList);
893     g_targetCnt = length;
894
895     jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
896     (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
897     g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
898
899     for (uint32_t index = 0; index < length; index++)
900     {
901         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
902         if (!jarrayObj)
903         {
904             OIC_LOG(ERROR, TAG, "jarrayObj is not available");
905             continue;
906         }
907
908         res = CALEClientSendData(env, jarrayObj);
909         if (res != CA_STATUS_OK)
910         {
911             OIC_LOG(ERROR, TAG, "BT device - send has failed");
912         }
913
914         jstring jni_address = CALEGetAddressFromBTDevice(env, jarrayObj);
915         if (!jni_address)
916         {
917             OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
918             continue;
919         }
920
921         const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
922         if (!address)
923         {
924             OIC_LOG(ERROR, TAG, "address is not available");
925             continue;
926         }
927
928         (*env)->ReleaseStringUTFChars(env, jni_address, address);
929     }
930
931     OIC_LOG(DEBUG, TAG, "connection routine is finished for multicast");
932
933     // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
934     ca_mutex_lock(g_threadMutex);
935     if (!g_isFinishedSendData)
936     {
937         OIC_LOG(DEBUG, TAG, "waiting send finish signal");
938         ca_cond_wait(g_threadCond, g_threadMutex);
939         OIC_LOG(DEBUG, TAG, "the data was sent");
940     }
941     ca_mutex_unlock(g_threadMutex);
942
943     // start LE Scan again
944     res = CALEClientStartScan();
945     if (CA_STATUS_OK != res)
946     {
947         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
948         ca_mutex_unlock(g_threadSendMutex);
949         return res;
950     }
951
952     ca_mutex_unlock(g_threadSendMutex);
953     OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
954     return CA_STATUS_OK;
955
956 error_exit:
957     res = CALEClientStartScan();
958     if (CA_STATUS_OK != res)
959     {
960         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
961         ca_mutex_unlock(g_threadSendMutex);
962         return res;
963     }
964
965     ca_mutex_unlock(g_threadSendMutex);
966     OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
967     return CA_SEND_FAILED;
968 }
969
970 CAResult_t CALEClientSendData(JNIEnv *env, jobject device)
971 {
972     OIC_LOG(DEBUG, TAG, "IN - CALEClientSendData");
973     VERIFY_NON_NULL(device, TAG, "device is null");
974     VERIFY_NON_NULL(env, TAG, "env is null");
975
976     // get BLE address from bluetooth device object.
977     char* address = NULL;
978     CALEState_t* state = NULL;
979     jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, device);
980     if (jni_address)
981     {
982         OIC_LOG(INFO, TAG, "there is gatt object..it's not first connection");
983         address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
984         if (!address)
985         {
986             OIC_LOG(ERROR, TAG, "address is not available");
987             return CA_STATUS_FAILED;
988         }
989         ca_mutex_lock(g_deviceStateListMutex);
990         state = CALEClientGetStateInfo(address);
991         ca_mutex_unlock(g_deviceStateListMutex);
992     }
993
994     if (!state)
995     {
996         OIC_LOG(DEBUG, TAG, "state is empty..start to connect LE");
997
998         // cancel previous connection request before connection
999         // if there is gatt object in g_gattObjectList.
1000         if (jni_address)
1001         {
1002             jobject gatt = CALEClientGetGattObjInList(env, address);
1003             if (gatt)
1004             {
1005                 CAResult_t res = CALEClientDisconnect(env, gatt);
1006                 if (CA_STATUS_OK != res)
1007                 {
1008                     OIC_LOG(INFO, TAG, "there is no gatt object");
1009                 }
1010             }
1011             (*env)->ReleaseStringUTFChars(env, jni_address, address);
1012         }
1013
1014         // connection request
1015         jobject newGatt = CALEClientConnect(env, device,
1016                                             JNI_FALSE);
1017         if (NULL == newGatt)
1018         {
1019             OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
1020             return CA_STATUS_FAILED;
1021         }
1022     }
1023     else
1024     {
1025         if (CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1026                                    STATE_SERVICE_CONNECTED))
1027         {
1028             OIC_LOG(INFO, TAG, "GATT has already connected");
1029
1030             jobject gatt = CALEClientGetGattObjInList(env, address);
1031             if (!gatt)
1032             {
1033                 OIC_LOG(ERROR, TAG, "CALEClientGetGattObjInList has failed");
1034                 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1035                 return CA_STATUS_FAILED;
1036             }
1037
1038             CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
1039             if (CA_STATUS_OK != ret)
1040             {
1041                 OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
1042                 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1043                 return ret;
1044             }
1045             (*env)->ReleaseStringUTFChars(env, jni_address, address);
1046         }
1047         else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1048                                        STATE_CONNECTED))
1049         {
1050             OIC_LOG(INFO, TAG, "service connecting...");
1051         }
1052         else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1053                                        STATE_DISCONNECTED))
1054         {
1055             OIC_LOG(INFO, TAG, "STATE_DISCONNECTED - start to connect LE");
1056
1057             // cancel previous connection request before connection
1058             // if there is gatt object in g_gattObjectList.
1059             if (jni_address)
1060             {
1061                 jobject gatt = CALEClientGetGattObjInList(env, address);
1062                 if (gatt)
1063                 {
1064                     CAResult_t res = CALEClientDisconnect(env, gatt);
1065                     if (CA_STATUS_OK != res)
1066                     {
1067                         OIC_LOG(INFO, TAG, "there is no gatt object");
1068                     }
1069                 }
1070                 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1071             }
1072
1073             OIC_LOG(DEBUG, TAG, "start to connect LE");
1074             jobject gatt = CALEClientConnect(env, device,
1075                                              CALEClientGetFlagFromState(env, jni_address,
1076                                                                         CA_LE_AUTO_CONNECT_FLAG));
1077             if (NULL == gatt)
1078             {
1079                 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
1080                 return CA_STATUS_FAILED;
1081             }
1082         }
1083     }
1084
1085     return CA_STATUS_OK;
1086 }
1087
1088 jstring CALEClientGetAddressFromGattObj(JNIEnv *env, jobject gatt)
1089 {
1090     VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
1091     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1092
1093     jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "getDevice",
1094                                                    "()Landroid/bluetooth/BluetoothDevice;");
1095     if (!jni_mid_getDevice)
1096     {
1097         OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
1098         return NULL;
1099     }
1100
1101     jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
1102     if (!jni_obj_device)
1103     {
1104         OIC_LOG(ERROR, TAG, "jni_obj_device is null");
1105         return NULL;
1106     }
1107
1108     jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
1109     if (!jni_address)
1110     {
1111         OIC_LOG(ERROR, TAG, "jni_address is null");
1112         return NULL;
1113     }
1114
1115     return jni_address;
1116 }
1117
1118 /**
1119  * BLE layer
1120  */
1121 CAResult_t CALEClientGattClose(JNIEnv *env, jobject bluetoothGatt)
1122 {
1123     // GATT CLOSE
1124     OIC_LOG(DEBUG, TAG, "Gatt Close");
1125     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1126     VERIFY_NON_NULL(env, TAG, "env is null");
1127
1128     // get BluetoothGatt method
1129     OIC_LOG(DEBUG, TAG, "get BluetoothGatt method");
1130     jmethodID jni_mid_closeGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "close", "()V");
1131     if (!jni_mid_closeGatt)
1132     {
1133         OIC_LOG(ERROR, TAG, "jni_mid_closeGatt is null");
1134         return CA_STATUS_OK;
1135     }
1136
1137     // call disconnect gatt method
1138     OIC_LOG(DEBUG, TAG, "request to close GATT");
1139     (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_closeGatt);
1140
1141     if ((*env)->ExceptionCheck(env))
1142     {
1143         OIC_LOG(ERROR, TAG, "closeGATT has failed");
1144         (*env)->ExceptionDescribe(env);
1145         (*env)->ExceptionClear(env);
1146         return CA_STATUS_FAILED;
1147     }
1148
1149     return CA_STATUS_OK;
1150 }
1151
1152 CAResult_t CALEClientStartScan()
1153 {
1154     if (!g_isStartedLEClient)
1155     {
1156         OIC_LOG(ERROR, TAG, "LE client is not started");
1157         return CA_STATUS_FAILED;
1158     }
1159
1160     if (!g_jvm)
1161     {
1162         OIC_LOG(ERROR, TAG, "g_jvm is null");
1163         return CA_STATUS_FAILED;
1164     }
1165
1166     if (g_isStartedScan)
1167     {
1168         OIC_LOG(INFO, TAG, "scanning is already started");
1169         return CA_STATUS_OK;
1170     }
1171
1172     bool isAttached = false;
1173     JNIEnv* env;
1174     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1175     if (JNI_OK != res)
1176     {
1177         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1178
1179         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1180         if (JNI_OK != res)
1181         {
1182             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1183             return CA_STATUS_FAILED;
1184         }
1185         isAttached = true;
1186     }
1187
1188     OIC_LOG(DEBUG, TAG, "CALEClientStartScan");
1189
1190     CAResult_t ret = CA_STATUS_OK;
1191     // scan gatt server with UUID
1192     if (g_leScanCallback && g_uuidList)
1193     {
1194 #ifdef UUID_SCAN
1195         ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback);
1196 #else
1197         ret = CALEClientStartScanImpl(env, g_leScanCallback);
1198 #endif
1199         if (CA_STATUS_OK != ret)
1200         {
1201             if (CA_ADAPTER_NOT_ENABLED == ret)
1202             {
1203                 OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1204             }
1205             else
1206             {
1207                 OIC_LOG(ERROR, TAG, "start scan has failed");
1208             }
1209         }
1210     }
1211
1212     if (isAttached)
1213     {
1214         (*g_jvm)->DetachCurrentThread(g_jvm);
1215     }
1216
1217     return ret;
1218 }
1219
1220 CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback)
1221 {
1222     VERIFY_NON_NULL(callback, TAG, "callback is null");
1223     VERIFY_NON_NULL(env, TAG, "env is null");
1224
1225     if (!CALEIsEnableBTAdapter(env))
1226     {
1227         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1228         return CA_ADAPTER_NOT_ENABLED;
1229     }
1230
1231     // get default bt adapter class
1232     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1233     if (!jni_cid_BTAdapter)
1234     {
1235         OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1236         return CA_STATUS_FAILED;
1237     }
1238
1239     // get remote bt adapter method
1240     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1241                                                                     "getDefaultAdapter",
1242                                                                     METHODID_OBJECTNONPARAM);
1243     if (!jni_mid_getDefaultAdapter)
1244     {
1245         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1246         return CA_STATUS_FAILED;
1247     }
1248
1249     // get start le scan method
1250     jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1251                                                         "(Landroid/bluetooth/BluetoothAdapter$"
1252                                                         "LeScanCallback;)Z");
1253     if (!jni_mid_startLeScan)
1254     {
1255         OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1256         return CA_STATUS_FAILED;
1257     }
1258
1259     // gat bt adapter object
1260     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1261                                                                jni_mid_getDefaultAdapter);
1262     if (!jni_obj_BTAdapter)
1263     {
1264         OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1265         return CA_STATUS_FAILED;
1266     }
1267
1268     // call start le scan method
1269     OIC_LOG(INFO, TAG, "CALL API - startLeScan");
1270     jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1271                                                              jni_mid_startLeScan, callback);
1272     if (!jni_obj_startLeScan)
1273     {
1274         OIC_LOG(INFO, TAG, "startLeScan has failed");
1275     }
1276     else
1277     {
1278         OIC_LOG(DEBUG, TAG, "LeScan has started");
1279         CALEClientSetScanFlag(true);
1280     }
1281
1282     return CA_STATUS_OK;
1283 }
1284
1285 CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback)
1286 {
1287     VERIFY_NON_NULL(callback, TAG, "callback is null");
1288     VERIFY_NON_NULL(uuids, TAG, "uuids is null");
1289     VERIFY_NON_NULL(env, TAG, "env is null");
1290
1291     if (!CALEIsEnableBTAdapter(env))
1292     {
1293         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1294         return CA_ADAPTER_NOT_ENABLED;
1295     }
1296
1297     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1298     if (!jni_cid_BTAdapter)
1299     {
1300         OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1301         return CA_STATUS_FAILED;
1302     }
1303
1304     // get remote bt adapter method
1305     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1306                                                                     "getDefaultAdapter",
1307                                                                     METHODID_OBJECTNONPARAM);
1308     if (!jni_mid_getDefaultAdapter)
1309     {
1310         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1311         return CA_STATUS_FAILED;
1312     }
1313
1314     // get start le scan method
1315     jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1316                                                         "([Ljava/util/UUID;Landroid/bluetooth/"
1317                                                         "BluetoothAdapter$LeScanCallback;)Z");
1318     if (!jni_mid_startLeScan)
1319     {
1320         OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1321         return CA_STATUS_FAILED;
1322     }
1323
1324     // get bt adapter object
1325     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1326                                                                jni_mid_getDefaultAdapter);
1327     if (!jni_obj_BTAdapter)
1328     {
1329         OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1330         return CA_STATUS_FAILED;
1331     }
1332
1333     // call start le scan method
1334     OIC_LOG(INFO, TAG, "CALL API - startLeScan (with UUID)");
1335     jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1336                                                              jni_mid_startLeScan, uuids, callback);
1337     if (!jni_obj_startLeScan)
1338     {
1339         OIC_LOG(INFO, TAG, "startLeScan has failed");
1340     }
1341     else
1342     {
1343         OIC_LOG(DEBUG, TAG, "LeScan has started");
1344         CALEClientSetScanFlag(true);
1345     }
1346
1347     return CA_STATUS_OK;
1348 }
1349
1350 jobject CALEClientGetUUIDObject(JNIEnv *env, const char* uuid)
1351 {
1352     VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
1353     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1354
1355     // setting UUID
1356     jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1357     if (!jni_cid_uuid)
1358     {
1359         OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
1360         return NULL;
1361     }
1362
1363     jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_uuid, "fromString",
1364                                                              "(Ljava/lang/String;)"
1365                                                              "Ljava/util/UUID;");
1366     if (!jni_mid_fromString)
1367     {
1368         OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
1369         return NULL;
1370     }
1371
1372     jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
1373     jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1374                                                           jni_uuid);
1375     if (!jni_obj_uuid)
1376     {
1377         OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1378         return NULL;
1379     }
1380
1381     return jni_obj_uuid;
1382 }
1383
1384 CAResult_t CALEClientStopScan()
1385 {
1386     if (!g_jvm)
1387     {
1388         OIC_LOG(ERROR, TAG, "g_jvm is null");
1389         return CA_STATUS_FAILED;
1390     }
1391
1392     if (!g_isStartedScan)
1393     {
1394         OIC_LOG(INFO, TAG, "scanning is already stopped");
1395         return CA_STATUS_OK;
1396     }
1397
1398     bool isAttached = false;
1399     JNIEnv* env;
1400     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1401     if (JNI_OK != res)
1402     {
1403         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1404         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1405         if (JNI_OK != res)
1406         {
1407             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1408             return CA_STATUS_FAILED;
1409         }
1410         isAttached = true;
1411     }
1412
1413     CAResult_t ret = CALEClientStopScanImpl(env, g_leScanCallback);
1414     if (CA_STATUS_OK != ret)
1415     {
1416         if (CA_ADAPTER_NOT_ENABLED == ret)
1417         {
1418             OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1419         }
1420         else
1421         {
1422             OIC_LOG(ERROR, TAG, "CALEClientStopScanImpl has failed");
1423         }
1424     }
1425     else
1426     {
1427         CALEClientSetScanFlag(false);
1428     }
1429
1430     if (isAttached)
1431     {
1432         (*g_jvm)->DetachCurrentThread(g_jvm);
1433     }
1434
1435     return ret;
1436 }
1437
1438 void CALEClientSetScanFlag(bool flag)
1439 {
1440     ca_mutex_lock(g_scanMutex);
1441     g_isStartedScan = flag;
1442     ca_mutex_unlock(g_scanMutex);
1443 }
1444
1445 CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
1446 {
1447     OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl");
1448     VERIFY_NON_NULL(callback, TAG, "callback is null");
1449     VERIFY_NON_NULL(env, TAG, "env is null");
1450
1451     if (!CALEIsEnableBTAdapter(env))
1452     {
1453         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1454         return CA_ADAPTER_NOT_ENABLED;
1455     }
1456
1457     // get default bt adapter class
1458     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1459     if (!jni_cid_BTAdapter)
1460     {
1461         OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1462         return CA_STATUS_FAILED;
1463     }
1464
1465     // get remote bt adapter method
1466     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1467                                                                     "getDefaultAdapter",
1468                                                                     METHODID_OBJECTNONPARAM);
1469     if (!jni_mid_getDefaultAdapter)
1470     {
1471         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1472         return CA_STATUS_FAILED;
1473     }
1474
1475     // get start le scan method
1476     jmethodID jni_mid_stopLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "stopLeScan",
1477                                                        "(Landroid/bluetooth/"
1478                                                        "BluetoothAdapter$LeScanCallback;)V");
1479     if (!jni_mid_stopLeScan)
1480     {
1481         OIC_LOG(ERROR, TAG, "stopLeScan: jni_mid_stopLeScan is null");
1482         return CA_STATUS_FAILED;
1483     }
1484
1485     // gat bt adapter object
1486     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1487                                                                jni_mid_getDefaultAdapter);
1488     if (!jni_obj_BTAdapter)
1489     {
1490         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1491         return CA_STATUS_FAILED;
1492     }
1493
1494     OIC_LOG(INFO, TAG, "CALL API - stopLeScan");
1495     // call start le scan method
1496     (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_stopLeScan, callback);
1497     if ((*env)->ExceptionCheck(env))
1498     {
1499         OIC_LOG(ERROR, TAG, "stopLeScan has failed");
1500         (*env)->ExceptionDescribe(env);
1501         (*env)->ExceptionClear(env);
1502         return CA_STATUS_FAILED;
1503     }
1504
1505     return CA_STATUS_OK;
1506 }
1507
1508 CAResult_t CALEClientSetFlagToState(JNIEnv *env, jstring jni_address, jint state_idx, jboolean flag)
1509 {
1510     OIC_LOG(DEBUG, TAG, "IN - CALEClientSetFlagToState");
1511     VERIFY_NON_NULL(env, TAG, "env");
1512     VERIFY_NON_NULL(jni_address, TAG, "jni_address");
1513
1514     ca_mutex_lock(g_deviceStateListMutex);
1515
1516     char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1517     if (!address)
1518     {
1519         OIC_LOG(ERROR, TAG, "address is not available");
1520         return CA_STATUS_FAILED;
1521     }
1522
1523     if (CALEClientIsDeviceInList(address))
1524     {
1525         CALEState_t* curState = CALEClientGetStateInfo(address);
1526         if(!curState)
1527         {
1528             OIC_LOG(ERROR, TAG, "curState is null");
1529             (*env)->ReleaseStringUTFChars(env, jni_address, address);
1530             ca_mutex_unlock(g_deviceStateListMutex);
1531             return CA_STATUS_FAILED;
1532         }
1533         OIC_LOG_V(INFO, TAG, "%d flag is set : %d", state_idx, flag);
1534
1535         switch(state_idx)
1536         {
1537             case CA_LE_AUTO_CONNECT_FLAG:
1538                 curState->autoConnectFlag = flag;
1539                 break;
1540             case CA_LE_DESCRIPTOR_FOUND:
1541                 curState->isDescriptorFound = flag;
1542                 break;
1543             default:
1544                 break;
1545         }
1546     }
1547
1548     (*env)->ReleaseStringUTFChars(env, jni_address, address);
1549     ca_mutex_unlock(g_deviceStateListMutex);
1550     OIC_LOG(DEBUG, TAG, "OUT - CALEClientSetFlagToState");
1551     return CA_STATUS_OK;
1552 }
1553
1554 jboolean CALEClientGetFlagFromState(JNIEnv *env, jstring jni_address, jint state_idx)
1555 {
1556     OIC_LOG(DEBUG, TAG, "IN - CALEClientGetFlagFromState");
1557     VERIFY_NON_NULL_RET(env, TAG, "env", false);
1558     VERIFY_NON_NULL_RET(jni_address, TAG, "jni_address", false);
1559
1560     ca_mutex_lock(g_deviceStateListMutex);
1561
1562     char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1563     if (!address)
1564     {
1565         OIC_LOG(ERROR, TAG, "address is not available");
1566         ca_mutex_unlock(g_deviceStateListMutex);
1567         return JNI_FALSE;
1568     }
1569
1570     CALEState_t* curState = CALEClientGetStateInfo(address);
1571     (*env)->ReleaseStringUTFChars(env, jni_address, address);
1572     if(!curState)
1573     {
1574         OIC_LOG(INFO, TAG, "there is no information. auto connect flag is false");
1575         ca_mutex_unlock(g_deviceStateListMutex);
1576         return JNI_FALSE;
1577     }
1578
1579     jboolean ret = JNI_FALSE;
1580     switch(state_idx)
1581     {
1582         case CA_LE_AUTO_CONNECT_FLAG:
1583             ret = curState->autoConnectFlag;
1584             break;
1585         case CA_LE_DESCRIPTOR_FOUND:
1586             ret = curState->isDescriptorFound;
1587             break;
1588         default:
1589             break;
1590     }
1591     ca_mutex_unlock(g_deviceStateListMutex);
1592
1593     OIC_LOG_V(INFO, TAG, "%d flag is %d", state_idx, ret);
1594     OIC_LOG(DEBUG, TAG, "OUT - CALEClientGetFlagFromState");
1595     return ret;
1596 }
1597
1598 jobject CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1599 {
1600     OIC_LOG(DEBUG, TAG, "CALEClientConnect");
1601     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1602     VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1603
1604     // get gatt object from Bluetooth Device object for closeProfileProxy(..)
1605     jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, bluetoothDevice);
1606     if (jni_address)
1607     {
1608         const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1609         if (!address)
1610         {
1611             OIC_LOG(ERROR, TAG, "address is not available");
1612             return NULL;
1613         }
1614
1615         // close the gatt service
1616         jobject gatt = CALEClientGetGattObjInList(env, address);
1617         if (gatt)
1618         {
1619             CAResult_t res = CALEClientCloseProfileProxy(env, gatt);
1620             if (CA_STATUS_OK != res)
1621             {
1622                 OIC_LOG(ERROR, TAG, "CALEClientCloseProfileProxy has failed");
1623                 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1624                 return NULL;
1625             }
1626
1627             // clean previous gatt object after close profile service
1628             res = CALEClientRemoveGattObjForAddr(env, jni_address);
1629             if (CA_STATUS_OK != res)
1630             {
1631                 OIC_LOG(ERROR, TAG, "CALEClientRemoveGattObjForAddr has failed");
1632                 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1633                 return NULL;
1634             }
1635         }
1636         (*env)->ReleaseStringUTFChars(env, jni_address, address);
1637     }
1638
1639     jobject newGatt = CALEClientGattConnect(env, bluetoothDevice, autoconnect);
1640     if (!newGatt)
1641     {
1642         OIC_LOG(DEBUG, TAG, "re-connection will be started");
1643         return NULL;
1644     }
1645
1646     // add new gatt object into g_gattObjectList
1647     CAResult_t res = CALEClientAddGattobjToList(env, newGatt);
1648     if (CA_STATUS_OK != res)
1649     {
1650         OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
1651         return NULL;
1652     }
1653
1654     return newGatt;
1655 }
1656
1657 jobject CALEClientGattConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1658 {
1659     OIC_LOG(DEBUG, TAG, "GATT CONNECT");
1660     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1661     VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1662
1663     if (!g_leGattCallback)
1664     {
1665         OIC_LOG(INFO, TAG, "g_leGattCallback is null");
1666         return NULL;
1667     }
1668
1669     if (!CALEIsEnableBTAdapter(env))
1670     {
1671         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1672         return NULL;
1673     }
1674
1675     jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
1676     if (!jni_address)
1677     {
1678         OIC_LOG(ERROR, TAG, "bleConnect: CALEGetAddressFromBTDevice is null");
1679         return NULL;
1680     }
1681
1682     // get BluetoothDevice method
1683     OIC_LOG(DEBUG, TAG, "get BluetoothDevice method");
1684     jmethodID jni_mid_connectGatt = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice",
1685                                                      "connectGatt",
1686                                                      "(Landroid/content/Context;ZLandroid/"
1687                                                      "bluetooth/BluetoothGattCallback;)"
1688                                                      "Landroid/bluetooth/BluetoothGatt;");
1689     if (!jni_mid_connectGatt)
1690     {
1691         OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null");
1692         return NULL;
1693     }
1694
1695     OIC_LOG(INFO, TAG, "CALL API - connectGatt");
1696     jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice,
1697                                                            jni_mid_connectGatt,
1698                                                            NULL,
1699                                                            autoconnect, g_leGattCallback);
1700     if (!jni_obj_connectGatt)
1701     {
1702         OIC_LOG(ERROR, TAG, "connectGatt was failed..it will be removed");
1703         CALEClientRemoveDeviceInScanDeviceList(env, jni_address);
1704         CALEClientUpdateSendCnt(env);
1705         return NULL;
1706     }
1707     else
1708     {
1709         OIC_LOG(DEBUG, TAG, "le connecting..please wait..");
1710     }
1711     return jni_obj_connectGatt;
1712 }
1713
1714 CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt)
1715 {
1716     OIC_LOG(DEBUG, TAG, "IN - CALEClientCloseProfileProxy");
1717
1718     VERIFY_NON_NULL(env, TAG, "env is null");
1719     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
1720
1721     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1722     if (!jni_cid_BTAdapter)
1723     {
1724         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
1725         return CA_STATUS_FAILED;
1726     }
1727
1728     // get remote bt adapter method
1729     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1730                                                                     "getDefaultAdapter",
1731                                                                     METHODID_OBJECTNONPARAM);
1732     if (!jni_mid_getDefaultAdapter)
1733     {
1734         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1735         return CA_STATUS_FAILED;
1736     }
1737
1738     // gat bt adapter object
1739     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1740                                                                jni_mid_getDefaultAdapter);
1741     if (!jni_obj_BTAdapter)
1742     {
1743         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1744         return CA_STATUS_FAILED;
1745     }
1746
1747     // get closeProfileProxy method
1748     jmethodID jni_mid_closeProfileProxy = (*env)->GetMethodID(env, jni_cid_BTAdapter,
1749                                                               "closeProfileProxy",
1750                                                               "(ILandroid/bluetooth/"
1751                                                               "BluetoothProfile;)V");
1752     if (!jni_mid_closeProfileProxy)
1753     {
1754         OIC_LOG(ERROR, TAG, "jni_mid_closeProfileProxy is null");
1755         return CA_STATUS_FAILED;
1756     }
1757
1758     jclass jni_cid_BTProfile = (*env)->FindClass(env, CLASSPATH_BT_PROFILE);
1759     if (!jni_cid_BTProfile)
1760     {
1761         OIC_LOG(ERROR, TAG, "jni_cid_BTProfile is null");
1762         return CA_STATUS_FAILED;
1763     }
1764
1765     // GATT - Constant value : 7 (0x00000007)
1766     jfieldID id_gatt = (*env)->GetStaticFieldID(env, jni_cid_BTProfile,
1767                                                 "GATT", "I");
1768     if (!id_gatt)
1769     {
1770         OIC_LOG(ERROR, TAG, "id_gatt is null");
1771         return CA_STATUS_FAILED;
1772     }
1773
1774     jint jni_gatt = (*env)->GetStaticIntField(env, jni_cid_BTProfile, id_gatt);
1775
1776     OIC_LOG(DEBUG, TAG, "CALL API - close the connection of the profile proxy to the Service");
1777     (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_closeProfileProxy, jni_gatt, gatt);
1778     if ((*env)->ExceptionCheck(env))
1779     {
1780         OIC_LOG(ERROR, TAG, "closeProfileProxy has failed");
1781         (*env)->ExceptionDescribe(env);
1782         (*env)->ExceptionClear(env);
1783         return CA_STATUS_FAILED;
1784     }
1785
1786     OIC_LOG(DEBUG, TAG, "OUT - CALEClientCloseProfileProxy");
1787     return CA_STATUS_OK;
1788 }
1789
1790
1791 CAResult_t CALEClientDisconnect(JNIEnv *env, jobject bluetoothGatt)
1792 {
1793     OIC_LOG(DEBUG, TAG, "GATT DISCONNECT");
1794     VERIFY_NON_NULL(env, TAG, "env is null");
1795     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1796
1797     // get BluetoothGatt method
1798     OIC_LOG(DEBUG, TAG, "get gatt disconnect method");
1799     jmethodID jni_mid_disconnectGatt  = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
1800                                                          "disconnect", "()V");
1801     if (!jni_mid_disconnectGatt)
1802     {
1803         OIC_LOG(ERROR, TAG, "jni_mid_disconnectGatt is null");
1804         return CA_STATUS_FAILED;
1805     }
1806
1807     // call disconnect gatt method
1808     OIC_LOG(INFO, TAG, "CALL API - disconnect");
1809     (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_disconnectGatt);
1810     if ((*env)->ExceptionCheck(env))
1811     {
1812         OIC_LOG(ERROR, TAG, "disconnect has failed");
1813         (*env)->ExceptionDescribe(env);
1814         (*env)->ExceptionClear(env);
1815         return CA_STATUS_FAILED;
1816     }
1817
1818     OIC_LOG(DEBUG, TAG, "disconnecting Gatt...");
1819
1820     return CA_STATUS_OK;
1821 }
1822
1823 CAResult_t CALEClientDisconnectAll(JNIEnv *env)
1824 {
1825     OIC_LOG(DEBUG, TAG, "CALEClientDisconnectAll");
1826     VERIFY_NON_NULL(env, TAG, "env is null");
1827
1828     if (!g_gattObjectList)
1829     {
1830         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
1831         return CA_STATUS_OK;
1832     }
1833
1834     uint32_t length = u_arraylist_length(g_gattObjectList);
1835     OIC_LOG_V(DEBUG, TAG, "list length : %d", length);
1836     for (uint32_t index = 0; index < length; index++)
1837     {
1838         OIC_LOG(DEBUG, TAG, "start CALEClientDisconnectAll");
1839         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1840         if (!jarrayObj)
1841         {
1842             OIC_LOG(ERROR, TAG, "jarrayObj is null");
1843             continue;
1844         }
1845         CAResult_t res = CALEClientDisconnect(env, jarrayObj);
1846         if (CA_STATUS_OK != res)
1847         {
1848             OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
1849             continue;
1850         }
1851     }
1852
1853     return CA_STATUS_OK;
1854 }
1855
1856 CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address)
1857 {
1858     OIC_LOG(DEBUG, TAG, "IN-CALEClientDisconnectforAddress");
1859     VERIFY_NON_NULL(env, TAG, "env is null");
1860
1861     if (!g_gattObjectList)
1862     {
1863         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
1864         return CA_STATUS_OK;
1865     }
1866
1867     char* address = (char*)(*env)->GetStringUTFChars(env, remote_address, NULL);
1868     if (!address)
1869     {
1870         OIC_LOG(ERROR, TAG, "address is null");
1871         return CA_STATUS_FAILED;
1872     }
1873
1874     uint32_t length = u_arraylist_length(g_gattObjectList);
1875     for (uint32_t index = 0; index < length; index++)
1876     {
1877         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1878         if (!jarrayObj)
1879         {
1880             OIC_LOG(ERROR, TAG, "jarrayObj is null");
1881             continue;
1882         }
1883
1884         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
1885         if (!jni_setAddress)
1886         {
1887             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
1888             (*env)->ReleaseStringUTFChars(env, remote_address, address);
1889             return CA_STATUS_FAILED;
1890         }
1891
1892         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
1893         if (!setAddress)
1894         {
1895             OIC_LOG(ERROR, TAG, "setAddress is null");
1896             (*env)->ReleaseStringUTFChars(env, remote_address, address);
1897             return CA_STATUS_FAILED;
1898         }
1899
1900         OIC_LOG_V(DEBUG, TAG, "target address : %s, set address : %s", address, setAddress);
1901         if (!strcmp(address, setAddress))
1902         {
1903             CAResult_t res = CALEClientDisconnect(env, jarrayObj);
1904             if (CA_STATUS_OK != res)
1905             {
1906                 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
1907                 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1908                 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1909                 return CA_STATUS_FAILED;
1910             }
1911             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1912             (*env)->ReleaseStringUTFChars(env, remote_address, address);
1913             return CA_STATUS_OK;
1914         }
1915         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1916     }
1917     (*env)->ReleaseStringUTFChars(env, remote_address, address);
1918
1919     OIC_LOG(DEBUG, TAG, "OUT-CALEClientDisconnectforAddress");
1920     return CA_STATUS_OK;
1921 }
1922
1923 CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt)
1924 {
1925     VERIFY_NON_NULL(env, TAG, "env is null");
1926     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1927
1928     if (!CALEIsEnableBTAdapter(env))
1929     {
1930         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1931         return CA_ADAPTER_NOT_ENABLED;
1932     }
1933
1934     // get BluetoothGatt.discoverServices method
1935     OIC_LOG(DEBUG, TAG, "get BluetoothGatt.discoverServices method");
1936     jmethodID jni_mid_discoverServices = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
1937                                                           "discoverServices", "()Z");
1938     if (!jni_mid_discoverServices)
1939     {
1940         OIC_LOG(ERROR, TAG, "jni_mid_discoverServices is null");
1941         return CA_STATUS_FAILED;
1942     }
1943
1944     // call disconnect gatt method
1945     OIC_LOG(INFO, TAG, "CALL API - discoverServices");
1946     jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_discoverServices);
1947     if (!ret)
1948     {
1949         OIC_LOG(ERROR, TAG, "discoverServices has not been started");
1950         return CA_STATUS_FAILED;
1951     }
1952
1953     return CA_STATUS_OK;
1954 }
1955
1956 static void CALEWriteCharacteristicThread(void* object)
1957 {
1958     VERIFY_NON_NULL_VOID(object, TAG, "object is null");
1959
1960     bool isAttached = false;
1961     JNIEnv* env;
1962     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1963     if (JNI_OK != res)
1964     {
1965         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1966         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1967
1968         if (JNI_OK != res)
1969         {
1970             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1971             return;
1972         }
1973         isAttached = true;
1974     }
1975
1976     jobject gatt = (jobject)object;
1977     CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
1978     if (CA_STATUS_OK != ret)
1979     {
1980         OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
1981     }
1982
1983     if (isAttached)
1984     {
1985         (*g_jvm)->DetachCurrentThread(g_jvm);
1986     }
1987 }
1988
1989 CAResult_t CALESetValueAndWriteCharacteristic(JNIEnv* env, jobject gatt)
1990 {
1991     OIC_LOG(DEBUG, TAG, "CALESetValueAndWriteCharacteristic");
1992
1993     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
1994     VERIFY_NON_NULL(env, TAG, "env is null");
1995
1996     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
1997     if (!jni_address)
1998     {
1999         CALEClientSendFinish(env, gatt);
2000         return CA_STATUS_FAILED;
2001     }
2002
2003     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
2004     if (!address)
2005     {
2006         CALEClientSendFinish(env, gatt);
2007         return CA_STATUS_FAILED;
2008     }
2009
2010     ca_mutex_lock(g_threadSendStateMutex);
2011
2012     if (CALEClientIsValidState(address, CA_LE_SEND_STATE, STATE_SENDING))
2013     {
2014         OIC_LOG(INFO, TAG, "current state is SENDING");
2015         (*env)->ReleaseStringUTFChars(env, jni_address, address);
2016         ca_mutex_unlock(g_threadSendStateMutex);
2017         return CA_STATUS_OK;
2018     }
2019
2020     if (CA_STATUS_OK != CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
2021                                                     STATE_SENDING))
2022     {
2023         OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
2024         (*env)->ReleaseStringUTFChars(env, jni_address, address);
2025         CALEClientSendFinish(env, gatt);
2026         ca_mutex_unlock(g_threadSendStateMutex);
2027         return CA_STATUS_FAILED;
2028     }
2029
2030     (*env)->ReleaseStringUTFChars(env, jni_address, address);
2031
2032     ca_mutex_unlock(g_threadSendStateMutex);
2033
2034     // send data
2035     jobject jni_obj_character = CALEClientCreateGattCharacteristic(env, gatt, g_sendBuffer);
2036     if (!jni_obj_character)
2037     {
2038         CALEClientSendFinish(env, gatt);
2039         return CA_STATUS_FAILED;
2040     }
2041
2042     CAResult_t ret = CALEClientWriteCharacteristicImpl(env, gatt, jni_obj_character);
2043     if (CA_STATUS_OK != ret)
2044     {
2045         CALEClientSendFinish(env, gatt);
2046         return CA_STATUS_FAILED;
2047     }
2048
2049     // wait for callback for write Characteristic with success to sent data
2050     OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
2051     ca_mutex_lock(g_threadWriteCharacteristicMutex);
2052     if (!g_isSignalSetFlag)
2053     {
2054         OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
2055         if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond,
2056                                   g_threadWriteCharacteristicMutex,
2057                                   WAIT_TIME_WRITE_CHARACTERISTIC))
2058         {
2059             OIC_LOG(ERROR, TAG, "there is no response. write has failed");
2060             g_isSignalSetFlag = false;
2061             ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2062             return CA_STATUS_FAILED;
2063         }
2064     }
2065     // reset flag set by writeCharacteristic Callback
2066     g_isSignalSetFlag = false;
2067     ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2068
2069     OIC_LOG(INFO, TAG, "writeCharacteristic success!!");
2070     return CA_STATUS_OK;
2071 }
2072
2073 CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt)
2074 {
2075     OIC_LOG(DEBUG, TAG, "IN - CALEClientWriteCharacteristic");
2076     VERIFY_NON_NULL(env, TAG, "env is null");
2077     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2078
2079     jobject gattParam = (*env)->NewGlobalRef(env, gatt);
2080     if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle,
2081                                                 CALEWriteCharacteristicThread, (void*)gattParam))
2082     {
2083         OIC_LOG(ERROR, TAG, "Failed to create read thread!");
2084         return CA_STATUS_FAILED;
2085     }
2086
2087     OIC_LOG(DEBUG, TAG, "OUT - CALEClientWriteCharacteristic");
2088     return CA_STATUS_OK;
2089 }
2090
2091 CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt,
2092                                              jobject gattCharacteristic)
2093 {
2094     OIC_LOG(DEBUG, TAG, "WRITE GATT CHARACTERISTIC");
2095     VERIFY_NON_NULL(env, TAG, "env is null");
2096     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2097     VERIFY_NON_NULL(gattCharacteristic, TAG, "gattCharacteristic is null");
2098
2099     if (!CALEIsEnableBTAdapter(env))
2100     {
2101         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2102         return CA_STATUS_FAILED;
2103     }
2104
2105     // get BluetoothGatt.write characteristic method
2106     OIC_LOG(DEBUG, TAG, "write characteristic method");
2107     jmethodID jni_mid_writeCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2108                                                              "writeCharacteristic",
2109                                                              "(Landroid/bluetooth/"
2110                                                              "BluetoothGattCharacteristic;)Z");
2111     if (!jni_mid_writeCharacteristic)
2112     {
2113         OIC_LOG(ERROR, TAG, "jni_mid_writeCharacteristic is null");
2114         return CA_STATUS_FAILED;
2115     }
2116
2117     // call disconnect gatt method
2118     OIC_LOG(INFO, TAG, "CALL API - writeCharacteristic");
2119     jboolean ret = (jboolean)(*env)->CallBooleanMethod(env, bluetoothGatt,
2120                                                        jni_mid_writeCharacteristic,
2121                                                        gattCharacteristic);
2122     if (ret)
2123     {
2124         OIC_LOG(DEBUG, TAG, "writeCharacteristic is called successfully");
2125     }
2126     else
2127     {
2128         OIC_LOG(ERROR, TAG, "writeCharacteristic has failed");
2129         return CA_STATUS_FAILED;
2130     }
2131
2132     return CA_STATUS_OK;
2133 }
2134
2135 CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt)
2136 {
2137     VERIFY_NON_NULL(env, TAG, "env is null");
2138     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2139
2140     if (!CALEIsEnableBTAdapter(env))
2141     {
2142         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2143         return CA_STATUS_FAILED;
2144     }
2145
2146     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
2147     if (!jni_uuid)
2148     {
2149         OIC_LOG(ERROR, TAG, "jni_uuid is null");
2150         return CA_STATUS_FAILED;
2151     }
2152
2153     jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2154     if (!jni_obj_GattCharacteristic)
2155     {
2156         OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2157         return CA_STATUS_FAILED;
2158     }
2159
2160     OIC_LOG(DEBUG, TAG, "read characteristic method");
2161     jmethodID jni_mid_readCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2162                                                             "readCharacteristic",
2163                                                             "(Landroid/bluetooth/"
2164                                                             "BluetoothGattCharacteristic;)Z");
2165     if (!jni_mid_readCharacteristic)
2166     {
2167         OIC_LOG(ERROR, TAG, "jni_mid_readCharacteristic is null");
2168         return CA_STATUS_FAILED;
2169     }
2170
2171     // call disconnect gatt method
2172     OIC_LOG(INFO, TAG, "CALL API - readCharacteristic");
2173     jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_readCharacteristic,
2174                                              jni_obj_GattCharacteristic);
2175     if (ret)
2176     {
2177         OIC_LOG(DEBUG, TAG, "readCharacteristic success");
2178     }
2179     else
2180     {
2181         OIC_LOG(ERROR, TAG, "readCharacteristic has failed");
2182         return CA_STATUS_FAILED;
2183     }
2184
2185     return CA_STATUS_OK;
2186 }
2187
2188 CAResult_t CALEClientSetCharacteristicNotification(JNIEnv *env, jobject bluetoothGatt,
2189                                                    jobject characteristic)
2190 {
2191     VERIFY_NON_NULL(env, TAG, "env is null");
2192     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2193     VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2194
2195     if (!CALEIsEnableBTAdapter(env))
2196     {
2197         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2198         return CA_ADAPTER_NOT_ENABLED;
2199     }
2200
2201     // get BluetoothGatt.setCharacteristicNotification method
2202     OIC_LOG(DEBUG, TAG, "CALEClientSetCharacteristicNotification");
2203     jmethodID jni_mid_setNotification = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2204                                                          "setCharacteristicNotification",
2205                                                          "(Landroid/bluetooth/"
2206                                                          "BluetoothGattCharacteristic;Z)Z");
2207     if (!jni_mid_setNotification)
2208     {
2209         OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2210         return CA_STATUS_FAILED;
2211     }
2212
2213     OIC_LOG(INFO, TAG, "CALL API - setCharacteristicNotification");
2214     jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_setNotification,
2215                                              characteristic, JNI_TRUE);
2216     if (JNI_TRUE == ret)
2217     {
2218         OIC_LOG(DEBUG, TAG, "setCharacteristicNotification success");
2219     }
2220     else
2221     {
2222         OIC_LOG(ERROR, TAG, "setCharacteristicNotification has failed");
2223         return CA_STATUS_FAILED;
2224     }
2225
2226     return CA_STATUS_OK;
2227 }
2228
2229 jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID)
2230 {
2231     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2232     VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2233     VERIFY_NON_NULL_RET(characterUUID, TAG, "characterUUID is null", NULL);
2234
2235     if (!CALEIsEnableBTAdapter(env))
2236     {
2237         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2238         return NULL;
2239     }
2240
2241     // get BluetoothGatt.getService method
2242     OIC_LOG(DEBUG, TAG, "BluetoothGatt.getService");
2243     jmethodID jni_mid_getService = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2244                                                     "getService",
2245                                                     "(Ljava/util/UUID;)Landroid/bluetooth/"
2246                                                     "BluetoothGattService;");
2247     if (!jni_mid_getService)
2248     {
2249         OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2250         return NULL;
2251     }
2252
2253     jobject jni_obj_service_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2254     if (!jni_obj_service_uuid)
2255     {
2256         OIC_LOG(ERROR, TAG, "jni_obj_service_uuid is null");
2257         return NULL;
2258     }
2259
2260     // get bluetooth gatt service
2261     OIC_LOG(DEBUG, TAG, "request to get service");
2262     jobject jni_obj_gattService = (*env)->CallObjectMethod(env, bluetoothGatt, jni_mid_getService,
2263                                                            jni_obj_service_uuid);
2264     if (!jni_obj_gattService)
2265     {
2266         OIC_LOG(ERROR, TAG, "jni_obj_gattService is null");
2267         return NULL;
2268     }
2269
2270     // get bluetooth gatt service method
2271     jmethodID jni_mid_getCharacteristic = CAGetJNIMethodID(env, "android/bluetooth/"
2272                                                            "BluetoothGattService",
2273                                                            "getCharacteristic",
2274                                                            "(Ljava/util/UUID;)"
2275                                                            "Landroid/bluetooth/"
2276                                                            "BluetoothGattCharacteristic;");
2277     if (!jni_mid_getCharacteristic)
2278     {
2279         OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null");
2280         return NULL;
2281     }
2282
2283     const char* uuid = (*env)->GetStringUTFChars(env, characterUUID, NULL);
2284     if (!uuid)
2285     {
2286         OIC_LOG(ERROR, TAG, "uuid is null");
2287         return NULL;
2288     }
2289
2290     jobject jni_obj_tx_uuid = CALEClientGetUUIDObject(env, uuid);
2291     if (!jni_obj_tx_uuid)
2292     {
2293         OIC_LOG(ERROR, TAG, "jni_obj_tx_uuid is null");
2294         (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2295         return NULL;
2296     }
2297
2298     OIC_LOG(DEBUG, TAG, "request to get Characteristic");
2299     jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService,
2300                                                                   jni_mid_getCharacteristic,
2301                                                                   jni_obj_tx_uuid);
2302
2303     (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2304     return jni_obj_GattCharacteristic;
2305 }
2306
2307 jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data)
2308 {
2309     OIC_LOG(DEBUG, TAG, "CALEClientCreateGattCharacteristic");
2310     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2311     VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2312     VERIFY_NON_NULL_RET(data, TAG, "data is null", NULL);
2313
2314     if (!CALEIsEnableBTAdapter(env))
2315     {
2316         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2317         return NULL;
2318     }
2319
2320     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
2321     if (!jni_uuid)
2322     {
2323         OIC_LOG(ERROR, TAG, "jni_uuid is null");
2324         return NULL;
2325     }
2326
2327     jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2328     if (!jni_obj_GattCharacteristic)
2329     {
2330         OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2331         return NULL;
2332     }
2333
2334     jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth"
2335                                                             "/BluetoothGattCharacteristic");
2336     if (!jni_cid_BTGattCharacteristic)
2337     {
2338         OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
2339         return NULL;
2340     }
2341
2342     OIC_LOG(DEBUG, TAG, "set value in Characteristic");
2343     jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "setValue",
2344                                                      "([B)Z");
2345     if (!jni_mid_setValue)
2346     {
2347         OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2348         return NULL;
2349     }
2350
2351     jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue,
2352                                              data);
2353     if (JNI_TRUE == ret)
2354     {
2355         OIC_LOG(DEBUG, TAG, "the locally stored value has been set");
2356     }
2357     else
2358     {
2359         OIC_LOG(ERROR, TAG, "the locally stored value hasn't been set");
2360         return NULL;
2361     }
2362
2363     // set Write Type
2364     jmethodID jni_mid_setWriteType = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic,
2365                                                          "setWriteType", "(I)V");
2366     if (!jni_mid_setWriteType)
2367     {
2368         OIC_LOG(ERROR, TAG, "jni_mid_setWriteType is null");
2369         return NULL;
2370     }
2371
2372     jfieldID jni_fid_no_response = (*env)->GetStaticFieldID(env, jni_cid_BTGattCharacteristic,
2373                                                             "WRITE_TYPE_NO_RESPONSE", "I");
2374     if (!jni_fid_no_response)
2375     {
2376         OIC_LOG(ERROR, TAG, "jni_fid_no_response is not available");
2377         return NULL;
2378     }
2379
2380     jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTGattCharacteristic,
2381                                                  jni_fid_no_response);
2382
2383     (*env)->CallVoidMethod(env, jni_obj_GattCharacteristic, jni_mid_setWriteType, jni_int_val);
2384
2385     return jni_obj_GattCharacteristic;
2386 }
2387
2388 jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteristic)
2389 {
2390     VERIFY_NON_NULL_RET(characteristic, TAG, "characteristic is null", NULL);
2391     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2392
2393     if (!CALEIsEnableBTAdapter(env))
2394     {
2395         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2396         return NULL;
2397     }
2398
2399     jmethodID jni_mid_getValue  = CAGetJNIMethodID(env, "android/bluetooth/"
2400                                                    "BluetoothGattCharacteristic",
2401                                                    "getValue", "()[B");
2402     if (!jni_mid_getValue)
2403     {
2404         OIC_LOG(ERROR, TAG, "jni_mid_getValue is null");
2405         return NULL;
2406     }
2407
2408     jbyteArray jni_obj_data_array = (*env)->CallObjectMethod(env, characteristic,
2409                                                              jni_mid_getValue);
2410     return jni_obj_data_array;
2411 }
2412
2413 CAResult_t CALEClientCreateUUIDList()
2414 {
2415     if (!g_jvm)
2416     {
2417         OIC_LOG(ERROR, TAG, "g_jvm is null");
2418         return CA_STATUS_FAILED;
2419     }
2420
2421     bool isAttached = false;
2422     JNIEnv* env;
2423     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
2424     if (JNI_OK != res)
2425     {
2426         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
2427         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
2428
2429         if (JNI_OK != res)
2430         {
2431             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
2432             return CA_STATUS_FAILED;
2433         }
2434         isAttached = true;
2435     }
2436
2437     // create new object array
2438     jclass jni_cid_uuid_list = (*env)->FindClass(env, CLASSPATH_BT_UUID);
2439     if (!jni_cid_uuid_list)
2440     {
2441         OIC_LOG(ERROR, TAG, "jni_cid_uuid_list is null");
2442         goto error_exit;
2443     }
2444
2445     jobjectArray jni_obj_uuid_list = (jobjectArray)(*env)->NewObjectArray(env, 1,
2446                                                                           jni_cid_uuid_list, NULL);
2447     if (!jni_obj_uuid_list)
2448     {
2449         OIC_LOG(ERROR, TAG, "jni_obj_uuid_list is null");
2450         goto error_exit;
2451     }
2452
2453     // make uuid list
2454     jobject jni_obj_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2455     if (!jni_obj_uuid)
2456     {
2457         OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
2458         goto error_exit;
2459     }
2460     (*env)->SetObjectArrayElement(env, jni_obj_uuid_list, 0, jni_obj_uuid);
2461
2462     g_uuidList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list);
2463
2464     if (isAttached)
2465     {
2466         (*g_jvm)->DetachCurrentThread(g_jvm);
2467     }
2468
2469     return CA_STATUS_OK;
2470
2471     // error label.
2472 error_exit:
2473
2474     if (isAttached)
2475     {
2476         (*g_jvm)->DetachCurrentThread(g_jvm);
2477     }
2478     return CA_STATUS_FAILED;
2479 }
2480
2481 CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt,
2482                                          jobject characteristic)
2483 {
2484     VERIFY_NON_NULL(env, TAG, "env is null");
2485     VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2486     VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2487
2488     if (!CALEIsEnableBTAdapter(env))
2489     {
2490         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2491         return CA_ADAPTER_NOT_ENABLED;
2492     }
2493
2494     OIC_LOG(DEBUG, TAG, "CALEClientSetUUIDToDescriptor");
2495     jmethodID jni_mid_getDescriptor  = CAGetJNIMethodID(env, "android/bluetooth/"
2496                                                         "BluetoothGattCharacteristic",
2497                                                         "getDescriptor",
2498                                                         "(Ljava/util/UUID;)Landroid/bluetooth/"
2499                                                         "BluetoothGattDescriptor;");
2500     if (!jni_mid_getDescriptor)
2501     {
2502         OIC_LOG(ERROR, TAG, "jni_mid_getDescriptor is null");
2503         return CA_STATUS_FAILED;
2504     }
2505
2506     jobject jni_obj_cc_uuid = CALEClientGetUUIDObject(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID);
2507     if (!jni_obj_cc_uuid)
2508     {
2509         OIC_LOG(ERROR, TAG, "jni_obj_cc_uuid is null");
2510         return CA_STATUS_FAILED;
2511     }
2512
2513     OIC_LOG(DEBUG, TAG, "request to get descriptor");
2514     jobject jni_obj_descriptor = (*env)->CallObjectMethod(env, characteristic,
2515                                                           jni_mid_getDescriptor, jni_obj_cc_uuid);
2516     if (!jni_obj_descriptor)
2517     {
2518         OIC_LOG(INFO, TAG, "jni_obj_descriptor is null");
2519         return CA_NOT_SUPPORTED;
2520     }
2521
2522     OIC_LOG(DEBUG, TAG, "set value in descriptor");
2523     jclass jni_cid_descriptor = (*env)->FindClass(env,
2524                                                   "android/bluetooth/BluetoothGattDescriptor");
2525     if (!jni_cid_descriptor)
2526     {
2527         OIC_LOG(ERROR, TAG, "jni_cid_descriptor is null");
2528         return CA_STATUS_FAILED;
2529     }
2530
2531     jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_descriptor, "setValue", "([B)Z");
2532     if (!jni_mid_setValue)
2533     {
2534         OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2535         return CA_STATUS_FAILED;
2536     }
2537
2538     jfieldID jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor,
2539                                                           "ENABLE_NOTIFICATION_VALUE", "[B");
2540     if (!jni_fid_NotiValue)
2541     {
2542         OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null");
2543         return CA_STATUS_FAILED;
2544     }
2545
2546     OIC_LOG(DEBUG, TAG, "get ENABLE_NOTIFICATION_VALUE");
2547
2548     jboolean jni_setvalue = (*env)->CallBooleanMethod(
2549             env, jni_obj_descriptor, jni_mid_setValue,
2550             (jbyteArray)(*env)->GetStaticObjectField(env, jni_cid_descriptor, jni_fid_NotiValue));
2551     if (jni_setvalue)
2552     {
2553         OIC_LOG(DEBUG, TAG, "setValue success");
2554     }
2555     else
2556     {
2557         OIC_LOG(ERROR, TAG, "setValue has failed");
2558         return CA_STATUS_FAILED;
2559     }
2560
2561     jmethodID jni_mid_writeDescriptor  = CAGetJNIMethodID(env, "android/bluetooth/BluetoothGatt",
2562                                                           "writeDescriptor",
2563                                                           "(Landroid/bluetooth/"
2564                                                           "BluetoothGattDescriptor;)Z");
2565     if (!jni_mid_writeDescriptor)
2566     {
2567         OIC_LOG(ERROR, TAG, "jni_mid_writeDescriptor is null");
2568         return CA_STATUS_FAILED;
2569     }
2570
2571     OIC_LOG(INFO, TAG, "CALL API - writeDescriptor");
2572     jboolean jni_ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_writeDescriptor,
2573                                                  jni_obj_descriptor);
2574     if (jni_ret)
2575     {
2576         OIC_LOG(DEBUG, TAG, "writeDescriptor success");
2577     }
2578     else
2579     {
2580         OIC_LOG(ERROR, TAG, "writeDescriptor has failed");
2581         return CA_STATUS_FAILED;
2582     }
2583
2584     return CA_STATUS_OK;
2585 }
2586
2587 void CALEClientCreateScanDeviceList(JNIEnv *env)
2588 {
2589     OIC_LOG(DEBUG, TAG, "CALEClientCreateScanDeviceList");
2590     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
2591
2592     ca_mutex_lock(g_deviceListMutex);
2593     // create new object array
2594     if (g_deviceList == NULL)
2595     {
2596         OIC_LOG(DEBUG, TAG, "Create device list");
2597
2598         g_deviceList = u_arraylist_create();
2599     }
2600     ca_mutex_unlock(g_deviceListMutex);
2601 }
2602
2603 CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device)
2604 {
2605     VERIFY_NON_NULL(device, TAG, "device is null");
2606     VERIFY_NON_NULL(env, TAG, "env is null");
2607
2608     ca_mutex_lock(g_deviceListMutex);
2609
2610     if (!g_deviceList)
2611     {
2612         OIC_LOG(ERROR, TAG, "gdevice_list is null");
2613
2614         CALEClientSetScanFlag(false);
2615         if (CA_STATUS_OK != CALEClientStopScan())
2616         {
2617             OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
2618         }
2619
2620         ca_mutex_unlock(g_deviceListMutex);
2621         return CA_STATUS_FAILED;
2622     }
2623
2624     jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2625     if (!jni_remoteAddress)
2626     {
2627         OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2628         ca_mutex_unlock(g_deviceListMutex);
2629         return CA_STATUS_FAILED;
2630     }
2631
2632     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2633     if (!remoteAddress)
2634     {
2635         OIC_LOG(ERROR, TAG, "remoteAddress is null");
2636         ca_mutex_unlock(g_deviceListMutex);
2637         return CA_STATUS_FAILED;
2638     }
2639
2640     if (!CALEClientIsDeviceInScanDeviceList(env, remoteAddress))
2641     {
2642         jobject gdevice = (*env)->NewGlobalRef(env, device);
2643         u_arraylist_add(g_deviceList, gdevice);
2644         ca_cond_signal(g_deviceDescCond);
2645         OIC_LOG_V(DEBUG, TAG, "Added a new BT Device in deviceList [%s]", remoteAddress);
2646     }
2647     (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2648
2649     ca_mutex_unlock(g_deviceListMutex);
2650
2651     return CA_STATUS_OK;
2652 }
2653
2654 bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress)
2655 {
2656     VERIFY_NON_NULL_RET(env, TAG, "env is null", true);
2657     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2658
2659     if (!g_deviceList)
2660     {
2661         OIC_LOG(DEBUG, TAG, "g_deviceList is null");
2662         return true;
2663     }
2664
2665     uint32_t length = u_arraylist_length(g_deviceList);
2666     for (uint32_t index = 0; index < length; index++)
2667     {
2668         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2669         if (!jarrayObj)
2670         {
2671             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2672             return true;
2673         }
2674
2675         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2676         if (!jni_setAddress)
2677         {
2678             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2679             return true;
2680         }
2681
2682         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2683         if (!setAddress)
2684         {
2685             OIC_LOG(ERROR, TAG, "setAddress is null");
2686             return true;
2687         }
2688
2689         if (!strcmp(remoteAddress, setAddress))
2690         {
2691             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2692             return true;
2693         }
2694
2695         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2696     }
2697
2698     OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in scanned device list", remoteAddress);
2699
2700     return false;
2701 }
2702
2703 CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env)
2704 {
2705     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices");
2706     VERIFY_NON_NULL(env, TAG, "env is null");
2707
2708     ca_mutex_lock(g_deviceListMutex);
2709
2710     if (!g_deviceList)
2711     {
2712         OIC_LOG(ERROR, TAG, "g_deviceList is null");
2713         ca_mutex_unlock(g_deviceListMutex);
2714         return CA_STATUS_FAILED;
2715     }
2716
2717     uint32_t length = u_arraylist_length(g_deviceList);
2718     for (uint32_t index = 0; index < length; index++)
2719     {
2720         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2721         if (!jarrayObj)
2722         {
2723             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2724             continue;
2725         }
2726         (*env)->DeleteGlobalRef(env, jarrayObj);
2727         jarrayObj = NULL;
2728     }
2729
2730     OICFree(g_deviceList);
2731     g_deviceList = NULL;
2732
2733     ca_mutex_unlock(g_deviceListMutex);
2734     return CA_STATUS_OK;
2735 }
2736
2737 CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address)
2738 {
2739     OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceInScanDeviceList");
2740     VERIFY_NON_NULL(address, TAG, "address is null");
2741     VERIFY_NON_NULL(env, TAG, "env is null");
2742
2743     ca_mutex_lock(g_deviceListMutex);
2744
2745     if (!g_deviceList)
2746     {
2747         OIC_LOG(ERROR, TAG, "g_deviceList is null");
2748         ca_mutex_unlock(g_deviceListMutex);
2749         return CA_STATUS_FAILED;
2750     }
2751
2752     uint32_t length = u_arraylist_length(g_deviceList);
2753     for (uint32_t index = 0; index < length; index++)
2754     {
2755         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2756         if (!jarrayObj)
2757         {
2758             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2759             ca_mutex_unlock(g_deviceListMutex);
2760             return CA_STATUS_FAILED;
2761         }
2762
2763         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2764         if (!jni_setAddress)
2765         {
2766             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2767             ca_mutex_unlock(g_deviceListMutex);
2768             return CA_STATUS_FAILED;
2769         }
2770
2771         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2772         if (!setAddress)
2773         {
2774             OIC_LOG(ERROR, TAG, "setAddress is null");
2775             ca_mutex_unlock(g_deviceListMutex);
2776             return CA_STATUS_FAILED;
2777         }
2778
2779         const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
2780         if (!remoteAddress)
2781         {
2782             OIC_LOG(ERROR, TAG, "remoteAddress is null");
2783             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2784             ca_mutex_unlock(g_deviceListMutex);
2785             return CA_STATUS_FAILED;
2786         }
2787
2788         if (!strcmp(setAddress, remoteAddress))
2789         {
2790             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2791             (*env)->DeleteGlobalRef(env, jarrayObj);
2792             jarrayObj = NULL;
2793             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2794             (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2795
2796             if (NULL == u_arraylist_remove(g_deviceList, index))
2797             {
2798                 OIC_LOG(ERROR, TAG, "List removal failed.");
2799                 ca_mutex_unlock(g_deviceListMutex);
2800                 return CA_STATUS_FAILED;
2801             }
2802             ca_mutex_unlock(g_deviceListMutex);
2803             return CA_STATUS_OK;
2804         }
2805         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2806         (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2807     }
2808
2809     ca_mutex_unlock(g_deviceListMutex);
2810     OIC_LOG(DEBUG, TAG, "There are no object in the device list");
2811
2812     return CA_STATUS_OK;
2813 }
2814
2815 /**
2816  * Gatt Object List
2817  */
2818
2819 CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt)
2820 {
2821     OIC_LOG(DEBUG, TAG, "CALEClientAddGattobjToList");
2822     VERIFY_NON_NULL(env, TAG, "env is null");
2823     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2824
2825     ca_mutex_lock(g_gattObjectMutex);
2826
2827     if (!g_gattObjectList)
2828     {
2829         OIC_LOG(ERROR, TAG, "g_gattObjectList is not available");
2830         ca_mutex_unlock(g_gattObjectMutex);
2831         return CA_STATUS_FAILED;
2832     }
2833
2834     jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
2835     if (!jni_remoteAddress)
2836     {
2837         OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2838         ca_mutex_unlock(g_gattObjectMutex);
2839         return CA_STATUS_FAILED;
2840     }
2841
2842     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2843     if (!remoteAddress)
2844     {
2845         OIC_LOG(ERROR, TAG, "remoteAddress is null");
2846         ca_mutex_unlock(g_gattObjectMutex);
2847         return CA_STATUS_FAILED;
2848     }
2849
2850     OIC_LOG_V(DEBUG, TAG, "remote address : %s", remoteAddress);
2851     if (!CALEClientIsGattObjInList(env, remoteAddress))
2852     {
2853         jobject newGatt = (*env)->NewGlobalRef(env, gatt);
2854         u_arraylist_add(g_gattObjectList, newGatt);
2855         OIC_LOG(INFO, TAG, "added a newGatt object to gattObjectList");
2856     }
2857
2858     (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2859     ca_mutex_unlock(g_gattObjectMutex);
2860     return CA_STATUS_OK;
2861 }
2862
2863 bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress)
2864 {
2865     OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList");
2866     VERIFY_NON_NULL(env, TAG, "env is null");
2867     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2868
2869     uint32_t length = u_arraylist_length(g_gattObjectList);
2870     for (uint32_t index = 0; index < length; index++)
2871     {
2872
2873         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2874         if (!jarrayObj)
2875         {
2876             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2877             return true;
2878         }
2879
2880         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2881         if (!jni_setAddress)
2882         {
2883             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2884             return true;
2885         }
2886
2887         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2888         if (!setAddress)
2889         {
2890             OIC_LOG(ERROR, TAG, "setAddress is null");
2891             return true;
2892         }
2893
2894         if (!strcmp(remoteAddress, setAddress))
2895         {
2896             OIC_LOG(DEBUG, TAG, "the device is already set");
2897             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2898             return true;
2899         }
2900         else
2901         {
2902             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2903             continue;
2904         }
2905     }
2906
2907     OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added");
2908     return false;
2909 }
2910
2911 jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress)
2912 {
2913     OIC_LOG(DEBUG, TAG, "CALEClientGetGattObjInList");
2914     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2915     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
2916
2917     ca_mutex_lock(g_gattObjectMutex);
2918     uint32_t length = u_arraylist_length(g_gattObjectList);
2919     for (uint32_t index = 0; index < length; index++)
2920     {
2921         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2922         if (!jarrayObj)
2923         {
2924             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2925             ca_mutex_unlock(g_gattObjectMutex);
2926             return NULL;
2927         }
2928
2929         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2930         if (!jni_setAddress)
2931         {
2932             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2933             ca_mutex_unlock(g_gattObjectMutex);
2934             return NULL;
2935         }
2936
2937         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2938         if (!setAddress)
2939         {
2940             OIC_LOG(ERROR, TAG, "setAddress is null");
2941             ca_mutex_unlock(g_gattObjectMutex);
2942             return NULL;
2943         }
2944
2945         if (!strcmp(remoteAddress, setAddress))
2946         {
2947             OIC_LOG(DEBUG, TAG, "the device is already set");
2948             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2949             ca_mutex_unlock(g_gattObjectMutex);
2950             return jarrayObj;
2951         }
2952         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2953     }
2954
2955     ca_mutex_unlock(g_gattObjectMutex);
2956     OIC_LOG(DEBUG, TAG, "There are no the gatt object in list");
2957     return NULL;
2958 }
2959
2960 CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env)
2961 {
2962     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs");
2963     VERIFY_NON_NULL(env, TAG, "env is null");
2964
2965     ca_mutex_lock(g_gattObjectMutex);
2966     if (!g_gattObjectList)
2967     {
2968         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2969         ca_mutex_unlock(g_gattObjectMutex);
2970         return CA_STATUS_OK;
2971     }
2972
2973     uint32_t length = u_arraylist_length(g_gattObjectList);
2974     for (uint32_t index = 0; index < length; index++)
2975     {
2976         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2977         if (!jarrayObj)
2978         {
2979             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2980             continue;
2981         }
2982         (*env)->DeleteGlobalRef(env, jarrayObj);
2983         jarrayObj = NULL;
2984     }
2985
2986     OICFree(g_gattObjectList);
2987     g_gattObjectList = NULL;
2988     OIC_LOG(INFO, TAG, "g_gattObjectList is removed");
2989     ca_mutex_unlock(g_gattObjectMutex);
2990     return CA_STATUS_OK;
2991 }
2992
2993 CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt)
2994 {
2995     OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObj");
2996     VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2997     VERIFY_NON_NULL(env, TAG, "env is null");
2998
2999     ca_mutex_lock(g_gattObjectMutex);
3000     if (!g_gattObjectList)
3001     {
3002         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3003         ca_mutex_unlock(g_gattObjectMutex);
3004         return CA_STATUS_OK;
3005     }
3006
3007     uint32_t length = u_arraylist_length(g_gattObjectList);
3008     for (uint32_t index = 0; index < length; index++)
3009     {
3010         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3011         if (!jarrayObj)
3012         {
3013             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3014             ca_mutex_unlock(g_gattObjectMutex);
3015             return CA_STATUS_FAILED;
3016         }
3017
3018         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3019         if (!jni_setAddress)
3020         {
3021             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3022             ca_mutex_unlock(g_gattObjectMutex);
3023             return CA_STATUS_FAILED;
3024         }
3025
3026         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3027         if (!setAddress)
3028         {
3029             OIC_LOG(ERROR, TAG, "setAddress is null");
3030             ca_mutex_unlock(g_gattObjectMutex);
3031             return CA_STATUS_FAILED;
3032         }
3033
3034         jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
3035         if (!jni_remoteAddress)
3036         {
3037             OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
3038             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3039             ca_mutex_unlock(g_gattObjectMutex);
3040             return CA_STATUS_FAILED;
3041         }
3042
3043         const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
3044         if (!remoteAddress)
3045         {
3046             OIC_LOG(ERROR, TAG, "remoteAddress is null");
3047             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3048             ca_mutex_unlock(g_gattObjectMutex);
3049             return CA_STATUS_FAILED;
3050         }
3051
3052         if (!strcmp(setAddress, remoteAddress))
3053         {
3054             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3055             (*env)->DeleteGlobalRef(env, jarrayObj);
3056             jarrayObj = NULL;
3057             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3058             (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3059
3060             if (NULL == u_arraylist_remove(g_gattObjectList, index))
3061             {
3062                 OIC_LOG(ERROR, TAG, "List removal failed.");
3063                 ca_mutex_unlock(g_gattObjectMutex);
3064                 return CA_STATUS_FAILED;
3065             }
3066             ca_mutex_unlock(g_gattObjectMutex);
3067             return CA_STATUS_OK;
3068         }
3069         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3070         (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3071     }
3072
3073     ca_mutex_unlock(g_gattObjectMutex);
3074     OIC_LOG(DEBUG, TAG, "there are no target object");
3075     return CA_STATUS_OK;
3076 }
3077
3078 CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr)
3079 {
3080     OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObjForAddr");
3081     VERIFY_NON_NULL(addr, TAG, "addr is null");
3082     VERIFY_NON_NULL(env, TAG, "env is null");
3083
3084     ca_mutex_lock(g_gattObjectMutex);
3085     if (!g_gattObjectList)
3086     {
3087         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3088         ca_mutex_unlock(g_gattObjectMutex);
3089         return CA_STATUS_OK;
3090     }
3091
3092     uint32_t length = u_arraylist_length(g_gattObjectList);
3093     for (uint32_t index = 0; index < length; index++)
3094     {
3095         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3096         if (!jarrayObj)
3097         {
3098             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3099             ca_mutex_unlock(g_gattObjectMutex);
3100             return CA_STATUS_FAILED;
3101         }
3102
3103         jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3104         if (!jni_setAddress)
3105         {
3106             OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3107             ca_mutex_unlock(g_gattObjectMutex);
3108             return CA_STATUS_FAILED;
3109         }
3110
3111         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3112         if (!setAddress)
3113         {
3114             OIC_LOG(ERROR, TAG, "setAddress is null");
3115             ca_mutex_unlock(g_gattObjectMutex);
3116             return CA_STATUS_FAILED;
3117         }
3118
3119         const char* remoteAddress = (*env)->GetStringUTFChars(env, addr, NULL);
3120         if (!remoteAddress)
3121         {
3122             OIC_LOG(ERROR, TAG, "remoteAddress is null");
3123             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3124             ca_mutex_unlock(g_gattObjectMutex);
3125             return CA_STATUS_FAILED;
3126         }
3127
3128         if (!strcmp(setAddress, remoteAddress))
3129         {
3130             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3131             (*env)->DeleteGlobalRef(env, jarrayObj);
3132             jarrayObj = NULL;
3133             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3134             (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3135             if (NULL == u_arraylist_remove(g_gattObjectList, index))
3136             {
3137                 OIC_LOG(ERROR, TAG, "List removal failed.");
3138                 ca_mutex_unlock(g_gattObjectMutex);
3139                 return CA_STATUS_FAILED;
3140             }
3141             ca_mutex_unlock(g_gattObjectMutex);
3142             return CA_STATUS_OK;
3143         }
3144         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3145         (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3146     }
3147
3148     ca_mutex_unlock(g_gattObjectMutex);
3149     OIC_LOG(DEBUG, TAG, "there are no target object");
3150     return CA_STATUS_FAILED;
3151 }
3152
3153 jstring CALEClientGetLEAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
3154 {
3155     OIC_LOG(DEBUG, TAG, "CALEClientGetLEAddressFromBTDevice");
3156
3157     VERIFY_NON_NULL_RET(env, TAG, "env", NULL);
3158     VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice", NULL);
3159
3160     // get Bluetooth Address
3161     jstring jni_btTargetAddress = CALEGetAddressFromBTDevice(env, bluetoothDevice);
3162     if (!jni_btTargetAddress)
3163     {
3164         OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3165         return NULL;
3166     }
3167
3168     const char* targetAddress = (*env)->GetStringUTFChars(env, jni_btTargetAddress, NULL);
3169     if (!targetAddress)
3170     {
3171         OIC_LOG(ERROR, TAG, "targetAddress is not available");
3172         return NULL;
3173     }
3174
3175     // get method ID of getDevice()
3176     jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
3177                                                    "getDevice", METHODID_BT_DEVICE);
3178     if (!jni_mid_getDevice)
3179     {
3180         OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
3181         (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3182         return NULL;
3183     }
3184
3185     ca_mutex_lock(g_gattObjectMutex);
3186
3187     size_t length = u_arraylist_length(g_gattObjectList);
3188     OIC_LOG_V(DEBUG, TAG, "length of gattObjectList : %d", length);
3189     OIC_LOG_V(DEBUG, TAG, "targetAddress : %s", targetAddress);
3190
3191     for (size_t index = 0; index < length; index++)
3192     {
3193         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3194         if (!jarrayObj)
3195         {
3196             ca_mutex_unlock(g_gattObjectMutex);
3197             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3198             (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3199             return NULL;
3200         }
3201
3202         jobject jni_obj_device = (*env)->CallObjectMethod(env, jarrayObj, jni_mid_getDevice);
3203         if (!jni_obj_device)
3204         {
3205             ca_mutex_unlock(g_gattObjectMutex);
3206             OIC_LOG(ERROR, TAG, "jni_obj_device is null");
3207             (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3208             return NULL;
3209         }
3210
3211         jstring jni_btAddress = CALEGetAddressFromBTDevice(env, jni_obj_device);
3212         if (!jni_btAddress)
3213         {
3214             ca_mutex_unlock(g_gattObjectMutex);
3215             OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3216             (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3217             return NULL;
3218         }
3219
3220         const char* btAddress = (*env)->GetStringUTFChars(env, jni_btAddress, NULL);
3221         if (!btAddress)
3222         {
3223             ca_mutex_unlock(g_gattObjectMutex);
3224             OIC_LOG(ERROR, TAG, "btAddress is not available");
3225             (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3226             return NULL;
3227         }
3228
3229         OIC_LOG_V(DEBUG, TAG, "btAddress : %s (idx: %d)", btAddress, index);
3230         if (!strcmp(targetAddress, btAddress))
3231         {
3232             OIC_LOG(DEBUG, TAG, "Found Gatt object from BT device");
3233
3234             // get LE address
3235             jstring jni_LEAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3236             if (!jni_LEAddress)
3237             {
3238                 OIC_LOG(ERROR, TAG, "jni_LEAddress is null");
3239             }
3240             ca_mutex_unlock(g_gattObjectMutex);
3241             (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3242             (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3243             (*env)->DeleteLocalRef(env, jni_btAddress);
3244             (*env)->DeleteLocalRef(env, jni_obj_device);
3245             return jni_LEAddress;
3246         }
3247         (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3248         (*env)->DeleteLocalRef(env, jni_btAddress);
3249         (*env)->DeleteLocalRef(env, jni_obj_device);
3250     }
3251     ca_mutex_unlock(g_gattObjectMutex);
3252
3253     (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3254     OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in gattObjectList", targetAddress);
3255     return NULL;
3256 }
3257
3258 /**
3259  * BT State List
3260  */
3261
3262 CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type,
3263                                        uint16_t target_state)
3264 {
3265     VERIFY_NON_NULL(address, TAG, "address is null");
3266     VERIFY_NON_NULL(address, TAG, "state_type is null");
3267     VERIFY_NON_NULL(address, TAG, "target_state is null");
3268
3269     if (!g_deviceStateList)
3270     {
3271         OIC_LOG(ERROR, TAG, "gdevice_list is null");
3272         return CA_STATUS_FAILED;
3273     }
3274
3275     ca_mutex_lock(g_deviceStateListMutex);
3276
3277     if (CALEClientIsDeviceInList(address))
3278     {
3279         CALEState_t* curState = CALEClientGetStateInfo(address);
3280         if(!curState)
3281         {
3282             OIC_LOG(ERROR, TAG, "curState is null");
3283             ca_mutex_unlock(g_deviceStateListMutex);
3284             return CA_STATUS_FAILED;
3285         }
3286
3287         switch(state_type)
3288         {
3289             case CA_LE_CONNECTION_STATE:
3290                 curState->connectedState = target_state;
3291                 break;
3292             case CA_LE_SEND_STATE:
3293                 curState->sendState = target_state;
3294                 break;
3295             default:
3296                 break;
3297         }
3298         OIC_LOG_V(INFO, TAG, "update state - addr : %s, conn : %d, send : %d, ACFlag : %d",
3299                   curState->address, curState->connectedState, curState->sendState,
3300                   curState->autoConnectFlag);
3301     }
3302     else /** state is added newly **/
3303     {
3304         if (strlen(address) > CA_MACADDR_SIZE)
3305         {
3306             OIC_LOG(ERROR, TAG, "address is not proper");
3307             ca_mutex_unlock(g_deviceStateListMutex);
3308             return CA_STATUS_INVALID_PARAM;
3309         }
3310
3311         CALEState_t *newstate = (CALEState_t*) OICCalloc(1, sizeof(*newstate));
3312         if (!newstate)
3313         {
3314             OIC_LOG(ERROR, TAG, "out of memory");
3315             ca_mutex_unlock(g_deviceStateListMutex);
3316             return CA_MEMORY_ALLOC_FAILED;
3317         }
3318
3319         OICStrcpy(newstate->address, sizeof(newstate->address), address);
3320
3321         switch(state_type)
3322         {
3323             case CA_LE_CONNECTION_STATE:
3324                 newstate->connectedState = target_state;
3325                 newstate->sendState = STATE_SEND_NONE;
3326                 break;
3327             case CA_LE_SEND_STATE:
3328                 newstate->connectedState = STATE_DISCONNECTED;
3329                 newstate->sendState = target_state;
3330                 break;
3331             default:
3332                 break;
3333         }
3334         OIC_LOG_V(INFO, TAG, "add a new state to List - addr : %s, "
3335                   "conn : %d, send : %d, ACFlag : %d",
3336                   newstate->address, newstate->connectedState, newstate->sendState,
3337                   newstate->autoConnectFlag);
3338         u_arraylist_add(g_deviceStateList, newstate); // update new state
3339     }
3340
3341     ca_mutex_unlock(g_deviceStateListMutex);
3342
3343     return CA_STATUS_OK;
3344 }
3345
3346 bool CALEClientIsDeviceInList(const char* remoteAddress)
3347 {
3348     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3349
3350     if (!g_deviceStateList)
3351     {
3352         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3353         return false;
3354     }
3355
3356     uint32_t length = u_arraylist_length(g_deviceStateList);
3357     for (uint32_t index = 0; index < length; index++)
3358     {
3359         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3360         if (!state)
3361         {
3362             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3363             return false;
3364         }
3365
3366         if (!strcmp(remoteAddress, state->address))
3367         {
3368             OIC_LOG(DEBUG, TAG, "the device is already set");
3369             return true;
3370         }
3371         else
3372         {
3373             continue;
3374         }
3375     }
3376
3377     OIC_LOG(DEBUG, TAG, "there are no the device in list.");
3378     return false;
3379 }
3380
3381 CAResult_t CALEClientRemoveAllDeviceState()
3382 {
3383     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllDeviceState");
3384
3385     ca_mutex_lock(g_deviceStateListMutex);
3386     if (!g_deviceStateList)
3387     {
3388         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3389         ca_mutex_unlock(g_deviceStateListMutex);
3390         return CA_STATUS_FAILED;
3391     }
3392
3393     uint32_t length = u_arraylist_length(g_deviceStateList);
3394     for (uint32_t index = 0; index < length; index++)
3395     {
3396         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3397         if (!state)
3398         {
3399             OIC_LOG(ERROR, TAG, "jarrayObj is null");
3400             continue;
3401         }
3402         OICFree(state);
3403     }
3404
3405     OICFree(g_deviceStateList);
3406     g_deviceStateList = NULL;
3407     ca_mutex_unlock(g_deviceStateListMutex);
3408
3409     return CA_STATUS_OK;
3410 }
3411
3412 CAResult_t CALEClientResetDeviceStateForAll()
3413 {
3414     OIC_LOG(DEBUG, TAG, "CALEClientResetDeviceStateForAll");
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     size_t length = u_arraylist_length(g_deviceStateList);
3425     for (size_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
3434         // autoConnectFlag value will be not changed,
3435         // since it has reset only termination case.
3436         state->connectedState = STATE_DISCONNECTED;
3437         state->sendState = STATE_SEND_NONE;
3438     }
3439     ca_mutex_unlock(g_deviceStateListMutex);
3440
3441     return CA_STATUS_OK;
3442 }
3443
3444 CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress)
3445 {
3446     OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceState");
3447     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
3448
3449     if (!g_deviceStateList)
3450     {
3451         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3452         return CA_STATUS_FAILED;
3453     }
3454
3455     uint32_t length = u_arraylist_length(g_deviceStateList);
3456     for (uint32_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, "CALEState_t object is null");
3462             continue;
3463         }
3464
3465         if (!strcmp(state->address, remoteAddress))
3466         {
3467             OIC_LOG_V(DEBUG, TAG, "remove state : %s", state->address);
3468
3469             CALEState_t* targetState  = (CALEState_t*)u_arraylist_remove(g_deviceStateList,
3470                                                                          index);
3471             if (NULL == targetState)
3472             {
3473                 OIC_LOG(ERROR, TAG, "List removal failed.");
3474                 return CA_STATUS_FAILED;
3475             }
3476
3477             OICFree(targetState);
3478             return CA_STATUS_OK;
3479         }
3480     }
3481
3482     return CA_STATUS_OK;
3483 }
3484
3485 CALEState_t* CALEClientGetStateInfo(const char* remoteAddress)
3486 {
3487     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
3488
3489     if (!g_deviceStateList)
3490     {
3491         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3492         return NULL;
3493     }
3494
3495     uint32_t length = u_arraylist_length(g_deviceStateList);
3496     OIC_LOG_V(DEBUG, TAG, "length of deviceStateList : %d", length);
3497     OIC_LOG_V(DEBUG, TAG, "target address : %s", remoteAddress);
3498
3499     for (uint32_t index = 0; index < length; index++)
3500     {
3501         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3502         if (!state)
3503         {
3504             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3505             continue;
3506         }
3507
3508         OIC_LOG_V(DEBUG, TAG, "state address : %s (idx: %d)", state->address, index);
3509
3510         if (!strcmp(state->address, remoteAddress))
3511         {
3512             OIC_LOG(DEBUG, TAG, "found state");
3513             return state;
3514         }
3515     }
3516
3517     OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in deviceStateList", remoteAddress);
3518     return NULL;
3519 }
3520
3521 bool CALEClientIsValidState(const char* remoteAddress, uint16_t state_type,
3522                              uint16_t target_state)
3523 {
3524     OIC_LOG_V(DEBUG, TAG, "CALEClientIsValidState : type[%d], target state[%d]",
3525               state_type, target_state);
3526     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3527
3528     ca_mutex_lock(g_deviceStateListMutex);
3529     if (!g_deviceStateList)
3530     {
3531         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3532         ca_mutex_unlock(g_deviceStateListMutex);
3533         return false;
3534     }
3535
3536     CALEState_t* state = CALEClientGetStateInfo(remoteAddress);
3537     if (NULL == state)
3538     {
3539         OIC_LOG(ERROR, TAG, "state is null");
3540         ca_mutex_unlock(g_deviceStateListMutex);
3541         return false;
3542     }
3543
3544     uint16_t curValue = 0;
3545     switch(state_type)
3546     {
3547         case CA_LE_CONNECTION_STATE:
3548             curValue = state->connectedState;
3549             break;
3550         case CA_LE_SEND_STATE:
3551             curValue = state->sendState;
3552             break;
3553         default:
3554             break;
3555     }
3556
3557     if (target_state == curValue)
3558     {
3559         ca_mutex_unlock(g_deviceStateListMutex);
3560         return true;
3561     }
3562     else
3563     {
3564         ca_mutex_unlock(g_deviceStateListMutex);
3565         return false;
3566     }
3567
3568     ca_mutex_unlock(g_deviceStateListMutex);
3569     return false;
3570 }
3571
3572 void CALEClientCreateDeviceList()
3573 {
3574     OIC_LOG(DEBUG, TAG, "CALEClientCreateDeviceList");
3575
3576     // create new object array
3577     if (!g_gattObjectList)
3578     {
3579         OIC_LOG(DEBUG, TAG, "Create g_gattObjectList");
3580
3581         g_gattObjectList = u_arraylist_create();
3582     }
3583
3584     if (!g_deviceStateList)
3585     {
3586         OIC_LOG(DEBUG, TAG, "Create g_deviceStateList");
3587
3588         g_deviceStateList = u_arraylist_create();
3589     }
3590
3591     if (!g_deviceList)
3592     {
3593         OIC_LOG(DEBUG, TAG, "Create g_deviceList");
3594
3595         g_deviceList = u_arraylist_create();
3596     }
3597 }
3598
3599 /**
3600  * Check Sent Count for remove g_sendBuffer
3601  */
3602 void CALEClientUpdateSendCnt(JNIEnv *env)
3603 {
3604     OIC_LOG(DEBUG, TAG, "CALEClientUpdateSendCnt");
3605
3606     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3607     // mutex lock
3608     ca_mutex_lock(g_threadMutex);
3609
3610     g_currentSentCnt++;
3611
3612     if (g_targetCnt <= g_currentSentCnt)
3613     {
3614         g_targetCnt = 0;
3615         g_currentSentCnt = 0;
3616
3617         if (g_sendBuffer)
3618         {
3619             (*env)->DeleteGlobalRef(env, g_sendBuffer);
3620             g_sendBuffer = NULL;
3621         }
3622         // notity the thread
3623         ca_cond_signal(g_threadCond);
3624
3625         CALEClientSetSendFinishFlag(true);
3626         OIC_LOG(DEBUG, TAG, "set signal for send data");
3627     }
3628     // mutex unlock
3629     ca_mutex_unlock(g_threadMutex);
3630 }
3631
3632 CAResult_t CALEClientInitGattMutexVaraibles()
3633 {
3634     if (NULL == g_bleReqRespClientCbMutex)
3635     {
3636         g_bleReqRespClientCbMutex = ca_mutex_new();
3637         if (NULL == g_bleReqRespClientCbMutex)
3638         {
3639             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3640             return CA_STATUS_FAILED;
3641         }
3642     }
3643
3644     if (NULL == g_bleServerBDAddressMutex)
3645     {
3646         g_bleServerBDAddressMutex = ca_mutex_new();
3647         if (NULL == g_bleServerBDAddressMutex)
3648         {
3649             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3650             return CA_STATUS_FAILED;
3651         }
3652     }
3653
3654     if (NULL == g_threadMutex)
3655     {
3656         g_threadMutex = ca_mutex_new();
3657         if (NULL == g_threadMutex)
3658         {
3659             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3660             return CA_STATUS_FAILED;
3661         }
3662     }
3663
3664     if (NULL == g_threadSendMutex)
3665     {
3666         g_threadSendMutex = ca_mutex_new();
3667         if (NULL == g_threadSendMutex)
3668         {
3669             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3670             return CA_STATUS_FAILED;
3671         }
3672     }
3673
3674     if (NULL == g_deviceListMutex)
3675     {
3676         g_deviceListMutex = ca_mutex_new();
3677         if (NULL == g_deviceListMutex)
3678         {
3679             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3680             return CA_STATUS_FAILED;
3681         }
3682     }
3683
3684     if (NULL == g_gattObjectMutex)
3685     {
3686         g_gattObjectMutex = ca_mutex_new();
3687         if (NULL == g_gattObjectMutex)
3688         {
3689             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3690             return CA_STATUS_FAILED;
3691         }
3692     }
3693
3694     if (NULL == g_deviceStateListMutex)
3695     {
3696         g_deviceStateListMutex = ca_mutex_new();
3697         if (NULL == g_deviceStateListMutex)
3698         {
3699             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3700             return CA_STATUS_FAILED;
3701         }
3702     }
3703
3704     if (NULL == g_SendFinishMutex)
3705     {
3706         g_SendFinishMutex = ca_mutex_new();
3707         if (NULL == g_SendFinishMutex)
3708         {
3709             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3710             return CA_STATUS_FAILED;
3711         }
3712     }
3713
3714     if (NULL == g_scanMutex)
3715     {
3716         g_scanMutex = ca_mutex_new();
3717         if (NULL == g_scanMutex)
3718         {
3719             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3720             return CA_STATUS_FAILED;
3721         }
3722     }
3723
3724     if (NULL == g_threadWriteCharacteristicMutex)
3725     {
3726         g_threadWriteCharacteristicMutex = ca_mutex_new();
3727         if (NULL == g_threadWriteCharacteristicMutex)
3728         {
3729             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3730             return CA_STATUS_FAILED;
3731         }
3732     }
3733
3734     if (NULL == g_deviceScanRetryDelayMutex)
3735     {
3736         g_deviceScanRetryDelayMutex = ca_mutex_new();
3737         if (NULL == g_deviceScanRetryDelayMutex)
3738         {
3739             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3740             return CA_STATUS_FAILED;
3741         }
3742     }
3743
3744     if (NULL == g_threadSendStateMutex)
3745     {
3746         g_threadSendStateMutex = ca_mutex_new();
3747         if (NULL == g_threadSendStateMutex)
3748         {
3749             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3750             return CA_STATUS_FAILED;
3751         }
3752     }
3753
3754     return CA_STATUS_OK;
3755 }
3756
3757 void CALEClientTerminateGattMutexVariables()
3758 {
3759     ca_mutex_free(g_bleReqRespClientCbMutex);
3760     g_bleReqRespClientCbMutex = NULL;
3761
3762     ca_mutex_free(g_bleServerBDAddressMutex);
3763     g_bleServerBDAddressMutex = NULL;
3764
3765     ca_mutex_free(g_threadMutex);
3766     g_threadMutex = NULL;
3767
3768     ca_mutex_free(g_threadSendMutex);
3769     g_threadSendMutex = NULL;
3770
3771     ca_mutex_free(g_deviceListMutex);
3772     g_deviceListMutex = NULL;
3773
3774     ca_mutex_free(g_SendFinishMutex);
3775     g_SendFinishMutex = NULL;
3776
3777     ca_mutex_free(g_scanMutex);
3778     g_scanMutex = NULL;
3779
3780     ca_mutex_free(g_threadWriteCharacteristicMutex);
3781     g_threadWriteCharacteristicMutex = NULL;
3782
3783     ca_mutex_free(g_deviceScanRetryDelayMutex);
3784     g_deviceScanRetryDelayMutex = NULL;
3785
3786     ca_mutex_free(g_threadSendStateMutex);
3787     g_threadSendStateMutex = NULL;
3788 }
3789
3790 void CALEClientSetSendFinishFlag(bool flag)
3791 {
3792     OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag);
3793
3794     ca_mutex_lock(g_SendFinishMutex);
3795     g_isFinishedSendData = flag;
3796     ca_mutex_unlock(g_SendFinishMutex);
3797 }
3798
3799 /**
3800  * adapter common
3801  */
3802
3803 CAResult_t CAStartLEGattClient()
3804 {
3805     // init mutex for send logic
3806     if (!g_deviceDescCond)
3807     {
3808         g_deviceDescCond = ca_cond_new();
3809     }
3810
3811     if (!g_threadCond)
3812     {
3813         g_threadCond = ca_cond_new();
3814     }
3815
3816     if (!g_threadWriteCharacteristicCond)
3817     {
3818         g_threadWriteCharacteristicCond = ca_cond_new();
3819     }
3820
3821     CAResult_t ret = CALEClientStartScan();
3822     if (CA_STATUS_OK != ret)
3823     {
3824         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
3825         return ret;
3826     }
3827
3828     g_isStartedLEClient = true;
3829     return CA_STATUS_OK;
3830 }
3831
3832 void CAStopLEGattClient()
3833 {
3834     OIC_LOG(DEBUG, TAG, "CAStopBLEGattClient");
3835
3836     if (!g_jvm)
3837     {
3838         OIC_LOG(ERROR, TAG, "g_jvm is null");
3839         return;
3840     }
3841
3842     bool isAttached = false;
3843     JNIEnv* env;
3844     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
3845     if (JNI_OK != res)
3846     {
3847         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
3848         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
3849
3850         if (JNI_OK != res)
3851         {
3852             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
3853             return;
3854         }
3855         isAttached = true;
3856     }
3857
3858     CAResult_t ret = CALEClientDisconnectAll(env);
3859     if (CA_STATUS_OK != ret)
3860     {
3861         OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
3862     }
3863
3864     ret = CALEClientStopScan();
3865     if(CA_STATUS_OK != ret)
3866     {
3867         OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
3868     }
3869
3870     ca_mutex_lock(g_threadMutex);
3871     OIC_LOG(DEBUG, TAG, "signal - connection cond");
3872     ca_cond_signal(g_threadCond);
3873     CALEClientSetSendFinishFlag(true);
3874     ca_mutex_unlock(g_threadMutex);
3875
3876     ca_mutex_lock(g_threadWriteCharacteristicMutex);
3877     OIC_LOG(DEBUG, TAG, "signal - WriteCharacteristic cond");
3878     ca_cond_signal(g_threadWriteCharacteristicCond);
3879     ca_mutex_unlock(g_threadWriteCharacteristicMutex);
3880
3881     ca_mutex_lock(g_deviceScanRetryDelayMutex);
3882     OIC_LOG(DEBUG, TAG, "signal - delay cond");
3883     ca_cond_signal(g_deviceScanRetryDelayCond);
3884     ca_mutex_unlock(g_deviceScanRetryDelayMutex);
3885
3886     ca_cond_free(g_deviceDescCond);
3887     ca_cond_free(g_threadCond);
3888     ca_cond_free(g_threadWriteCharacteristicCond);
3889     ca_cond_free(g_deviceScanRetryDelayCond);
3890
3891     g_deviceDescCond = NULL;
3892     g_threadCond = NULL;
3893     g_threadWriteCharacteristicCond = NULL;
3894     g_deviceScanRetryDelayCond = NULL;
3895
3896     if (isAttached)
3897     {
3898         (*g_jvm)->DetachCurrentThread(g_jvm);
3899     }
3900
3901 }
3902
3903 CAResult_t CAInitializeLEGattClient()
3904 {
3905     OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
3906     CALEClientInitialize();
3907     return CA_STATUS_OK;
3908 }
3909
3910 void CATerminateLEGattClient()
3911 {
3912     OIC_LOG(DEBUG, TAG, "Terminate GATT Client");
3913     CAStopLEGattClient();
3914     CALEClientTerminate();
3915 }
3916
3917 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t  *data,
3918                                                uint32_t dataLen, CALETransferType_t type,
3919                                                int32_t position)
3920 {
3921     OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage");
3922     VERIFY_NON_NULL(data, TAG, "data is null");
3923     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
3924
3925     if (LE_UNICAST != type || position < 0)
3926     {
3927         OIC_LOG(ERROR, TAG, "this request is not unicast");
3928         return CA_STATUS_INVALID_PARAM;
3929     }
3930
3931     return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
3932 }
3933
3934 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
3935 {
3936     OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
3937     VERIFY_NON_NULL(data, TAG, "data is null");
3938
3939     return CALEClientSendMulticastMessage(data, dataLen);
3940 }
3941
3942 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
3943 {
3944     ca_mutex_lock(g_bleReqRespClientCbMutex);
3945     g_CABLEClientDataReceivedCallback = callback;
3946     ca_mutex_unlock(g_bleReqRespClientCbMutex);
3947 }
3948
3949 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
3950 {
3951     g_threadPoolHandle = handle;
3952 }
3953
3954 CAResult_t CAGetLEAddress(char **local_address)
3955 {
3956     VERIFY_NON_NULL(local_address, TAG, "local_address");
3957     OIC_LOG(INFO, TAG, "CAGetLEAddress is not support");
3958     return CA_NOT_SUPPORTED;
3959 }
3960
3961 JNIEXPORT void JNICALL
3962 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
3963                                                                     jobject callback)
3964 {
3965     OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
3966     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3967     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3968     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
3969
3970     g_leScanCallback = (*env)->NewGlobalRef(env, callback);
3971 }
3972
3973 JNIEXPORT void JNICALL
3974 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
3975                                                                   jobject callback)
3976 {
3977     OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
3978     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3979     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3980     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
3981
3982     g_leGattCallback = (*env)->NewGlobalRef(env, callback);
3983 }
3984
3985 JNIEXPORT void JNICALL
3986 Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
3987                                                           jobject device)
3988 {
3989     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3990     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3991     VERIFY_NON_NULL_VOID(device, TAG, "device is null");
3992
3993     CAResult_t res = CALEClientAddScanDeviceToList(env, device);
3994     if (CA_STATUS_OK != res)
3995     {
3996         OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
3997     }
3998 }
3999
4000 static jstring CALEClientGetAddressFromGatt(JNIEnv *env, jobject gatt)
4001 {
4002     OIC_LOG(DEBUG, TAG, "IN - CAManagerGetAddressFromGatt");
4003
4004     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
4005     VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
4006
4007     jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
4008                                                    "getDevice", METHODID_BT_DEVICE);
4009     if (!jni_mid_getDevice)
4010     {
4011         OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
4012         return NULL;
4013     }
4014
4015     jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
4016     if (!jni_obj_device)
4017     {
4018         OIC_LOG(ERROR, TAG, "jni_obj_device is null");
4019         return NULL;
4020     }
4021
4022     jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
4023     if (!jni_address)
4024     {
4025         OIC_LOG(ERROR, TAG, "jni_address is null");
4026         return NULL;
4027     }
4028
4029     OIC_LOG(DEBUG, TAG, "OUT - CAManagerGetAddressFromGatt");
4030     return jni_address;
4031 }
4032
4033 /*
4034  * Class:     org_iotivity_ca_jar_caleinterface
4035  * Method:    CALeGattConnectionStateChangeCallback
4036  * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
4037  */
4038 JNIEXPORT void JNICALL
4039 Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
4040                                                                                jobject obj,
4041                                                                                jobject gatt,
4042                                                                                jint status,
4043                                                                                jint newstate)
4044 {
4045     OIC_LOG_V(INFO, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
4046               newstate);
4047     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4048     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4049     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4050
4051     jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
4052
4053     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4054     if (!jni_address)
4055     {
4056         OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
4057         goto error_exit;
4058     }
4059
4060     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4061     if (!address)
4062     {
4063         OIC_LOG(ERROR, TAG, "address is null");
4064         goto error_exit;
4065     }
4066     OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address);
4067
4068     CAResult_t res;
4069     if (state_connected == newstate)
4070     {
4071         OIC_LOG(DEBUG, TAG, "LE is connected");
4072         if (GATT_SUCCESS == status)
4073         {
4074             res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE, STATE_CONNECTED);
4075             (*env)->ReleaseStringUTFChars(env, jni_address, address);
4076             if (CA_STATUS_OK != res)
4077             {
4078                 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4079                 goto error_exit;
4080             }
4081
4082             res = CALEClientAddGattobjToList(env, gatt);
4083             if (CA_STATUS_OK != res)
4084             {
4085                 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
4086                 goto error_exit;
4087             }
4088
4089             res = CALEClientDiscoverServices(env, gatt);
4090             if (CA_STATUS_OK != res)
4091             {
4092                 OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
4093                 goto error_exit;
4094             }
4095         }
4096         else
4097         {
4098             OIC_LOG(INFO, TAG, "unknown status");
4099             (*env)->ReleaseStringUTFChars(env, jni_address, address);
4100         }
4101     }
4102     else // STATE_DISCONNECTED == newstate
4103     {
4104         OIC_LOG(DEBUG, TAG, "LE is disconnected");
4105
4106         res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE, STATE_DISCONNECTED);
4107         (*env)->ReleaseStringUTFChars(env, jni_address, address);
4108         if (CA_STATUS_OK != res)
4109         {
4110             OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4111             goto error_exit;
4112         }
4113
4114         res = CALEClientGattClose(env, gatt);
4115         if (CA_STATUS_OK != res)
4116         {
4117             OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
4118         }
4119
4120         if (GATT_ERROR == status)
4121         {
4122             // when we get GATT ERROR(0x85), gatt connection can be called again.
4123             OIC_LOG(INFO, TAG, "retry gatt connect");
4124
4125             jstring leAddress = CALEClientGetAddressFromGatt(env, gatt);
4126             if (!leAddress)
4127             {
4128                 OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGatt has failed");
4129                 goto error_exit;
4130             }
4131
4132             jobject btObject = CALEGetRemoteDevice(env, leAddress);
4133             if (!btObject)
4134             {
4135                 OIC_LOG(ERROR, TAG, "CALEGetRemoteDevice has failed");
4136                 goto error_exit;
4137             }
4138
4139             jobject newGatt = CALEClientConnect(env, btObject, JNI_TRUE);
4140             if (!newGatt)
4141             {
4142                 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
4143                 goto error_exit;
4144             }
4145
4146             return;
4147         }
4148         else
4149         {
4150             if (CALECheckConnectionStateValue(status))
4151             {
4152                 // this state is unexpected reason to disconnect
4153                 // if the reason is suitable, connection logic of the device will be destroyed.
4154                 OIC_LOG(INFO, TAG, "connection logic destroy");
4155                 goto error_exit;
4156             }
4157             else
4158             {
4159                 // other reason except for gatt_success is expected to running
4160                 // background connection in BT platform.
4161                 OIC_LOG(INFO, TAG, "unknown status or manual disconnected state");
4162                 CALEClientUpdateSendCnt(env);
4163                 return;
4164             }
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 }