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