Replace glib threadpool usage with a 'dumb' thread implementation.
[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 "calecore.h"
27 #include "caleserver.h"
28 #include "caleutils.h"
29
30 #include "logger.h"
31 #include "oic_malloc.h"
32 #include "cathreadpool.h" /* for thread pool */
33 #include "camutex.h"
34 #include "uarraylist.h"
35 #include "com_iotivity_jar_caleinterface.h"
36
37 //#define DEBUG_MODE
38 #define TAG PCF("CA_LE_CLIENT")
39
40 static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;";
41 static const char METHODID_STRINGNONPARAM[] = "()Ljava/lang/String;";
42 static const char CLASSPATH_BT_ADPATER[] = "android/bluetooth/BluetoothAdapter";
43 static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
44 static const char CLASSPATH_BT_GATT[] = "android/bluetooth/BluetoothGatt";
45
46 static const char IOTIVITY_GATT_SERVIE_UUID[] = "713d0000-503e-4c75-ba94-3148f18d941e";
47 static const char IOTIVITY_GATT_TX_UUID[] = "713d0003-503e-4c75-ba94-3148f18d941e";
48 static const char IOTIVITY_GATT_RX_UUID[] = "713d0002-503e-4c75-ba94-3148f18d941e";
49
50 static const uint32_t STATE_CONNECTED = 2;
51 static const uint32_t STATE_DISCONNECTED = 0;
52 static const uint32_t GATT_SUCCESS = 0;
53
54 static const size_t MAX_PDU_BUFFER = 1400;
55
56 JavaVM *g_jvm;
57 static u_arraylist_t *g_deviceList = NULL;
58 static u_arraylist_t *g_gattObjectList = NULL;
59 static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
60 static ca_thread_pool_t g_threadPoolHandle = NULL;
61 static jobject g_leScanCallback;
62 static jobject g_leGattCallback;
63 static jobject g_context;
64 static jobjectArray g_UUIDList;
65 static jboolean g_isStartServer;
66 static jboolean g_isFinishSendData;
67
68 static jbyteArray g_sendBuffer;
69 static uint32_t g_targetCnt = 0;
70 static uint32_t g_currentSentCnt = 0;
71
72 /** mutex for synchrnoization **/
73 static ca_mutex g_threadMutex;
74 /** conditional mutex for synchrnoization **/
75 static ca_cond g_threadCond;
76
77 ///////////////////////////////////////////////////////////////////////////////////////////////////
78 //FIXME getting context
79 void CALEClientJNISetContext(JNIEnv *env, jobject context)
80 {
81     OIC_LOG(DEBUG, TAG, "CALEClientJNISetContext");
82
83     if (context == NULL)
84     {
85         OIC_LOG(ERROR, TAG, "context is null");
86         return;
87     }
88
89     g_context = (*env)->NewGlobalRef(env, context);
90 }
91
92 void CALeCreateJniInterfaceObject()
93 {
94     OIC_LOG(DEBUG, TAG, "CALeCreateJniInterfaceObject");
95
96     jboolean isAttached = JNI_FALSE;
97     JNIEnv* env;
98     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
99     if (res != JNI_OK)
100     {
101         OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
102         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
103
104         if (res != JNI_OK)
105         {
106             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
107             return;
108         }
109         isAttached = JNI_TRUE;
110     }
111
112     jclass LeJniInterface = (*env)->FindClass(env, "com/iotivity/jar/CALeInterface");
113     if (!LeJniInterface)
114     {
115         OIC_LOG(DEBUG, TAG, "Could not get CALeInterface class");
116         return;
117     }
118
119     jmethodID LeInterfaceConstructorMethod = (*env)->GetMethodID(env, LeJniInterface, "<init>",
120                                                                  "(Landroid/content/Context;)V");
121     if (!LeInterfaceConstructorMethod)
122     {
123         OIC_LOG(DEBUG, TAG, "Could not get CALeInterface constructor method");
124         return;
125     }
126
127     (*env)->NewObject(env, LeJniInterface, LeInterfaceConstructorMethod, g_context);
128     OIC_LOG(DEBUG, TAG, "Create CALeInterface instance");
129
130     if (isAttached)
131     {
132         (*g_jvm)->DetachCurrentThread(g_jvm);
133     }
134 }
135
136 JNIEXPORT jint JNI_OnLoad(JavaVM *jvm, void *reserved)
137 {
138     OIC_LOG(DEBUG, TAG, "JNI_OnLoad in calecore");
139
140     JNIEnv* env;
141     if ((*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
142     {
143         return -1;
144     }
145     g_jvm = jvm; /* cache the JavaVM pointer */
146
147     //JVM required for WifiCore to work with JNI interface
148     CAWiFiJniInit(jvm);
149     CALeServerJniInit(env, jvm);
150     CAEDRCoreJniInit(env, jvm);
151
152     return JNI_VERSION_1_6;
153 }
154
155 void JNI_OnUnload(JavaVM *jvm, void *reserved)
156 {
157     OIC_LOG(DEBUG, TAG, "JNI_OnUnload in calecore");
158
159     JNIEnv* env;
160     if ((*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
161     {
162         return;
163     }
164     g_jvm = 0;
165     return;
166 }
167
168 void CALEInitialize(ca_thread_pool_t handle)
169 {
170     OIC_LOG(DEBUG, TAG, "CALEInitialize");
171
172     g_threadPoolHandle = handle;
173
174     // init mutex for send logic
175     g_threadMutex = ca_mutex_new();
176     g_threadCond = ca_cond_new();
177
178     CANativeCreateUUIDList();
179
180     CALeCreateJniInterfaceObject(); /* create java CALeInterface instance*/
181 }
182
183 void CALETerminate()
184 {
185     OIC_LOG(DEBUG, TAG, "CALETerminate");
186
187     jboolean isAttached = JNI_FALSE;
188     JNIEnv* env;
189     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
190     if (res != JNI_OK)
191     {
192         OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
193         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
194
195         if (res != JNI_OK)
196         {
197             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
198             return;
199         }
200         isAttached = JNI_TRUE;
201     }
202
203     CANativeLEDisconnectAll(env);
204
205     if (g_leScanCallback)
206     {
207         CANativeLEStopScanImpl(env, g_leScanCallback);
208         sleep(1);
209     }
210
211     if (g_leScanCallback)
212     {
213         (*env)->DeleteGlobalRef(env, g_leScanCallback);
214     }
215
216     if (g_leGattCallback)
217     {
218         (*env)->DeleteGlobalRef(env, g_leGattCallback);
219     }
220
221     if (g_context)
222     {
223         (*env)->DeleteGlobalRef(env, g_context);
224     }
225
226     if (g_sendBuffer)
227     {
228         (*env)->DeleteGlobalRef(env, g_sendBuffer);
229     }
230
231     if (g_UUIDList)
232     {
233         (*env)->DeleteGlobalRef(env, g_UUIDList);
234     }
235
236     CANativeRemoveAllDevices(env);
237     CANativeRemoveAllGattObjsList(env);
238     g_isStartServer = FALSE;
239     g_isFinishSendData = FALSE;
240
241     if (isAttached)
242     {
243         (*g_jvm)->DetachCurrentThread(g_jvm);
244     }
245
246     // delete mutex object
247     ca_mutex_free(g_threadMutex);
248     g_threadMutex = NULL;
249     ca_cond_signal(g_threadCond);
250     ca_cond_free(g_threadCond);
251 }
252
253 void CANativeSendFinish(JNIEnv *env, jobject gatt)
254 {
255     OIC_LOG(DEBUG, TAG, "CANativeSendFinish");
256
257     if (gatt)
258     {
259         CANativeLEDisconnect(env, gatt);
260     }
261     CANativeupdateSendCnt(env);
262 }
263
264 CAResult_t CALESendUnicastMessage(const char* address, const char* data, const uint32_t dataLen)
265 {
266     OIC_LOG_V(DEBUG, TAG, "CALESendUnicastMessage(%s, %s)", address, data);
267
268     return CALESendUnicastMessageImpl(address, data, dataLen);
269 }
270
271 CAResult_t CALESendMulticastMessage(const char* data, const uint32_t dataLen)
272 {
273     OIC_LOG_V(DEBUG, TAG, "CALESendMulticastMessage(%s)", data);
274
275     return CALESendMulticastMessageImpl(data, dataLen);
276 }
277
278 CAResult_t CALEStartUnicastServer(const char* address)
279 {
280     OIC_LOG_V(DEBUG, TAG, "CALEStartUnicastServer(%s)", address);
281
282     return CA_STATUS_OK;
283 }
284
285 CAResult_t CALEStartMulticastServer()
286 {
287     OIC_LOG(DEBUG, TAG, "CALEStartMulticastServer");
288
289     if (g_isStartServer)
290     {
291         OIC_LOG(ERROR, TAG, "server is already started..it will be skipped");
292         return CA_STATUS_FAILED;
293     }
294
295     jboolean isAttached = JNI_FALSE;
296     JNIEnv* env;
297     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
298     if (res != JNI_OK)
299     {
300         OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
301         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
302
303         if (res != JNI_OK)
304         {
305             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
306             return CA_STATUS_FAILED;
307         }
308         isAttached = JNI_TRUE;
309     }
310
311     g_isStartServer = JNI_TRUE;
312
313     CANativeLEStartScan();
314
315     if (isAttached)
316     {
317         (*g_jvm)->DetachCurrentThread(g_jvm);
318     }
319
320     return CA_STATUS_OK;
321 }
322
323 void CALEStopUnicastServer()
324 {
325     OIC_LOG(DEBUG, TAG, "CALEStopUnicastServer");
326 }
327
328 void CALEStopMulticastServer()
329 {
330     OIC_LOG(DEBUG, TAG, "CALEStopMulticastServer");
331     g_isStartServer = JNI_FALSE;
332     CANativeLEStopScan();
333 }
334
335 void CALESetCallback(CAPacketReceiveCallback callback)
336 {
337     g_packetReceiveCallback = callback;
338 }
339
340 CAResult_t CALEGetInterfaceInfo(char **address)
341 {
342     CALEGetLocalAddress(address);
343     return CA_STATUS_OK;
344 }
345
346 void CALEGetLocalAddress(char** address)
347 {
348     jboolean isAttached = JNI_FALSE;
349     JNIEnv* env;
350     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
351     if (res != JNI_OK)
352     {
353         OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
354         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
355         if (res != JNI_OK)
356         {
357             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
358             return;
359         }
360         isAttached = JNI_TRUE;
361     }
362
363     jstring jni_address = CALEGetLocalDeviceAddress(env);
364     if (jni_address)
365     {
366         const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
367         uint32_t length = strlen(localAddress);
368         *address = (char*) OICMalloc(length + 1);
369         if (*address == NULL)
370         {
371             return;
372         }
373         memcpy(*address, localAddress, length + 1);
374     }
375
376     OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
377     if (isAttached)
378     {
379         (*g_jvm)->DetachCurrentThread(g_jvm);
380     }
381 }
382
383 CAResult_t CALESendUnicastMessageImpl(const char* address, const char* data, const uint32_t dataLen)
384 {
385     OIC_LOG_V(DEBUG, TAG, "CALESendUnicastMessageImpl, address: %s, data: %s", address, data);
386
387     jboolean isAttached = JNI_FALSE;
388     JNIEnv* env;
389     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
390     if (res != JNI_OK)
391     {
392         OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
393         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
394         if (res != JNI_OK)
395         {
396             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
397             return CA_STATUS_FAILED;
398         }
399         isAttached = JNI_TRUE;
400     }
401
402     OIC_LOG(DEBUG, TAG, "[BLE][Native] set byteArray for data");
403     if (g_sendBuffer)
404     {
405         (*env)->DeleteGlobalRef(env, g_sendBuffer);
406     }
407     jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
408     (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
409     g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
410
411     // connect to gatt server
412     CANativeLEStopScanImpl(env, g_leScanCallback);
413     sleep(1);
414
415     jobject jni_obj_bluetoothDevice = NULL;
416     if (g_context && g_deviceList)
417     {
418         jint index;
419         for (index = 0; index < u_arraylist_length(g_deviceList); index++)
420         {
421             jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
422             if (!jarrayObj)
423             {
424                 OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is null");
425                 return CA_STATUS_FAILED;
426             }
427
428             jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
429             if (!jni_setAddress)
430             {
431                 OIC_LOG(ERROR, TAG, "[BLE][Native] jni_setAddress is null");
432                 return CA_STATUS_FAILED;
433             }
434             const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
435
436             if (!strcmp(setAddress, address))
437             {
438                 jni_obj_bluetoothDevice = jarrayObj;
439                 break;
440             }
441         }
442
443         if (jni_obj_bluetoothDevice)
444         {
445             jboolean autoConnect = FALSE;
446             CANativeLEConnect(env, jni_obj_bluetoothDevice, g_context, autoConnect,
447                               g_leGattCallback);
448         }
449     }
450
451     if (isAttached)
452     {
453         (*g_jvm)->DetachCurrentThread(g_jvm);
454     }
455
456     return CA_STATUS_OK;
457 }
458
459 CAResult_t CALESendMulticastMessageImpl(const char* data, const uint32_t dataLen)
460 {
461     OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen);
462
463     jboolean isAttached = JNI_FALSE;
464     JNIEnv* env;
465     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
466     if (res != JNI_OK)
467     {
468         OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
469         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
470         if (res != JNI_OK)
471         {
472             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
473             return CA_STATUS_FAILED;
474         }
475         isAttached = JNI_TRUE;
476     }
477
478     if (!g_deviceList)
479     {
480         OIC_LOG(ERROR, TAG, "[BLE][Native] g_deviceList is null");
481         return CA_STATUS_FAILED;
482     }OIC_LOG(DEBUG, TAG, "set wait");
483
484     g_isFinishSendData = JNI_FALSE;
485
486     OIC_LOG(DEBUG, TAG, "[BLE][Native] set byteArray for data");
487     if (g_sendBuffer)
488     {
489         (*env)->DeleteGlobalRef(env, g_sendBuffer);
490     }
491     jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
492     (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
493     g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
494
495     // connect to gatt server
496     CANativeLEStopScanImpl(env, g_leScanCallback);
497     sleep(1);
498
499     // reset gatt list
500     CANativeRemoveAllGattObjsList(env);
501     CANativeCreateGattObjList(env);
502
503     g_targetCnt = u_arraylist_length(g_deviceList);
504
505     jint index = 0;
506
507     while (index < u_arraylist_length(g_deviceList))
508     {
509         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
510         if (!jarrayObj)
511         {
512             OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is null");
513             continue;
514         }
515
516         if (CA_STATUS_FAILED
517                 == CANativeLEConnect(env, jarrayObj, g_context, JNI_FALSE, g_leGattCallback))
518         {
519             // connection failure
520         }
521         index++;
522         sleep(1);
523     }
524
525     // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
526     if (!g_isFinishSendData)
527     {
528         ca_mutex_lock(g_threadMutex);
529         ca_cond_wait(g_threadCond, g_threadMutex);
530         OIC_LOG(DEBUG, TAG, "unset wait");
531         ca_mutex_unlock(g_threadMutex);
532     }
533
534     // start LE Scan again
535 #ifdef DEBUG_MODE
536     CANativeLEStartScan();
537 #endif
538
539     if (isAttached)
540     {
541         (*g_jvm)->DetachCurrentThread(g_jvm);
542     }
543
544     return CA_STATUS_OK;
545 }
546
547 jstring CANativeGetAddressFromGattObj(JNIEnv *env, jobject gatt)
548 {
549     if (!gatt)
550     {
551         OIC_LOG(ERROR, TAG, "[BLE][Native] gatt is null");
552         return NULL;
553     }
554
555     jclass jni_cid_gattdevice_list = (*env)->FindClass(env, CLASSPATH_BT_GATT);
556     if (!jni_cid_gattdevice_list)
557     {
558         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_gattdevice_list is null");
559         return NULL;
560     }
561
562     jmethodID jni_mid_getDevice = (*env)->GetMethodID(env, jni_cid_gattdevice_list, "getDevice",
563                                                       "()Landroid/bluetooth/BluetoothDevice;");
564     if (!jni_mid_getDevice)
565     {
566         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_getDevice is null");
567         return NULL;
568     }
569
570     jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
571     if (!jni_obj_device)
572     {
573         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_obj_device is null");
574         return NULL;
575     }
576
577     jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
578     if (!jni_address)
579     {
580         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_address is null");
581         return NULL;
582     }
583
584     return jni_address;
585 }
586
587 /**
588  * BLE layer
589  */
590 void CANativeGattClose(JNIEnv *env, jobject bluetoothGatt)
591 {
592     // GATT CLOSE
593     OIC_LOG(DEBUG, TAG, "[BLE][Native] GATT CLOSE");
594
595     // get BluetoothGatt class
596     OIC_LOG(DEBUG, TAG, "[BLE][Native] get BluetoothGatt class");
597     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
598     if (!jni_cid_BluetoothGatt)
599     {
600         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
601         return;
602     }
603
604     jmethodID jni_mid_closeGatt = (*env)->GetMethodID(env, jni_cid_BluetoothGatt, "close", "()V");
605     if (!jni_mid_closeGatt)
606     {
607         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_closeGatt is null");
608         return;
609     }
610
611     // call disconnect gatt method
612     OIC_LOG(DEBUG, TAG, "[BLE][Native] request close Gatt");
613     (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_closeGatt);
614 }
615
616 void CANativeLEStartScan()
617 {
618     if (!g_isStartServer)
619     {
620         OIC_LOG(DEBUG, TAG, "server is not started yet..scan will be passed");
621         return;
622     }
623
624     jboolean isAttached = FALSE;
625     JNIEnv* env;
626     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
627     if (res != JNI_OK)
628     {
629         OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
630
631         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
632         if (res != JNI_OK)
633         {
634             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
635             return;
636         }
637         isAttached = TRUE;
638     }
639
640     OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeLEStartScan");
641
642     // scan gatt server with UUID
643     if (g_leScanCallback && g_UUIDList)
644     {
645         CANativeLEStartScanWithUUIDImpl(env, g_UUIDList, g_leScanCallback);
646     }
647
648     if (isAttached)
649     {
650         (*g_jvm)->DetachCurrentThread(g_jvm);
651     }
652
653 }
654
655 void CANativeLEStartScanImpl(JNIEnv *env, jobject callback)
656 {
657     if (!CALEIsEnableBTAdapter(env))
658     {
659         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
660         return;
661     }
662
663     // get default bt adapter class
664     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
665     if (!jni_cid_BTAdapter)
666     {
667         OIC_LOG(ERROR, TAG, "[BLE][Native] getState From BTAdapter: jni_cid_BTAdapter is null");
668         return;
669     }
670
671     // get remote bt adapter method
672     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
673                                                                     "getDefaultAdapter",
674                                                                     METHODID_OBJECTNONPARAM);
675     if (!jni_mid_getDefaultAdapter)
676     {
677         OIC_LOG(ERROR, TAG, "[BLE][Native] getState From BTAdapter: getDefaultAdapter is null");
678         return;
679     }
680
681     // get start le scan method
682     jmethodID jni_mid_startLeScan = (*env)->GetMethodID(
683             env, jni_cid_BTAdapter, "startLeScan",
684             "(Landroid/bluetooth/BluetoothAdapter$LeScanCallback;)Z");
685     if (!jni_mid_startLeScan)
686     {
687         OIC_LOG(ERROR, TAG, "[BLE][Native] startLeScan: jni_mid_startLeScan is null");
688         return;
689     }
690
691     // gat bt adapter object
692     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
693                                                                jni_mid_getDefaultAdapter);
694     if (!jni_obj_BTAdapter)
695     {
696         OIC_LOG(ERROR, TAG, "[BLE][Native] getState From BTAdapter: jni_obj_BTAdapter is null");
697         return;
698     }
699
700     // call start le scan method
701     jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
702                                                              jni_mid_startLeScan, callback);
703     if (!jni_obj_startLeScan)
704     {
705         OIC_LOG(ERROR, TAG, "[BLE][Native] startLeScan is failed");
706         return;
707     }
708     else
709     {
710         OIC_LOG(DEBUG, TAG, "[BLE][Native] startLeScan is started");
711     }
712 }
713
714 jobject CANativeGetUUIDObject(JNIEnv *env, const char* uuid)
715 {
716     // setting UUID
717     jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
718     if (!jni_cid_uuid)
719     {
720         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_uuid is null");
721         return NULL;
722     }
723
724     jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
725             env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
726     if (!jni_mid_fromString)
727     {
728         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_fromString is null");
729         return NULL;
730     }
731
732     jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
733     jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
734                                                           jni_uuid);
735     if (!jni_obj_uuid)
736     {
737         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_obj_uuid is null");
738         return NULL;
739     }
740
741     return jni_obj_uuid;
742 }
743
744 void CANativeLEStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback)
745 {
746     // get default bt adapter class
747     OIC_LOG(DEBUG, TAG, "[BLE][Native] get default bt adapter class");
748
749     if (!CALEIsEnableBTAdapter(env))
750     {
751         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
752         return;
753     }
754
755     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
756     if (!jni_cid_BTAdapter)
757     {
758         OIC_LOG(ERROR, TAG, "[BLE][Native] getState From BTAdapter: jni_cid_BTAdapter is null");
759         return;
760     }
761
762     // get remote bt adapter method
763     OIC_LOG(DEBUG, TAG, "[BLE][Native] get remote bt adapter method");
764     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
765                                                                     "getDefaultAdapter",
766                                                                     METHODID_OBJECTNONPARAM);
767     if (!jni_mid_getDefaultAdapter)
768     {
769         OIC_LOG(ERROR, TAG, "[BLE][Native] getState From BTAdapter: getDefaultAdapter is null");
770         return;
771     }
772
773     // get start le scan method
774     OIC_LOG(DEBUG, TAG, "[BLE][Native] get start le scan method");
775     jmethodID jni_mid_startLeScan = (*env)->GetMethodID(
776             env, jni_cid_BTAdapter, "startLeScan",
777             "([Ljava/util/UUID;Landroid/bluetooth/BluetoothAdapter$LeScanCallback;)Z");
778     if (!jni_mid_startLeScan)
779     {
780         OIC_LOG(ERROR, TAG, "[BLE][Native] startLeScan: jni_mid_startLeScan is null");
781         return;
782     }
783
784     // get bt adapter object
785     OIC_LOG(DEBUG, TAG, "[BLE][Native] get bt adapter object");
786     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
787                                                                jni_mid_getDefaultAdapter);
788     if (!jni_obj_BTAdapter)
789     {
790         OIC_LOG(ERROR, TAG, "[BLE][Native] getState From BTAdapter: jni_obj_BTAdapter is null");
791         return;
792     }
793
794     // call start le scan method
795     OIC_LOG(DEBUG, TAG, "[BLE][Native] call start le scan service method");
796     jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
797                                                              jni_mid_startLeScan, uuids, callback);
798     if (!jni_obj_startLeScan)
799     {
800         OIC_LOG(ERROR, TAG, "[BLE][Native] startLeScan With UUID is failed");
801         return;
802     }
803     else
804     {
805         OIC_LOG(DEBUG, TAG, "[BLE][Native] startLeScan With UUID is started");
806     }
807 }
808
809 void CANativeLEStopScan()
810 {
811     jboolean isAttached = FALSE;
812     JNIEnv* env;
813     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
814     if (res != JNI_OK)
815     {
816         OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
817         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
818         if (res != JNI_OK)
819         {
820             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
821             return;
822         }
823         isAttached = TRUE;
824     }
825
826     CANativeLEStopScanImpl(env, g_leScanCallback);
827
828     if (isAttached)
829     {
830         (*g_jvm)->DetachCurrentThread(g_jvm);
831     }
832
833 }
834
835 void CANativeLEStopScanImpl(JNIEnv *env, jobject callback)
836 {
837     OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeLEStopScan");
838
839     if (!CALEIsEnableBTAdapter(env))
840     {
841         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
842         return;
843     }
844
845     // get default bt adapter class
846     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
847     if (!jni_cid_BTAdapter)
848     {
849         OIC_LOG(ERROR, TAG, "[BLE][Native] getState From BTAdapter: jni_cid_BTAdapter is null");
850         return;
851     }
852
853     // get remote bt adapter method
854     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
855                                                                     "getDefaultAdapter",
856                                                                     METHODID_OBJECTNONPARAM);
857     if (!jni_mid_getDefaultAdapter)
858     {
859         OIC_LOG(ERROR, TAG, "[BLE][Native] getState From BTAdapter: getDefaultAdapter is null");
860         return;
861     }
862
863     // get start le scan method
864     jmethodID jni_mid_stopLeScan = (*env)->GetMethodID(
865             env, jni_cid_BTAdapter, "stopLeScan",
866             "(Landroid/bluetooth/BluetoothAdapter$LeScanCallback;)V");
867     if (!jni_mid_stopLeScan)
868     {
869         OIC_LOG(ERROR, TAG, "[BLE][Native] stopLeScan: jni_mid_stopLeScan is null");
870         return;
871     }
872
873     // gat bt adapter object
874     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
875                                                                jni_mid_getDefaultAdapter);
876     if (!jni_obj_BTAdapter)
877     {
878         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_obj_BTAdapter is null");
879         return;
880     }
881
882     OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - request to stop LE Scan");
883     // call start le scan method
884     (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_stopLeScan, callback);
885 }
886
887 CAResult_t CANativeLEConnect(JNIEnv *env, jobject bluetoothDevice, jobject context,
888                              jboolean autoconnect, jobject callback)
889 {
890     if (!CALEIsEnableBTAdapter(env))
891     {
892         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
893         return CA_STATUS_FAILED;
894     }
895
896     jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
897     const char * addr = (*env)->GetStringUTFChars(env, jni_address, NULL);
898     OIC_LOG_V(DEBUG, TAG, "[BLE][Native] request connectGatt to %s", addr);
899
900     // GATT CONNECT
901
902     // get BluetoothDevice class
903     OIC_LOG(DEBUG, TAG, "[BLE][Native] get BluetoothDevice class");
904     jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, "android/bluetooth/BluetoothDevice");
905     if (!jni_cid_BluetoothDevice)
906     {
907         OIC_LOG(ERROR, TAG, "[BLE][Native] bleConnect: jni_cid_BluetoothDevice is null");
908         return CA_STATUS_FAILED;
909     }
910
911     // get connectGatt method
912     OIC_LOG(DEBUG, TAG, "[BLE][Native] get connectGatt method");
913     jmethodID jni_mid_connectGatt = (*env)->GetMethodID(
914             env, jni_cid_BluetoothDevice, "connectGatt",
915             "(Landroid/content/Context;ZLandroid/bluetooth/BluetoothGattCallback;)"
916             "Landroid/bluetooth/BluetoothGatt;");
917     if (!jni_mid_connectGatt)
918     {
919         OIC_LOG(ERROR, TAG, "[BLE][Native] bleConnect: jni_mid_connectGatt is null");
920         return CA_STATUS_FAILED;
921     }
922
923     OIC_LOG(DEBUG, TAG, "[BLE][Native] Call object method - connectGatt");
924     jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice,
925                                                            jni_mid_connectGatt,
926                                                            NULL,
927                                                            autoconnect, callback);
928     if (!jni_obj_connectGatt)
929     {
930         OIC_LOG(ERROR, TAG, "[BLE][Native] CALL API - connectGatt was failed.obj will be removed");
931         CANativeRemoveDevice(env, jni_address);
932         CANativeupdateSendCnt(env);
933         return CA_STATUS_FAILED;
934     }
935     else
936     {
937         OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - connecting..");
938     }
939     return CA_STATUS_OK;
940 }
941
942 void CANativeLEDisconnect(JNIEnv *env, jobject bluetoothGatt)
943 {
944     if (!CALEIsEnableBTAdapter(env))
945     {
946         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
947         return;
948     }
949
950     // GATT DISCONNECT
951     OIC_LOG(DEBUG, TAG, "[BLE][Native] GATT DISCONNECT");
952
953     // get BluetoothGatt class
954     OIC_LOG(DEBUG, TAG, "[BLE][Native] get BluetoothGatt classjobject bluetoothGatt");
955     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
956     if (!jni_cid_BluetoothGatt)
957     {
958         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
959         return;
960     }
961
962     OIC_LOG(DEBUG, TAG, "[BLE][Native] get gatt disconnect method");
963     jmethodID jni_mid_disconnectGatt = (*env)->GetMethodID(env, jni_cid_BluetoothGatt, "disconnect",
964                                                            "()V");
965     if (!jni_mid_disconnectGatt)
966     {
967         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_disconnectGatt is null");
968         return;
969     }
970
971     // call disconnect gatt method
972     OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - request disconnectGatt");
973     (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_disconnectGatt);
974
975 }
976
977 void CANativeLEDisconnectAll(JNIEnv *env)
978 {
979     OIC_LOG(DEBUG, TAG, "CANativeLEDisconnectAll");
980
981     if (!g_gattObjectList)
982     {
983         OIC_LOG(ERROR, TAG, "[BLE][Native] g_gattObjectList is null");
984         return;
985     }
986
987     jint index;
988     for (index = 0; index < u_arraylist_length(g_gattObjectList); index++)
989     {
990         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
991         if (!jarrayObj)
992         {
993             OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is null");
994             continue;
995         }
996         CANativeLEDisconnect(env, jarrayObj);
997     }
998
999     OICFree(g_gattObjectList);
1000     g_gattObjectList = NULL;
1001     return;
1002 }
1003
1004 void CANativeLEDiscoverServices(JNIEnv *env, jobject bluetoothGatt)
1005 {
1006     if (!CALEIsEnableBTAdapter(env))
1007     {
1008         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
1009         return;
1010     }
1011
1012     // GATT SERVICE DISCOVERY
1013     OIC_LOG(DEBUG, TAG, "[BLE][Native] GATT SERVICE DISCOVERY");
1014
1015     // get BluetoothGatt class
1016     OIC_LOG(DEBUG, TAG, "[BLE][Native] get BluetoothGatt class");
1017     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
1018     if (!jni_cid_BluetoothGatt)
1019     {
1020         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
1021         return;
1022     }
1023
1024     OIC_LOG(DEBUG, TAG, "[BLE][Native] discovery gatt services method");
1025     jmethodID jni_mid_discoverServices = (*env)->GetMethodID(env, jni_cid_BluetoothGatt,
1026                                                              "discoverServices", "()Z");
1027     if (!jni_mid_discoverServices)
1028     {
1029         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_discoverServices is null");
1030         return;
1031     }
1032     // call disconnect gatt method
1033     OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - request discovery gatt services");
1034     (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_discoverServices);
1035 }
1036
1037 CAResult_t CANativeWriteCharacteristic(JNIEnv *env, jobject bluetoothGatt,
1038                                        jobject gattCharacteristic)
1039 {
1040     if (!CALEIsEnableBTAdapter(env))
1041     {
1042         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
1043         return CA_STATUS_FAILED;
1044     }
1045
1046     // WRITE GATT CHARACTERISTIC
1047     OIC_LOG(DEBUG, TAG, "[BLE][Native] WRITE GATT CHARACTERISTIC");
1048
1049     // get BluetoothGatt class
1050     OIC_LOG(DEBUG, TAG, "[BLE][Native] get BluetoothGatt class");
1051     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
1052     if (!jni_cid_BluetoothGatt)
1053     {
1054         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
1055         return CA_STATUS_FAILED;
1056     }
1057
1058     OIC_LOG(DEBUG, TAG, "[BLE][Native] write characteristic method");
1059     jmethodID jni_mid_writeCharacteristic = (*env)->GetMethodID(
1060             env, jni_cid_BluetoothGatt, "writeCharacteristic",
1061             "(Landroid/bluetooth/BluetoothGattCharacteristic;)Z");
1062     if (!jni_mid_writeCharacteristic)
1063     {
1064         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_writeCharacteristic is null");
1065         return CA_STATUS_FAILED;
1066     }
1067
1068     // call disconnect gatt method
1069     OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - request to write gatt characteristic");
1070     jboolean ret = (jboolean)(*env)->CallBooleanMethod(env, bluetoothGatt,
1071                                                        jni_mid_writeCharacteristic,
1072                                                        gattCharacteristic);
1073     if (ret)
1074     {
1075         OIC_LOG(DEBUG, TAG, "[BLE][Native] writeCharacteristic is success");
1076     }
1077     else
1078     {
1079         OIC_LOG(ERROR, TAG, "[BLE][Native] writeCharacteristic is failed");
1080         return CA_STATUS_FAILED;
1081     }
1082     return CA_STATUS_OK;
1083 }
1084
1085 void CANativeReadCharacteristic(JNIEnv *env, jobject bluetoothGatt)
1086 {
1087
1088     if (!CALEIsEnableBTAdapter(env))
1089     {
1090         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
1091         return;
1092     }
1093
1094     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
1095     if (!jni_cid_BluetoothGatt)
1096     {
1097         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
1098         return;
1099     }
1100
1101     jstring jni_uuid = (*env)->NewStringUTF(env, IOTIVITY_GATT_RX_UUID);
1102     jobject jni_obj_GattCharacteristic = CANativeGetGattService(env, bluetoothGatt, jni_uuid);
1103     if (!jni_obj_GattCharacteristic)
1104     {
1105         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_obj_GattCharacteristic is null");
1106         return;
1107     }
1108
1109     OIC_LOG(DEBUG, TAG, "[BLE][Native] read characteristic method");
1110     jmethodID jni_mid_readCharacteristic = (*env)->GetMethodID(
1111             env, jni_cid_BluetoothGatt, "readCharacteristic",
1112             "(Landroid/bluetooth/BluetoothGattCharacteristic;)Z");
1113     if (!jni_mid_readCharacteristic)
1114     {
1115         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_readCharacteristic is null");
1116         return;
1117     }
1118
1119     // call disconnect gatt method
1120     OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - request to read gatt characteristic");
1121     jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_readCharacteristic,
1122                                              jni_obj_GattCharacteristic);
1123     if (ret)
1124     {
1125         OIC_LOG(DEBUG, TAG, "[BLE][Native] readCharacteristic is success");
1126     }
1127     else
1128     {
1129         OIC_LOG(ERROR, TAG, "[BLE][Native] readCharacteristic is failed");
1130     }
1131 }
1132
1133 CAResult_t CANativeSetCharacteristicNotification(JNIEnv *env, jobject bluetoothGatt,
1134                                                  const char* uuid)
1135 {
1136     if (!CALEIsEnableBTAdapter(env))
1137     {
1138         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
1139         return CA_ADAPTER_NOT_ENABLED;
1140     }
1141
1142     // get BluetoothGatt class
1143     OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeSetCharacteristicNotification");
1144     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
1145     if (!jni_cid_BluetoothGatt)
1146     {
1147         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
1148         return CA_STATUS_FAILED;
1149     }
1150
1151     jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
1152     jobject jni_obj_GattCharacteristic = CANativeGetGattService(env, bluetoothGatt, jni_uuid);
1153     if (!jni_obj_GattCharacteristic)
1154     {
1155         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_obj_GattCharacteristic is null");
1156         return CA_STATUS_FAILED;
1157     }
1158
1159     // set Characteristic Notification
1160     jmethodID jni_mid_setNotification = (*env)->GetMethodID(
1161             env, jni_cid_BluetoothGatt, "setCharacteristicNotification",
1162             "(Landroid/bluetooth/BluetoothGattCharacteristic;Z)Z");
1163     if (!jni_mid_setNotification)
1164     {
1165         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_getService is null");
1166         return CA_STATUS_FAILED;
1167     }
1168
1169     jboolean enable = TRUE;
1170     jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_setNotification,
1171                                              jni_obj_GattCharacteristic, enable);
1172     if (1 == ret)
1173     {
1174         OIC_LOG(DEBUG, TAG, "[BLE][Native] CALL API - setCharacteristicNotification is success");
1175         return CA_STATUS_OK;
1176     }
1177     else
1178     {
1179         OIC_LOG(ERROR, TAG, "[BLE][Native] CALL API - setCharacteristicNotification is failed");
1180         return CA_STATUS_FAILED;
1181     }
1182 }
1183
1184 jobject CANativeGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID)
1185 {
1186     if (!CALEIsEnableBTAdapter(env))
1187     {
1188         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
1189         return NULL;
1190     }
1191
1192     // get BluetoothGatt class
1193     OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeGetGattService");
1194     jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
1195     if (!jni_cid_BluetoothGatt)
1196     {
1197         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_BluetoothGatt is null");
1198         return NULL;
1199     }
1200
1201     jmethodID jni_mid_getService = (*env)->GetMethodID(
1202             env, jni_cid_BluetoothGatt, "getService",
1203             "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattService;");
1204     if (!jni_mid_getService)
1205     {
1206         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_getService is null");
1207         return NULL;
1208     }
1209
1210     jobject jni_obj_service_uuid = CANativeGetUUIDObject(env, IOTIVITY_GATT_SERVIE_UUID);
1211     if (!jni_obj_service_uuid)
1212     {
1213         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_obj_service_uuid is null");
1214         return NULL;
1215     }
1216
1217     // get bluetooth gatt service
1218     OIC_LOG(DEBUG, TAG, "[BLE][Native] request to get service");
1219     jobject jni_obj_gattService = (*env)->CallObjectMethod(env, bluetoothGatt, jni_mid_getService,
1220                                                            jni_obj_service_uuid);
1221
1222     // get bluetooth gatt service class
1223     jclass jni_cid_BluetoothGattService = (*env)->FindClass(
1224             env, "android/bluetooth/BluetoothGattService");
1225     if (!jni_cid_BluetoothGattService)
1226     {
1227         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_BluetoothGattService is null");
1228         return NULL;
1229     }
1230
1231     OIC_LOG(DEBUG, TAG, "[BLE][Native] get gatt getCharacteristic method");
1232     jmethodID jni_mid_getCharacteristic = (*env)->GetMethodID(
1233             env, jni_cid_BluetoothGattService, "getCharacteristic",
1234             "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattCharacteristic;");
1235     if (!jni_mid_getCharacteristic)
1236     {
1237         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_getCharacteristic is null");
1238         return NULL;
1239     }
1240
1241     const char* uuid = (*env)->GetStringUTFChars(env, characterUUID, NULL);
1242     jobject jni_obj_tx_uuid = CANativeGetUUIDObject(env, uuid);
1243     if (!jni_obj_tx_uuid)
1244     {
1245         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_obj_tx_uuid is null");
1246         return NULL;
1247     }
1248
1249     OIC_LOG(DEBUG, TAG, "[BLE][Native] request to get Characteristic");
1250     jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService,
1251                                                                   jni_mid_getCharacteristic,
1252                                                                   jni_obj_tx_uuid);
1253
1254     return jni_obj_GattCharacteristic;
1255 }
1256
1257 jobject CANativeCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data)
1258 {
1259     if (!CALEIsEnableBTAdapter(env))
1260     {
1261         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
1262         return NULL;
1263     }
1264
1265     OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeCreateGattCharacteristic");
1266     jstring jni_uuid = (*env)->NewStringUTF(env, IOTIVITY_GATT_TX_UUID);
1267     jobject jni_obj_GattCharacteristic = CANativeGetGattService(env, bluetoothGatt, jni_uuid);
1268     if (!jni_obj_GattCharacteristic)
1269     {
1270         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_obj_GattCharacteristic is null");
1271         return NULL;
1272     }
1273
1274     jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(
1275             env, "android/bluetooth/BluetoothGattCharacteristic");
1276     if (!jni_cid_BTGattCharacteristic)
1277     {
1278         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_BTGattCharacteristic is null");
1279         return NULL;
1280     }
1281
1282     OIC_LOG(DEBUG, TAG, "[BLE][Native] set value in Characteristic");
1283     jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "setValue",
1284                                                      "([B)Z");
1285     if (!jni_mid_setValue)
1286     {
1287         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_setValue is null");
1288         return NULL;
1289     }
1290
1291     jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue,
1292                                              data);
1293     if (1 == ret)
1294     {
1295         OIC_LOG(DEBUG, TAG, "[BLE][Native] the locally stored value has been set");
1296         return jni_obj_GattCharacteristic;
1297     }
1298     else
1299     {
1300         OIC_LOG(DEBUG, TAG, "[BLE][Native] the locally stored value hasn't been set");
1301         return NULL;
1302     }
1303 }
1304
1305 jbyteArray CANativeGetValueFromCharacteristic(JNIEnv *env, jobject characteristic)
1306 {
1307     if (!CALEIsEnableBTAdapter(env))
1308     {
1309         OIC_LOG(ERROR, TAG, "[BLE][Native] BT adpater is not enable");
1310         return NULL;
1311     }
1312
1313     jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(
1314             env, "android/bluetooth/BluetoothGattCharacteristic");
1315     if (!jni_cid_BTGattCharacteristic)
1316     {
1317         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_BTGattCharacteristic is null");
1318         return NULL;
1319     }
1320
1321     OIC_LOG(DEBUG, TAG, "[BLE][Native] get value in Characteristic");
1322     jmethodID jni_mid_getValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "getValue",
1323                                                      "()[B");
1324     if (!jni_mid_getValue)
1325     {
1326         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_mid_getValue is null");
1327         return NULL;
1328     }
1329
1330     jbyteArray jni_obj_data_array = (*env)->CallObjectMethod(env, characteristic, jni_mid_getValue);
1331     return jni_obj_data_array;
1332 }
1333
1334 void CANativeCreateUUIDList()
1335 {
1336     jboolean isAttached = FALSE;
1337     JNIEnv* env;
1338     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1339     if (res != JNI_OK)
1340     {
1341         OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
1342         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1343
1344         if (res != JNI_OK)
1345         {
1346             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
1347             return;
1348         }
1349         isAttached = TRUE;
1350     }
1351
1352     // create new object array
1353     jclass jni_cid_uuid_list = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1354     if (!jni_cid_uuid_list)
1355     {
1356         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_cid_uuid_list is null");
1357         return;
1358     }
1359
1360     jobjectArray jni_obj_uuid_list = (jobjectArray)(*env)->NewObjectArray(env, 1, jni_cid_uuid_list,
1361     NULL);
1362     if (!jni_obj_uuid_list)
1363     {
1364         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_obj_uuid_list is null");
1365         return;
1366     }
1367
1368     // remove previous list and create list again
1369     CANativeRemoveAllDevices(env);
1370     CANativeCreateScanDeviceList(env);
1371
1372     // make uuid list
1373     jobject jni_obj_uuid = CANativeGetUUIDObject(env, IOTIVITY_GATT_SERVIE_UUID);
1374     (*env)->SetObjectArrayElement(env, jni_obj_uuid_list, 0, jni_obj_uuid);
1375
1376     g_UUIDList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list);
1377
1378     if (isAttached)
1379     {
1380         (*g_jvm)->DetachCurrentThread(g_jvm);
1381     }
1382 }
1383
1384 void CANativeCreateScanDeviceList(JNIEnv *env)
1385 {
1386     OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeCreateScanDeviceList");
1387
1388     // create new object array
1389     if (g_deviceList == NULL)
1390     {
1391         OIC_LOG(DEBUG, TAG, "Create device list");
1392
1393         g_deviceList = u_arraylist_create();
1394     }
1395 }
1396
1397 void CANativeAddScanDeviceToList(JNIEnv *env, jobject device)
1398 {
1399     if (!device)
1400     {
1401         OIC_LOG(ERROR, TAG, "[BLE][Native] device is null");
1402         return;
1403     }
1404
1405     if (!g_deviceList)
1406     {
1407         OIC_LOG(ERROR, TAG, "[BLE][Native] gdevice_list is null");
1408         return;
1409     }
1410
1411     jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
1412     if (!jni_remoteAddress)
1413     {
1414         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_remoteAddress is null");
1415         return;
1416     }
1417
1418     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
1419
1420     if (!CANativeIsDeviceInList(env, remoteAddress))
1421     {
1422         jobject gdevice = (*env)->NewGlobalRef(env, device);
1423         u_arraylist_add(g_deviceList, gdevice);
1424         OIC_LOG(DEBUG, TAG, "Set Object to Array as Element");
1425     }
1426 }
1427
1428 jboolean CANativeIsDeviceInList(JNIEnv *env, const char* remoteAddress)
1429 {
1430     // get address value from device list
1431
1432     jint index;
1433     for (index = 0; index < u_arraylist_length(g_deviceList); index++)
1434     {
1435         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
1436         if (!jarrayObj)
1437         {
1438             OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is null");
1439             return TRUE;
1440         }
1441
1442         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
1443         if (!jni_setAddress)
1444         {
1445             OIC_LOG(ERROR, TAG, "[BLE][Native] jni_setAddress is null");
1446             return TRUE;
1447         }
1448
1449         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
1450
1451         if (!strcmp(remoteAddress, setAddress))
1452         {
1453             OIC_LOG(DEBUG, TAG, "the device is already set");
1454             return TRUE;
1455         }
1456     }
1457
1458     OIC_LOG(DEBUG, TAG, "there are no the device in list. we can add");
1459     return FALSE;
1460 }
1461
1462 void CANativeRemoveAllDevices(JNIEnv *env)
1463 {
1464     OIC_LOG(DEBUG, TAG, "CANativeRemoveAllDevices");
1465
1466     if (!g_deviceList)
1467     {
1468         OIC_LOG(ERROR, TAG, "[BLE][Native] g_deviceList is null");
1469         return;
1470     }
1471
1472     jint index;
1473     for (index = 0; index < u_arraylist_length(g_deviceList); index++)
1474     {
1475         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
1476         if (!jarrayObj)
1477         {
1478             OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is null");
1479             continue;
1480         }
1481         (*env)->DeleteGlobalRef(env, jarrayObj);
1482     }
1483
1484     OICFree(g_deviceList);
1485     g_deviceList = NULL;
1486     return;
1487 }
1488
1489 void CANativeRemoveDevice(JNIEnv *env, jstring address)
1490 {
1491     OIC_LOG(DEBUG, TAG, "CANativeRemoveDevice");
1492
1493     if (!g_deviceList)
1494     {
1495         OIC_LOG(ERROR, TAG, "[BLE][Native] g_deviceList is null");
1496         return;
1497     }
1498
1499     jint index;
1500     for (index = 0; index < u_arraylist_length(g_deviceList); index++)
1501     {
1502         jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
1503         if (!jarrayObj)
1504         {
1505             OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is null");
1506             return;
1507         }
1508
1509         jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
1510         if (!jni_setAddress)
1511         {
1512             OIC_LOG(ERROR, TAG, "[BLE][Native] jni_setAddress is null");
1513             return;
1514         }
1515         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
1516         const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
1517
1518         if (!strcmp(setAddress, remoteAddress))
1519         {
1520             OIC_LOG_V(DEBUG, TAG, "[BLE][Native] remove object : %s", remoteAddress);
1521             (*env)->DeleteGlobalRef(env, jarrayObj);
1522
1523             CAReorderingDeviceList(index);
1524             return;
1525         }
1526     }OIC_LOG(DEBUG, TAG, "[BLE][Native] there are no target object");
1527     return;
1528 }
1529
1530 void CAReorderingDeviceList(uint32_t index)
1531 {
1532     if (index >= g_deviceList->length)
1533     {
1534         return;
1535     }
1536
1537     if (index < g_deviceList->length - 1)
1538     {
1539         memmove(&g_deviceList->data[index], &g_deviceList->data[index + 1],
1540                 (g_deviceList->length - index - 1) * sizeof(void *));
1541     }
1542
1543     g_deviceList->size--;
1544     g_deviceList->length--;
1545 }
1546
1547 /**
1548  * Gatt Object List
1549  */
1550 void CANativeCreateGattObjList(JNIEnv *env)
1551 {
1552     OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeCreateGattObjList");
1553
1554     // create new object array
1555     if (g_gattObjectList == NULL)
1556     {
1557         OIC_LOG(DEBUG, TAG, "Create Gatt object list");
1558
1559         g_gattObjectList = u_arraylist_create();
1560     }
1561 }
1562
1563 void CANativeAddGattobjToList(JNIEnv *env, jobject gatt)
1564 {
1565     OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeAddGattobjToList");
1566
1567     if (!gatt)
1568     {
1569         OIC_LOG(ERROR, TAG, "[BLE][Native] gatt is null");
1570         return;
1571     }
1572
1573     if (!g_gattObjectList)
1574     {
1575         OIC_LOG(ERROR, TAG, "[BLE][Native] g_gattObjectList is null");
1576         return;
1577     }
1578
1579     jstring jni_remoteAddress = CANativeGetAddressFromGattObj(env, gatt);
1580     if (!jni_remoteAddress)
1581     {
1582         OIC_LOG(ERROR, TAG, "[BLE][Native] jni_remoteAddress is null");
1583         return;
1584     }
1585
1586     const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
1587
1588     if (!CANativeIsGattObjInList(env, remoteAddress))
1589     {
1590         jobject gGatt = (*env)->NewGlobalRef(env, gatt);
1591         u_arraylist_add(g_gattObjectList, gGatt);
1592         OIC_LOG(DEBUG, TAG, "Set Object to Array as Element");
1593     }
1594 }
1595
1596 jboolean CANativeIsGattObjInList(JNIEnv *env, const char* remoteAddress)
1597 {
1598     OIC_LOG(DEBUG, TAG, "[BLE][Native] CANativeIsGattObjInList");
1599
1600     jint index;
1601     for (index = 0; index < u_arraylist_length(g_gattObjectList); index++)
1602     {
1603
1604         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1605         if (!jarrayObj)
1606         {
1607             OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is null");
1608             return TRUE;
1609         }
1610
1611         jstring jni_setAddress = CANativeGetAddressFromGattObj(env, jarrayObj);
1612         if (!jni_setAddress)
1613         {
1614             OIC_LOG(ERROR, TAG, "[BLE][Native] jni_setAddress is null");
1615             return TRUE;
1616         }
1617
1618         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
1619
1620         if (!strcmp(remoteAddress, setAddress))
1621         {
1622             OIC_LOG(DEBUG, TAG, "the device is already set");
1623             return TRUE;
1624         }
1625         else
1626         {
1627             continue;
1628         }
1629     }
1630
1631     OIC_LOG(DEBUG, TAG, "there are no the gatt obejct in list. we can add");
1632     return FALSE;
1633 }
1634
1635 void CANativeRemoveAllGattObjsList(JNIEnv *env)
1636 {
1637     OIC_LOG(DEBUG, TAG, "CANativeRemoveAllGattObjsList");
1638
1639     if (!g_gattObjectList)
1640     {
1641         OIC_LOG(ERROR, TAG, "[BLE][Native] g_gattObjectList is null");
1642         return;
1643     }
1644
1645     jint index;
1646     for (index = 0; index < u_arraylist_length(g_gattObjectList); index++)
1647     {
1648         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1649         if (!jarrayObj)
1650         {
1651             OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is null");
1652             continue;
1653         }
1654         (*env)->DeleteGlobalRef(env, jarrayObj);
1655     }
1656
1657     OICFree(g_gattObjectList);
1658     g_gattObjectList = NULL;
1659     return;
1660 }
1661
1662 void CANativeRemoveGattObj(JNIEnv *env, jobject gatt)
1663 {
1664     OIC_LOG(DEBUG, TAG, "CANativeRemoveGattObj");
1665
1666     if (!g_gattObjectList)
1667     {
1668         OIC_LOG(ERROR, TAG, "[BLE][Native] g_gattObjectList is null");
1669         return;
1670     }
1671
1672     jint index;
1673     for (index = 0; index < u_arraylist_length(g_gattObjectList); index++)
1674     {
1675         jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1676         if (!jarrayObj)
1677         {
1678             OIC_LOG(ERROR, TAG, "[BLE][Native] jarrayObj is null");
1679             return;
1680         }
1681
1682         jstring jni_setAddress = CANativeGetAddressFromGattObj(env, jarrayObj);
1683         if (!jni_setAddress)
1684         {
1685             OIC_LOG(ERROR, TAG, "[BLE][Native] jni_setAddress is null");
1686             return;
1687         }
1688         const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
1689
1690         jstring jni_remoteAddress = CANativeGetAddressFromGattObj(env, gatt);
1691         if (!jni_remoteAddress)
1692         {
1693             OIC_LOG(ERROR, TAG, "[BLE][Native] jni_remoteAddress is null");
1694             return;
1695         }
1696         const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
1697
1698         if (!strcmp(setAddress, remoteAddress))
1699         {
1700             OIC_LOG_V(DEBUG, TAG, "[BLE][Native] remove object : %s", remoteAddress);
1701             (*env)->DeleteGlobalRef(env, jarrayObj);
1702
1703             CAReorderingGattList(index);
1704             return;
1705         }
1706     }OIC_LOG(DEBUG, TAG, "[BLE][Native] there are no target object");
1707     return;
1708 }
1709
1710 void CAReorderingGattList(uint32_t index)
1711 {
1712     if (index >= g_gattObjectList->length)
1713     {
1714         return;
1715     }
1716
1717     if (index < g_gattObjectList->length - 1)
1718     {
1719         memmove(&g_gattObjectList->data[index], &g_gattObjectList->data[index + 1],
1720                 (g_gattObjectList->length - index - 1) * sizeof(void *));
1721     }
1722
1723     g_gattObjectList->size--;
1724     g_gattObjectList->length--;
1725 }
1726
1727 /**
1728  * Check Sent Count for remove g_sendBuffer
1729  */
1730 void CANativeupdateSendCnt(JNIEnv *env)
1731 {
1732     // mutex lock
1733     ca_mutex_lock(g_threadMutex);
1734
1735     g_currentSentCnt++;
1736
1737     if (g_targetCnt <= g_currentSentCnt)
1738     {
1739         g_targetCnt = 0;
1740         g_currentSentCnt = 0;
1741
1742         if (g_sendBuffer)
1743         {
1744             (*env)->DeleteGlobalRef(env, g_sendBuffer);
1745             g_sendBuffer = NULL;
1746         }
1747         // notity the thread
1748         ca_cond_signal(g_threadCond);
1749         g_isFinishSendData = TRUE;
1750         OIC_LOG(DEBUG, TAG, "set signal for send data");
1751     }
1752     // mutex unlock
1753     ca_mutex_unlock(g_threadMutex);
1754 }
1755
1756 JNIEXPORT void JNICALL
1757 Java_com_iotivity_jar_caleinterface_CARegisterLeScanCallback(JNIEnv *env, jobject obj,
1758                                                              jobject callback)
1759 {
1760     OIC_LOG(DEBUG, TAG, "CARegisterLeScanCallback");
1761
1762     g_leScanCallback = (*env)->NewGlobalRef(env, callback);
1763 }
1764
1765 JNIEXPORT void JNICALL
1766 Java_com_iotivity_jar_caleinterface_CARegisterLeGattCallback(JNIEnv *env, jobject obj,
1767                                                              jobject callback)
1768 {
1769     OIC_LOG(DEBUG, TAG, "CARegisterLeGattCallback");
1770
1771     g_leGattCallback = (*env)->NewGlobalRef(env, callback);
1772 }
1773
1774 JNIEXPORT void JNICALL
1775 Java_com_iotivity_jar_caleinterface_CALeScanCallback(JNIEnv *env, jobject obj, jobject device,
1776                                                      jint rssi, jbyteArray scanRecord)
1777 {
1778     CANativeAddScanDeviceToList(env, device);
1779 }
1780
1781 /*
1782  * Class:     com_iotivity_jar_caleinterface
1783  * Method:    CALeGattConnectionStateChangeCallback
1784  * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
1785  */
1786 JNIEXPORT void JNICALL
1787 Java_com_iotivity_jar_caleinterface_CALeGattConnectionStateChangeCallback(JNIEnv *env, jobject obj,
1788                                                                           jobject gatt, jint status,
1789                                                                           jint newstate)
1790 {
1791     OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
1792             newstate);
1793
1794     if (GATT_SUCCESS == status && STATE_CONNECTED == newstate) // le connected
1795     {
1796         if (gatt)
1797         {
1798             CANativeAddGattobjToList(env, gatt);
1799             CANativeLEDiscoverServices(env, gatt);
1800         }
1801     }
1802     else if (GATT_SUCCESS == status && STATE_DISCONNECTED == newstate) // le disconnected
1803     {
1804
1805     }
1806     else // other error
1807     {
1808         CANativeSendFinish(env, gatt);
1809     }
1810 }
1811
1812 /*
1813  * Class:     com_iotivity_jar_caleinterface
1814  * Method:    CALeGattServicesDiscoveredCallback
1815  * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
1816  */
1817 JNIEXPORT void JNICALL
1818 Java_com_iotivity_jar_caleinterface_CALeGattServicesDiscoveredCallback(JNIEnv *env, jobject obj,
1819                                                                        jobject gatt, jint status)
1820 {
1821     OIC_LOG_V(DEBUG, TAG, "CALeGattServicesDiscoveredCallback - status %d: ", status);
1822
1823     if (0 != status) // discovery error
1824     {
1825         CANativeSendFinish(env, gatt);
1826         return;
1827     }
1828
1829     // read Characteristic
1830 //    CANativeReadCharacteristic(env, gatt);
1831
1832     CAResult_t ret = CANativeSetCharacteristicNotification(env, gatt, IOTIVITY_GATT_RX_UUID);
1833     if (CA_STATUS_OK != ret) // SetCharacteristicNoti is failed
1834     {
1835         CANativeSendFinish(env, gatt);
1836         return;
1837     }
1838
1839 //        jstring data = (*env)->NewStringUTF(env, "HelloWorld");
1840     jobject jni_obj_character = CANativeCreateGattCharacteristic(env, gatt, g_sendBuffer);
1841     if (!jni_obj_character)
1842     {
1843         CANativeSendFinish(env, gatt);
1844         return;
1845     }
1846
1847     sleep(1);
1848     ret = CANativeWriteCharacteristic(env, gatt, jni_obj_character);
1849     if (CA_STATUS_FAILED == ret)
1850     {
1851         CANativeSendFinish(env, gatt);
1852         return;
1853     }
1854 }
1855
1856 /*
1857  * Class:     com_iotivity_jar_caleinterface
1858  * Method:    CALeGattCharacteristicReadCallback
1859  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
1860  */
1861 JNIEXPORT void JNICALL
1862 Java_com_iotivity_jar_caleinterface_CALeGattCharacteristicReadCallback(JNIEnv *env, jobject obj,
1863                                                                        jobject gatt,
1864                                                                        jobject characteristic,
1865                                                                        jbyteArray data, jint status)
1866 {
1867     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicReadCallback - status : %d", status);
1868 }
1869
1870 /*
1871  * Class:     com_iotivity_jar_caleinterface
1872  * Method:    CALeGattCharacteristicWritjclasseCallback
1873  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
1874  */
1875 JNIEXPORT void JNICALL
1876 Java_com_iotivity_jar_caleinterface_CALeGattCharacteristicWriteCallback(JNIEnv *env, jobject obj,
1877                                                                         jobject gatt,
1878                                                                         jobject characteristic,
1879                                                                         jbyteArray data,
1880                                                                         jint status)
1881 {
1882     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
1883
1884     jstring jni_address = CANativeGetAddressFromGattObj(env, gatt);
1885     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1886
1887     jboolean isCopy;
1888     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - write data : %s",
1889             (char*)(*env)->GetByteArrayElements(env, data, &isCopy));
1890
1891 #ifdef DEBUG_MODE
1892     CANativeSendFinish(env, gatt);
1893 #endif
1894
1895     if (0 != status) // error case
1896     {
1897         CANativeSendFinish(env, gatt);
1898     }
1899 }
1900
1901 /*
1902  * Class:     com_iotivity_jar_caleinterface
1903  * Method:    CALeGattCharacteristicChangedCallback
1904  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
1905  */
1906 JNIEXPORT void JNICALL
1907 Java_com_iotivity_jar_caleinterface_CALeGattCharacteristicChangedCallback(JNIEnv *env, jobject obj,
1908                                                                           jobject gatt,
1909                                                                           jobject characteristic,
1910                                                                           jbyteArray data)
1911 {
1912     OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicChangedCallback");
1913
1914     // get Byte Array and covert to char*
1915     jint length = (*env)->GetArrayLength(env, data);
1916
1917     jboolean isCopy;
1918     jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
1919
1920     char* recevicedData = (char*) OICMalloc(sizeof(char) * length);
1921     if (NULL == recevicedData)
1922     {
1923         OIC_LOG(ERROR, TAG, "recevicedData is null");
1924         CANativeSendFinish(env, gatt);
1925
1926         return;
1927     }
1928
1929     memcpy(recevicedData, (const char*) jni_byte_responseData, length);
1930     recevicedData[length] = '\0';
1931     (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
1932
1933     jstring jni_address = CANativeGetAddressFromGattObj(env, gatt);
1934     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1935
1936     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %s, %d",
1937             recevicedData, length);
1938
1939     // callback
1940     g_packetReceiveCallback(address, recevicedData);
1941     (*env)->ReleaseStringUTFChars(env, jni_address, address);
1942
1943     // LE disconnect and finish BLE write routine
1944     CANativeSendFinish(env, gatt);
1945 }
1946
1947 /*
1948  * Class:     com_iotivity_jar_caleinterface
1949  * Method:    CALeGattDescriptorReadCallback
1950  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
1951  */
1952 JNIEXPORT void JNICALL
1953 Java_com_iotivity_jar_caleinterface_CALeGattDescriptorReadCallback(JNIEnv *env, jobject obj,
1954                                                                    jobject gatt, jobject descriptor,
1955                                                                    jint status)
1956 {
1957     OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorReadCallback - status %d: ", status);
1958 }
1959
1960 /*
1961  * Class:     com_iotivity_jar_caleinterface
1962  * Method:    CALeGattDescriptorWriteCallback
1963  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
1964  */
1965 JNIEXPORT void JNICALL
1966 Java_com_iotivity_jar_caleinterface_CALeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
1967                                                                     jobject gatt,
1968                                                                     jobject descriptor, jint status)
1969 {
1970     OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorWriteCallback - status %d: ", status);
1971 }
1972
1973 /*
1974  * Class:     com_iotivity_jar_caleinterface
1975  * Method:    CALeGattReliableWriteCompletedCallback
1976  * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
1977  */
1978 JNIEXPORT void JNICALL
1979 Java_com_iotivity_jar_caleinterface_CALeGattReliableWriteCompletedCallback(JNIEnv *env, jobject obj,
1980                                                                            jobject gatt,
1981                                                                            jint status)
1982 {
1983     OIC_LOG_V(DEBUG, TAG, "CALeGattReliableWriteCompletedCallback - status %d: ", status);
1984 }
1985
1986 /*
1987  * Class:     com_iotivity_jar_caleinterface
1988  * Method:    CALeGattReadRemoteRssiCallback
1989  * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
1990  */
1991 JNIEXPORT void JNICALL
1992 Java_com_iotivity_jar_caleinterface_CALeGattReadRemoteRssiCallback(JNIEnv *env, jobject obj,
1993                                                                    jobject gatt, jint rssi,
1994                                                                    jint status)
1995 {
1996     OIC_LOG_V(DEBUG, TAG, "CALeGattReadRemoteRssiCallback - rssi %d,  status %d: ", rssi, status);
1997 }