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