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