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