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