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