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