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