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