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