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