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