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